Home | History | Annotate | Download | only in tests
      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