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 #undef _FORTIFY_SOURCE 18 #define _FORTIFY_SOURCE 2 19 #include <fcntl.h> 20 #include <netinet/in.h> 21 #include <poll.h> 22 #include <stdarg.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <sys/socket.h> 27 #include <sys/stat.h> 28 #include <time.h> 29 #include <unistd.h> 30 31 void test_sprintf() { 32 char buf[4]; 33 34 // NOLINTNEXTLINE(whitespace/line_length) 35 // GCC: warning: call to int __builtin___sprintf_chk(char*, int, {{(long )?}}unsigned int, const char*, ...) will always overflow destination buffer 36 // CLANG: error: call to unavailable function 'sprintf': format string will always overflow destination buffer 37 sprintf(buf, "foobar"); // NOLINT(runtime/printf) 38 39 // NOLINTNEXTLINE(whitespace/line_length) 40 // GCC: warning: call to int __builtin___sprintf_chk(char*, int, {{(long )?}}unsigned int, const char*, ...) will always overflow destination buffer 41 // clang should emit a warning, but doesn't 42 sprintf(buf, "%s", "foobar"); // NOLINT(runtime/printf) 43 } 44 45 void test_snprintf() { 46 char buf[4]; 47 48 // NOLINTNEXTLINE(whitespace/line_length) 49 // GCC: warning: call to int __builtin___snprintf_chk(char*, {{(long )?}}unsigned int, int, {{(long )?}}unsigned int, const char*, ...) will always overflow destination buffer 50 // CLANG: error: call to unavailable function 'snprintf': format string will always overflow destination buffer 51 snprintf(buf, 5, "foobar"); // NOLINT(runtime/printf) 52 53 // NOLINTNEXTLINE(whitespace/line_length) 54 // GCC: warning: call to int __builtin___snprintf_chk(char*, {{(long )?}}unsigned int, int, {{(long )?}}unsigned int, const char*, ...) will always overflow destination buffer 55 // clang should emit a warning, but doesn't 56 snprintf(buf, 5, "%s", "foobar"); // NOLINT(runtime/printf) 57 58 // NOLINTNEXTLINE(whitespace/line_length) 59 // GCC: warning: call to int __builtin___snprintf_chk(char*, {{(long )?}}unsigned int, int, {{(long )?}}unsigned int, const char*, ...) will always overflow destination buffer 60 // clang should emit a warning, but doesn't 61 snprintf(buf, 5, " %s ", "foobar"); // NOLINT(runtime/printf) 62 63 // NOLINTNEXTLINE(whitespace/line_length) 64 // GCC: warning: call to int __builtin___snprintf_chk(char*, {{(long )?}}unsigned int, int, {{(long )?}}unsigned int, const char*, ...) will always overflow destination buffer 65 // clang should emit a warning, but doesn't 66 snprintf(buf, 5, "%d", 100000); // NOLINT(runtime/printf) 67 } 68 69 void test_memcpy() { 70 char buf[4]; 71 72 // NOLINTNEXTLINE(whitespace/line_length) 73 // GCC: warning: call to void* __builtin___memcpy_chk(void*, const void*, {{(long )?}}unsigned int, {{(long )?}}unsigned int) will always overflow destination buffer 74 // CLANG: error: call to unavailable function 'memcpy': memcpy called with size bigger than buffer 75 memcpy(buf, "foobar", sizeof("foobar") + 100); 76 } 77 78 void test_memmove() { 79 char buf[4]; 80 81 // NOLINTNEXTLINE(whitespace/line_length) 82 // GCC: warning: call to void* __builtin___memmove_chk(void*, const void*, {{(long )?}}unsigned int, {{(long )?}}unsigned int) will always overflow destination buffer 83 // CLANG: error: call to unavailable function 'memmove': memmove called with size bigger than buffer 84 memmove(buf, "foobar", sizeof("foobar")); 85 } 86 87 void test_memset() { 88 char buf[4]; 89 90 // NOLINTNEXTLINE(whitespace/line_length) 91 // GCC: warning: call to void* __builtin___memset_chk(void*, int, {{(long )?}}unsigned int, {{(long )?}}unsigned int) will always overflow destination buffer 92 // CLANG: error: call to unavailable function 'memset': memset called with size bigger than buffer 93 memset(buf, 0, 6); 94 } 95 96 void test_strcpy() { 97 char buf[4]; 98 99 // NOLINTNEXTLINE(whitespace/line_length) 100 // 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 101 // CLANG: error: call to unavailable function 'strcpy': strcpy called with string bigger than buffer 102 strcpy(buf, "foobar"); // NOLINT(runtime/printf) 103 } 104 105 void test_stpcpy() { 106 char buf[4]; 107 108 // NOLINTNEXTLINE(whitespace/line_length) 109 // GCC: warning: call to char* __builtin___stpcpy_chk(char*, const char*, {{(long )?}}unsigned int) will always overflow destination buffer 110 // CLANG: error: call to unavailable function 'stpcpy': stpcpy called with string bigger than buffer 111 stpcpy(buf, "foobar"); 112 } 113 114 void test_strncpy() { 115 char buf[4]; 116 117 // NOLINTNEXTLINE(whitespace/line_length) 118 // GCC: warning: call to char* __builtin___strncpy_chk(char*, const char*, {{(long )?}}unsigned int, {{(long )?}}unsigned int) will always overflow destination buffer 119 // clang should emit a warning, but doesn't 120 strncpy(buf, "foobar", sizeof("foobar")); 121 } 122 123 void test_strcat() { 124 char buf[4] = ""; 125 126 // NOLINTNEXTLINE(whitespace/line_length) 127 // 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 128 // clang should emit a warning, but doesn't 129 strcat(buf, "foobar"); // NOLINT(runtime/printf) 130 } 131 132 void test_strncat() { 133 char buf[4] = ""; 134 135 // NOLINTNEXTLINE(whitespace/line_length) 136 // 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 137 // gcc output warning with __builtin___strcat_chk for __builtin___strncat_chk. 138 // clang should emit a warning, but doesn't 139 strncat(buf, "foobar", sizeof("foobar")); 140 } 141 142 void test_vsprintf(const char* fmt, ...) { 143 va_list va; 144 char buf[4]; 145 va_start(va, fmt); 146 147 // NOLINTNEXTLINE(whitespace/line_length) 148 // 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 149 // clang should emit a warning, but doesn't 150 vsprintf(buf, "foobar", va); 151 va_end(va); 152 } 153 154 void test_vsnprintf(const char* fmt, ...) { 155 va_list va; 156 char buf[4]; 157 va_start(va, fmt); 158 159 // NOLINTNEXTLINE(whitespace/line_length) 160 // 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 161 // clang should emit a warning, but doesn't 162 vsnprintf(buf, 5, "foobar", va); // NOLINT(runtime/printf) 163 164 va_end(va); 165 } 166 167 void test_fgets() { 168 char buf[4]; 169 170 // NOLINTNEXTLINE(whitespace/line_length) 171 // GCC: error: call to '__fgets_too_small_error' declared with attribute error: fgets called with size less than zero 172 // CLANG: error: call to unavailable function 'fgets': size is negative 173 fgets(buf, -1, stdin); 174 175 // NOLINTNEXTLINE(whitespace/line_length) 176 // GCC: error: call to '__fgets_too_big_error' declared with attribute error: fgets called with size bigger than buffer 177 // CLANG: error: call to unavailable function 'fgets': size is larger than the destination buffer 178 fgets(buf, 6, stdin); 179 } 180 181 void test_recvfrom() { 182 char buf[4]; 183 sockaddr_in addr; 184 185 // NOLINTNEXTLINE(whitespace/line_length) 186 // GCC: error: call to '__recvfrom_error' declared with attribute error: recvfrom called with size bigger than buffer 187 // CLANG: error: call to unavailable function 'recvfrom': recvfrom called with size bigger than buffer 188 recvfrom(0, buf, 6, 0, reinterpret_cast<sockaddr*>(&addr), NULL); 189 } 190 191 void test_umask() { 192 // NOLINTNEXTLINE(whitespace/line_length) 193 // GCC: error: call to '__umask_invalid_mode' declared with attribute error: umask called with invalid mode 194 // CLANG: error: call to unavailable function 'umask': umask called with invalid mode 195 umask(01777); 196 } 197 198 void test_read() { 199 char buf[4]; 200 // NOLINTNEXTLINE(whitespace/line_length) 201 // GCC: error: call to '__read_dest_size_error' declared with attribute error: read called with size bigger than destination 202 // CLANG: error: call to unavailable function 'read': 'count' bytes overflows the given object 203 read(0, buf, 6); 204 } 205 206 void test_open() { 207 // NOLINTNEXTLINE(whitespace/line_length) 208 // GCC: error: call to '__creat_missing_mode' declared with attribute error: called with O_CREAT, but missing mode 209 // CLANG: error: call to unavailable function 'open': called with O_CREAT, but missing mode 210 open("/dev/null", O_CREAT); 211 212 // NOLINTNEXTLINE(whitespace/line_length) 213 // GCC: error: call to '__creat_too_many_args' declared with attribute error: too many arguments 214 // CLANG: error: call to unavailable function 'open': too many arguments 215 open("/dev/null", O_CREAT, 0, 0); 216 } 217 218 void test_poll() { 219 pollfd fds[1]; 220 // NOLINTNEXTLINE(whitespace/line_length) 221 // GCC: error: call to '__poll_too_small_error' declared with attribute error: poll: pollfd array smaller than fd count 222 // CLANG: error: call to unavailable function 'poll': too many fds specified 223 poll(fds, 2, 0); 224 } 225 226 void test_ppoll() { 227 pollfd fds[1]; 228 timespec timeout; 229 // NOLINTNEXTLINE(whitespace/line_length) 230 // GCC: error: call to '__ppoll_too_small_error' declared with attribute error: ppoll: pollfd array smaller than fd count 231 // CLANG: error: call to unavailable function 'ppoll': too many fds specified 232 ppoll(fds, 2, &timeout, NULL); 233 } 234 235 void test_fread_overflow() { 236 char buf[4]; 237 // NOLINTNEXTLINE(whitespace/line_length) 238 // GCC: error: call to '__fread_overflow' declared with attribute error: fread called with overflowing size * count 239 // CLANG: error: call to unavailable function 'fread': size * count overflows 240 fread(buf, 2, (size_t)-1, stdin); 241 } 242 243 void test_fread_too_big() { 244 char buf[4]; 245 // NOLINTNEXTLINE(whitespace/line_length) 246 // GCC: error: call to '__fread_too_big_error' declared with attribute error: fread called with size * count bigger than buffer 247 // CLANG: error: call to unavailable function 'fread': size * count is too large 248 fread(buf, 1, 5, stdin); 249 } 250 251 void test_fwrite_overflow() { 252 char buf[4] = {0}; 253 // NOLINTNEXTLINE(whitespace/line_length) 254 // GCC: error: call to '__fwrite_overflow' declared with attribute error: fwrite called with overflowing size * count 255 // CLANG: error: call to unavailable function 'fwrite': size * count overflows 256 fwrite(buf, 2, (size_t)-1, stdout); 257 } 258 259 void test_fwrite_too_big() { 260 char buf[4] = {0}; 261 // NOLINTNEXTLINE(whitespace/line_length) 262 // GCC: error: call to '__fwrite_too_big_error' declared with attribute error: fwrite called with size * count bigger than buffer 263 // CLANG: error: call to unavailable function 'fwrite': size * count is too large 264 fwrite(buf, 1, 5, stdout); 265 } 266 267 void test_getcwd() { 268 char buf[4]; 269 // NOLINTNEXTLINE(whitespace/line_length) 270 // GCC: error: call to '__getcwd_dest_size_error' declared with attribute error: getcwd called with size bigger than destination 271 // CLANG: error: call to unavailable function 'getcwd': 'size' bytes overflows the given object 272 getcwd(buf, 5); 273 } 274 275 void test_pwrite64_size() { 276 char buf[4] = {0}; 277 // NOLINTNEXTLINE(whitespace/line_length) 278 // GCC: error: call to '__pwrite64_dest_size_error' declared with attribute error: pwrite64 called with size bigger than destination 279 // CLANG: error: call to unavailable function 'pwrite64': 'count' bytes overflows the given object 280 pwrite64(STDOUT_FILENO, buf, 5, 0); 281 } 282 283 void test_pwrite64_too_big_malloc() { 284 void *buf = calloc(atoi("5"), 1); 285 // NOLINTNEXTLINE(whitespace/line_length) 286 // GCC: error: call to '__pwrite64_count_toobig_error' declared with attribute error: pwrite64 called with count > SSIZE_MAX 287 // clang should emit a warning, but probably never will. 288 pwrite64(STDOUT_FILENO, buf, SIZE_MAX, 0); 289 } 290 291 void test_pwrite64_too_big() { 292 char buf[4] = {0}; 293 // NOLINTNEXTLINE(whitespace/line_length) 294 // GCC: error: call to '__pwrite64_count_toobig_error' declared with attribute error: pwrite64 called with count > SSIZE_MAX 295 // CLANG: error: call to unavailable function 'pwrite64': count must be <= SSIZE_MAX 296 pwrite64(STDOUT_FILENO, buf, SIZE_MAX, 0); 297 } 298 299 void test_write_size() { 300 char buf[4] = {0}; 301 // NOLINTNEXTLINE(whitespace/line_length) 302 // GCC: error: call to '__write_dest_size_error' declared with attribute error: write called with size bigger than destination 303 // CLANG: error: call to unavailable function 'write': 'count' bytes overflows the given object 304 write(STDOUT_FILENO, buf, 5); 305 } 306 307 void test_memset_args_flipped() { 308 char from[4] = {0}; 309 // NOLINTNEXTLINE(whitespace/line_length) 310 // CLANG: 'memset' is deprecated: will set 0 bytes; maybe the arguments got flipped? (Add __bionic_zero_size_is_okay as a fourth argument to silence this.) 311 memset(from, sizeof(from), 0); 312 } 313 314 void test_sendto() { 315 char buf[4] = {0}; 316 sockaddr_in addr; 317 318 // NOLINTNEXTLINE(whitespace/line_length) 319 // GCC: error: call to '__sendto_error' declared with attribute error: sendto called with size bigger than buffer 320 // CLANG: error: call to unavailable function 'sendto': sendto called with size bigger than buffer 321 sendto(0, buf, 6, 0, reinterpret_cast<sockaddr*>(&addr), sizeof(sockaddr_in)); 322 } 323 324 void test_send() { 325 char buf[4] = {0}; 326 327 // NOLINTNEXTLINE(whitespace/line_length) 328 // GCC: error: call to '__sendto_error' declared with attribute error: sendto called with size bigger than buffer 329 // CLANG: error: call to unavailable function 'send': send called with size bigger than buffer 330 send(0, buf, 6, 0); 331 } 332