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
31void 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 should emit a warning, but doesn't
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
45void 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 should emit a warning, but doesn't
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
69void 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 should emit a warning, but doesn't
75  memcpy(buf, "foobar", sizeof("foobar"));
76}
77
78void 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 should emit a warning, but doesn't
84  memmove(buf, "foobar", sizeof("foobar"));
85}
86
87void 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 should emit a warning, but doesn't
93  memset(buf, 0, 6);
94}
95
96void 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 should emit a warning, but doesn't
102  strcpy(buf, "foobar");  // NOLINT(runtime/printf)
103}
104
105void 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 should emit a warning, but doesn't
111  stpcpy(buf, "foobar");
112}
113
114void 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
123void 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
132void 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
142void 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
154void 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
167void 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 should emit a warning, but doesn't
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 should emit a warning, but doesn't
178  fgets(buf, 6, stdin);
179}
180
181void 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 should emit a warning, but doesn't
188  recvfrom(0, buf, 6, 0, reinterpret_cast<sockaddr*>(&addr), NULL);
189}
190
191void 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 should emit a warning, but doesn't
195  umask(01777);
196}
197
198void 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 should emit a warning, but doesn't
203  read(0, buf, 6);
204}
205
206void 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 should emit a warning, but doesn't
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 should emit a warning, but doesn't
215  open("/dev/null", O_CREAT, 0, 0);
216}
217
218void 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 should emit a warning, but doesn't
223  poll(fds, 2, 0);
224}
225
226void 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 should emit a warning, but doesn't
232  ppoll(fds, 2, &timeout, NULL);
233}
234
235void 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 should emit a warning, but doesn't
240  fread(buf, 2, (size_t)-1, stdin);
241}
242
243void 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 should emit a warning, but doesn't
248  fread(buf, 1, 5, stdin);
249}
250
251void 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 should emit a warning, but doesn't
256  fwrite(buf, 2, (size_t)-1, stdout);
257}
258
259void 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 should emit a warning, but doesn't
264  fwrite(buf, 1, 5, stdout);
265}
266
267void 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 should emit a warning, but doesn't
272  getcwd(buf, 5);
273}
274
275void 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 should emit a warning, but doesn't
280  pwrite64(STDOUT_FILENO, buf, 5, 0);
281}
282
283void test_pwrite64_too_big() {
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 doesn't
288  pwrite64(STDOUT_FILENO, buf, SIZE_MAX, 0);
289}
290
291void test_write_size() {
292  char buf[4] = {0};
293  // NOLINTNEXTLINE(whitespace/line_length)
294  // GCC: error: call to '__write_dest_size_error' declared with attribute error: write called with size bigger than destination
295  // clang should emit a warning, but doesn't
296  write(STDOUT_FILENO, buf, 5);
297}
298