1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* 18 * If this test fails, you can see the compiler's output by erasing a few args from the failing 19 * command. Specifically, delete everything before the path/to/the/compiler, then delete the first 20 * arg after the path/to/the/compiler. For example, given the following command: 21 * 22 * bionic/tests/file-check-cxx out/host/linux-x86/bin/FileCheck \ 23 * prebuilts/clang/host/linux-x86/clang-4053586/bin/clang++ CLANG -I bionic/tests -I ... 24 * 25 * If you delete everything before clang++ and delete "CLANG" (or "GCC" if gcc is failing), then 26 * you'll end up with: 27 * 28 * prebuilts/clang/host/linux-x86/clang-4053586/bin/clang++ -I bionic/tests -I ... 29 * 30 * Which is the command that FileCheck executes. 31 */ 32 33 #undef _FORTIFY_SOURCE 34 #define _FORTIFY_SOURCE 2 35 #include <fcntl.h> 36 #include <netinet/in.h> 37 #include <poll.h> 38 #include <stdarg.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <sys/socket.h> 43 #include <sys/stat.h> 44 #include <time.h> 45 #include <unistd.h> 46 47 void test_sprintf() { 48 char buf[4]; 49 50 // NOLINTNEXTLINE(whitespace/line_length) 51 // GCC: warning: call to int __builtin___sprintf_chk(char*, int, {{(long )?}}unsigned int, const char*, ...) will always overflow destination buffer 52 // CLANG: error: call to unavailable function 'sprintf': format string will always overflow destination buffer 53 sprintf(buf, "foobar"); // NOLINT(runtime/printf) 54 55 // NOLINTNEXTLINE(whitespace/line_length) 56 // GCC: warning: call to int __builtin___sprintf_chk(char*, int, {{(long )?}}unsigned int, const char*, ...) will always overflow destination buffer 57 // clang should emit a warning, but doesn't 58 sprintf(buf, "%s", "foobar"); // NOLINT(runtime/printf) 59 } 60 61 void test_snprintf() { 62 char buf[4]; 63 64 // NOLINTNEXTLINE(whitespace/line_length) 65 // GCC: warning: call to int __builtin___snprintf_chk(char*, {{(long )?}}unsigned int, int, {{(long )?}}unsigned int, const char*, ...) will always overflow destination buffer 66 // CLANG: error: call to unavailable function 'snprintf': format string will always overflow destination buffer 67 snprintf(buf, 5, "foobar"); // NOLINT(runtime/printf) 68 69 // NOLINTNEXTLINE(whitespace/line_length) 70 // GCC: warning: call to int __builtin___snprintf_chk(char*, {{(long )?}}unsigned int, int, {{(long )?}}unsigned int, const char*, ...) will always overflow destination buffer 71 // clang should emit a warning, but doesn't 72 snprintf(buf, 5, "%s", "foobar"); // NOLINT(runtime/printf) 73 74 // NOLINTNEXTLINE(whitespace/line_length) 75 // GCC: warning: call to int __builtin___snprintf_chk(char*, {{(long )?}}unsigned int, int, {{(long )?}}unsigned int, const char*, ...) will always overflow destination buffer 76 // clang should emit a warning, but doesn't 77 snprintf(buf, 5, " %s ", "foobar"); // NOLINT(runtime/printf) 78 79 // NOLINTNEXTLINE(whitespace/line_length) 80 // GCC: warning: call to int __builtin___snprintf_chk(char*, {{(long )?}}unsigned int, int, {{(long )?}}unsigned int, const char*, ...) will always overflow destination buffer 81 // clang should emit a warning, but doesn't 82 snprintf(buf, 5, "%d", 100000); // NOLINT(runtime/printf) 83 } 84 85 void test_memcpy() { 86 char buf[4]; 87 88 // NOLINTNEXTLINE(whitespace/line_length) 89 // GCC: warning: call to void* __builtin___memcpy_chk(void*, const void*, {{(long )?}}unsigned int, {{(long )?}}unsigned int) will always overflow destination buffer 90 // CLANG: error: 'memcpy' called with size bigger than buffer 91 memcpy(buf, "foobar", sizeof("foobar") + 100); 92 } 93 94 void test_memmove() { 95 char buf[4]; 96 97 // NOLINTNEXTLINE(whitespace/line_length) 98 // GCC: warning: call to void* __builtin___memmove_chk(void*, const void*, {{(long )?}}unsigned int, {{(long )?}}unsigned int) will always overflow destination buffer 99 // CLANG: error: 'memmove' called with size bigger than buffer 100 memmove(buf, "foobar", sizeof("foobar")); 101 } 102 103 void test_memset() { 104 char buf[4]; 105 106 // NOLINTNEXTLINE(whitespace/line_length) 107 // GCC: warning: call to void* __builtin___memset_chk(void*, int, {{(long )?}}unsigned int, {{(long )?}}unsigned int) will always overflow destination buffer 108 // CLANG: error: 'memset' called with size bigger than buffer 109 memset(buf, 0, 6); 110 } 111 112 void test_strcpy() { 113 char buf[4]; 114 115 // NOLINTNEXTLINE(whitespace/line_length) 116 // GCC: warning: call to {{(char\* __builtin___strcpy_chk\(char\*, const char\*, unsigned int\))|(void\* __builtin___memcpy_chk\(void\*, const void\*, (long )?unsigned int, (long )?unsigned int\))}} will always overflow destination buffer 117 // CLANG: error: 'strcpy' called with string bigger than buffer 118 strcpy(buf, "foobar"); // NOLINT(runtime/printf) 119 120 // NOLINTNEXTLINE(whitespace/line_length) 121 // GCC: warning: call to {{(char\* __builtin___strcpy_chk\(char\*, const char\*, unsigned int\))|(void\* __builtin___memcpy_chk\(void\*, const void\*, (long )?unsigned int, (long )?unsigned int\))}} will always overflow destination buffer 122 // CLANG: error: 'strcpy' called with string bigger than buffer 123 strcpy(buf, "quux"); 124 } 125 126 void test_stpcpy() { 127 char buf[4]; 128 129 // NOLINTNEXTLINE(whitespace/line_length) 130 // GCC: warning: call to char* __builtin___stpcpy_chk(char*, const char*, {{(long )?}}unsigned int) will always overflow destination buffer 131 // CLANG: error: 'stpcpy' called with string bigger than buffer 132 stpcpy(buf, "foobar"); 133 134 // NOLINTNEXTLINE(whitespace/line_length) 135 // GCC: warning: call to char* __builtin___stpcpy_chk(char*, const char*, {{(long )?}}unsigned int) will always overflow destination buffer 136 // CLANG: error: 'stpcpy' called with string bigger than buffer 137 stpcpy(buf, "quux"); 138 } 139 140 void test_strncpy() { 141 char buf[4]; 142 143 // NOLINTNEXTLINE(whitespace/line_length) 144 // GCC: warning: call to char* __builtin___strncpy_chk(char*, const char*, {{(long )?}}unsigned int, {{(long )?}}unsigned int) will always overflow destination buffer 145 // clang should emit a warning, but doesn't 146 strncpy(buf, "foobar", sizeof("foobar")); 147 } 148 149 void test_strcat() { 150 char buf[4] = ""; 151 152 // NOLINTNEXTLINE(whitespace/line_length) 153 // GCC: warning: call to {{(char\* __builtin___strcat_chk\(char\*, const char\*, unsigned int\))|(void\* __builtin___memcpy_chk\(void\*, const void\*, (long )?unsigned int, (long )?unsigned int\))}} will always overflow destination buffer 154 // clang should emit a warning, but doesn't 155 strcat(buf, "foobar"); // NOLINT(runtime/printf) 156 } 157 158 void test_strncat() { 159 char buf[4] = ""; 160 161 // NOLINTNEXTLINE(whitespace/line_length) 162 // GCC: warning: call to {{(char\* __builtin___strcat_chk\(char\*, const char\*, unsigned int\))|(void\* __builtin___memcpy_chk\(void\*, const void\*, (long )?unsigned int, (long )?unsigned int\))}} will always overflow destination buffer 163 // gcc output warning with __builtin___strcat_chk for __builtin___strncat_chk. 164 // clang should emit a warning, but doesn't 165 strncat(buf, "foobar", sizeof("foobar")); 166 } 167 168 void test_vsprintf(const char* fmt, ...) { 169 va_list va; 170 char buf[4]; 171 va_start(va, fmt); 172 173 // NOLINTNEXTLINE(whitespace/line_length) 174 // GCC: warning: call to int __builtin___vsprintf_chk(char*, int, {{(long )?}}unsigned int, const char*, {{(__va_list)|(void\*)|(char\*)|(__va_list_tag\*)}}) will always overflow destination buffer 175 // clang should emit a warning, but doesn't 176 vsprintf(buf, "foobar", va); 177 va_end(va); 178 } 179 180 void test_vsnprintf(const char* fmt, ...) { 181 va_list va; 182 char buf[4]; 183 va_start(va, fmt); 184 185 // NOLINTNEXTLINE(whitespace/line_length) 186 // GCC: warning: call to int __builtin___vsnprintf_chk(char*, {{(long )?}}unsigned int, int, {{(long )?}}unsigned int, const char*, {{(__va_list)|(void\*)|(char\*)|(__va_list_tag\*)}}) will always overflow destination buffer 187 // clang should emit a warning, but doesn't 188 vsnprintf(buf, 5, "foobar", va); // NOLINT(runtime/printf) 189 190 va_end(va); 191 } 192 193 void test_fgets() { 194 char buf[4]; 195 196 // NOLINTNEXTLINE(whitespace/line_length) 197 // GCC: error: call to '__fgets_too_small_error' declared with attribute error: fgets called with size less than zero 198 // CLANG: error: in call to 'fgets', size should not be negative 199 fgets(buf, -1, stdin); 200 201 // NOLINTNEXTLINE(whitespace/line_length) 202 // GCC: error: call to '__fgets_too_big_error' declared with attribute error: fgets called with size bigger than buffer 203 // CLANG: error: in call to 'fgets', size is larger than the destination buffer 204 fgets(buf, 6, stdin); 205 } 206 207 void test_recvfrom() { 208 char buf[4]; 209 sockaddr_in addr; 210 211 // NOLINTNEXTLINE(whitespace/line_length) 212 // GCC: error: call to '__recvfrom_error' declared with attribute error: 'recvfrom' called with size bigger than buffer 213 // CLANG: error: 'recvfrom' called with size bigger than buffer 214 recvfrom(0, buf, 6, 0, reinterpret_cast<sockaddr*>(&addr), NULL); 215 } 216 217 void test_recv() { 218 char buf[4] = {0}; 219 220 // NOLINTNEXTLINE(whitespace/line_length) 221 // GCC: error: call to '__recvfrom_error' declared with attribute error: 'recvfrom' called with size bigger than buffer 222 // CLANG: error: 'recv' called with size bigger than buffer 223 recv(0, buf, 6, 0); 224 } 225 226 void test_umask() { 227 // NOLINTNEXTLINE(whitespace/line_length) 228 // GCC: error: call to '__umask_invalid_mode' declared with attribute error: 'umask' called with invalid mode 229 // CLANG: error: 'umask' called with invalid mode 230 umask(01777); 231 } 232 233 void test_read() { 234 char buf[4]; 235 // NOLINTNEXTLINE(whitespace/line_length) 236 // GCC: error: call to '__read_dest_size_error' declared with attribute error: read called with size bigger than destination 237 // CLANG: error: in call to 'read', 'count' bytes overflows the given object 238 read(0, buf, 6); 239 } 240 241 void test_open() { 242 // NOLINTNEXTLINE(whitespace/line_length) 243 // GCC: error: call to '__creat_missing_mode' declared with attribute error: called with O_CREAT or O_TMPFILE, but missing mode 244 // CLANG: error: 'open' called with O_CREAT or O_TMPFILE, but missing mode 245 open("/dev/null", O_CREAT); 246 247 // GCC: error: call to '__creat_missing_mode' declared with attribute error: called with O_CREAT or O_TMPFILE, but missing mode 248 // CLANG: error: 'open' called with O_CREAT or O_TMPFILE, but missing mode 249 open("/dev/null", O_TMPFILE); 250 251 // NOLINTNEXTLINE(whitespace/line_length) 252 // GCC: error: call to '__creat_too_many_args' declared with attribute error: too many arguments 253 // CLANG: error: call to unavailable function 'open': too many arguments 254 open("/dev/null", O_CREAT, 0, 0); 255 256 // GCC: error: call to '__creat_too_many_args' declared with attribute error: too many arguments 257 // CLANG: error: call to unavailable function 'open': too many arguments 258 open("/dev/null", O_TMPFILE, 0, 0); 259 260 // CLANG: warning: 'open' has superfluous mode bits; missing O_CREAT? 261 open("/dev/null", O_RDONLY, 0644); 262 263 // CLANG: warning: 'open' has superfluous mode bits; missing O_CREAT? 264 open("/dev/null", O_DIRECTORY, 0644); 265 } 266 267 void test_poll() { 268 pollfd fds[1]; 269 // NOLINTNEXTLINE(whitespace/line_length) 270 // GCC: error: call to '__poll_too_small_error' declared with attribute error: poll: pollfd array smaller than fd count 271 // CLANG: error: in call to 'poll', fd_count is larger than the given buffer 272 poll(fds, 2, 0); 273 } 274 275 void test_ppoll() { 276 pollfd fds[1]; 277 timespec timeout; 278 // NOLINTNEXTLINE(whitespace/line_length) 279 // GCC: error: call to '__ppoll_too_small_error' declared with attribute error: ppoll: pollfd array smaller than fd count 280 // CLANG: error: in call to 'ppoll', fd_count is larger than the given buffer 281 ppoll(fds, 2, &timeout, NULL); 282 } 283 284 void test_fread_overflow() { 285 char buf[4]; 286 // NOLINTNEXTLINE(whitespace/line_length) 287 // GCC: error: call to '__fread_overflow' declared with attribute error: fread called with overflowing size * count 288 // CLANG: error: in call to 'fread', size * count overflows 289 fread(buf, 2, (size_t)-1, stdin); 290 } 291 292 void test_fread_too_big() { 293 char buf[4]; 294 // NOLINTNEXTLINE(whitespace/line_length) 295 // GCC: error: call to '__fread_too_big_error' declared with attribute error: fread called with size * count bigger than buffer 296 // NOLINTNEXTLINE(whitespace/line_length) 297 // CLANG: error: in call to 'fread', size * count is too large for the given buffer 298 fread(buf, 1, 5, stdin); 299 } 300 301 void test_fwrite_overflow() { 302 char buf[4] = {0}; 303 // NOLINTNEXTLINE(whitespace/line_length) 304 // GCC: error: call to '__fwrite_overflow' declared with attribute error: fwrite called with overflowing size * count 305 // CLANG: error: in call to 'fwrite', size * count overflows 306 fwrite(buf, 2, (size_t)-1, stdout); 307 } 308 309 void test_fwrite_too_big() { 310 char buf[4] = {0}; 311 // NOLINTNEXTLINE(whitespace/line_length) 312 // GCC: error: call to '__fwrite_too_big_error' declared with attribute error: fwrite called with size * count bigger than buffer 313 // NOLINTNEXTLINE(whitespace/line_length) 314 // CLANG: error: in call to 'fwrite', size * count is too large for the given buffer 315 fwrite(buf, 1, 5, stdout); 316 } 317 318 void test_getcwd() { 319 char buf[4]; 320 // NOLINTNEXTLINE(whitespace/line_length) 321 // GCC: error: call to '__getcwd_dest_size_error' declared with attribute error: getcwd called with size bigger than destination 322 // CLANG: error: in call to 'getcwd', 'size' bytes overflows the given object 323 getcwd(buf, 5); 324 } 325 326 void test_pwrite64_size() { 327 char buf[4] = {0}; 328 // NOLINTNEXTLINE(whitespace/line_length) 329 // GCC: error: call to '__pwrite64_dest_size_error' declared with attribute error: pwrite64 called with size bigger than destination 330 // CLANG: error: in call to 'pwrite64', 'count' bytes overflows the given object 331 pwrite64(STDOUT_FILENO, buf, 5, 0); 332 } 333 334 void test_pwrite64_too_big_malloc() { 335 void *buf = calloc(atoi("5"), 1); 336 // NOLINTNEXTLINE(whitespace/line_length) 337 // GCC: error: call to '__pwrite64_count_toobig_error' declared with attribute error: pwrite64 called with count > SSIZE_MAX 338 // clang should emit a warning, but probably never will. 339 pwrite64(STDOUT_FILENO, buf, SIZE_MAX, 0); 340 } 341 342 void test_pwrite64_too_big() { 343 char buf[4] = {0}; 344 // NOLINTNEXTLINE(whitespace/line_length) 345 // GCC: error: call to '__pwrite64_count_toobig_error' declared with attribute error: pwrite64 called with count > SSIZE_MAX 346 // CLANG: error: in call to 'pwrite64', 'count' must be <= SSIZE_MAX 347 pwrite64(STDOUT_FILENO, buf, SIZE_MAX, 0); 348 } 349 350 void test_write_size() { 351 char buf[4] = {0}; 352 // NOLINTNEXTLINE(whitespace/line_length) 353 // GCC: error: call to '__write_dest_size_error' declared with attribute error: write called with size bigger than destination 354 // CLANG: error: in call to 'write', 'count' bytes overflows the given object 355 write(STDOUT_FILENO, buf, 5); 356 } 357 358 void test_memset_args_flipped() { 359 char from[4] = {0}; 360 // NOLINTNEXTLINE(whitespace/line_length) 361 // CLANG: 'memset' will set 0 bytes; maybe the arguments got flipped? 362 memset(from, sizeof(from), 0); 363 } 364 365 void test_sendto() { 366 char buf[4] = {0}; 367 sockaddr_in addr; 368 369 // NOLINTNEXTLINE(whitespace/line_length) 370 // GCC: error: call to '__sendto_error' declared with attribute error: 'sendto' called with size bigger than buffer 371 // CLANG: error: 'sendto' called with size bigger than buffer 372 sendto(0, buf, 6, 0, reinterpret_cast<sockaddr*>(&addr), sizeof(sockaddr_in)); 373 } 374 375 void test_send() { 376 char buf[4] = {0}; 377 378 // NOLINTNEXTLINE(whitespace/line_length) 379 // GCC: error: call to '__sendto_error' declared with attribute error: 'sendto' called with size bigger than buffer 380 // CLANG: error: 'send' called with size bigger than buffer 381 send(0, buf, 6, 0); 382 } 383 384 void test_realpath() { 385 char buf[4] = {0}; 386 // NOLINTNEXTLINE(whitespace/line_length) 387 // GCC: error: call to '__realpath_size_error' declared with attribute error: 'realpath' output parameter must be NULL or a pointer to a buffer with >= PATH_MAX bytes 388 // NOLINTNEXTLINE(whitespace/line_length) 389 // CLANG: error: 'realpath' output parameter must be NULL or a pointer to a buffer with >= PATH_MAX bytes 390 realpath(".", buf); 391 392 // This is fine. 393 realpath(".", NULL); 394 395 char bigbuf[PATH_MAX]; 396 // CLANG: error: 'realpath': NULL path is never correct; flipped arguments? 397 realpath(NULL, bigbuf); 398 } 399