1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #if !defined(__clang__)
6 #error "Non-clang isn't supported"
7 #endif
8 
9 // Clang compile-time and run-time tests for glibc FORTIFY.
10 //
11 // This file is compiled in two configurations ways to give us a sane set of
12 // tests for clang's FORTIFY implementation.
13 //
14 // One configuration uses clang's diagnostic consumer
15 // (https://clang.llvm.org/doxygen/classclang_1_1VerifyDiagnosticConsumer.html#details)
16 // to check diagnostics (e.g. the expected-* comments everywhere).
17 //
18 // The other configuration builds this file such that the resultant object file
19 // exports a function named test_fortify_1 or test_fortify_2, depending on the
20 // FORTIFY level we're using. These are called by clang_fortify_driver.cpp.
21 //
22 // Please note that this test does things like leaking memory. That's WAI.
23 
24 // Silence all "from 'diagnose_if'" `note`s from anywhere, including headers;
25 // they're uninteresting for this test case, and their line numbers may change
26 // over time.
27 // expected-note@* 0+{{from 'diagnose_if'}}
28 //
29 // Similarly, there are a few overload tricks we have to emit errors. Ignore any
30 // notes from those.
31 // expected-note@* 0+{{candidate function}}
32 // expected-note@* 0+{{has been explicitly marked unavailable}}
33 
34 // Must come before stdlib.h
35 #include <limits.h>
36 
37 #include <err.h>
38 #include <fcntl.h>
39 #include <mqueue.h>
40 #include <poll.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <sys/socket.h>
45 #include <sys/wait.h>
46 #include <syslog.h>
47 #include <unistd.h>
48 #include <vector>
49 #include <wchar.h>
50 
51 #include "clang-fortify-common.h"
52 
53 // We're going to use deprecated APIs here (e.g. getwd). That's OK.
54 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
55 
56 #ifndef _FORTIFY_SOURCE
57 #error "_FORTIFY_SOURCE must be defined"
58 #endif
59 
60 /////////////////// Test infrastructure; nothing to see here ///////////////////
61 
62 // GTest doesn't seem to have an EXPECT_NO_DEATH equivalent, and this all seems
63 // easy enough to hand-roll in a simple environment.
64 
65 // Failures get stored here.
66 static std::vector<Failure> *failures;
67 
68 template <typename Fn>
ForkAndExpect(int line,const char * message,Fn && F,bool expect_death)69 static void ForkAndExpect(int line, const char *message, Fn &&F,
70                           bool expect_death) {
71   fprintf(stderr, "Running %s... (expected to %s)\n", message,
72           expect_death ? "die" : "not die");
73 
74   int pid = fork();
75   if (pid == -1)
76     err(1, "Failed to fork() a subproc");
77 
78   if (pid == 0) {
79     F();
80     exit(0);
81   }
82 
83   int status;
84   if (waitpid(pid, &status, 0) == -1)
85     err(1, "Failed to wait on child (pid %d)", pid);
86 
87   bool died = WIFSIGNALED(status) || WEXITSTATUS(status) != 0;
88   if (died != expect_death) {
89     fprintf(stderr, "Check `%s` (at line %d) %s\n", message, line,
90             expect_death ? "failed to die" : "died");
91     failures->push_back({line, message, expect_death});
92   }
93 }
94 
95 #define FORK_AND_EXPECT(x, die) ForkAndExpect(__LINE__, #x, [&] { (x); }, die)
96 
97 // EXPECT_NO_DEATH forks so that the test remains alive on a bug, and so that
98 // the environment doesn't get modified on no bug. (Environment modification is
99 // especially tricky to deal with given the *_STRUCT variants below.)
100 #define EXPECT_NO_DEATH(x) FORK_AND_EXPECT(x, false)
101 #define EXPECT_DEATH(x) FORK_AND_EXPECT(x, true)
102 
103 // Expecting death, but only if we're doing a "strict" struct-checking mode.
104 #if _FORTIFY_SOURCE > 1
105 #define EXPECT_DEATH_STRUCT(x) EXPECT_DEATH(x)
106 #else
107 #define EXPECT_DEATH_STRUCT(x) EXPECT_NO_DEATH(x)
108 #endif
109 
110 //////////////////////////////// FORTIFY tests! ////////////////////////////////
111 
112 // FIXME(gbiv): glibc shouldn't #define this with FORTIFY on.
113 #undef mempcpy
114 
115 const static int kBogusFD = -1;
116 
TestString()117 static void TestString() {
118   char small_buffer[8] = {};
119 
120   {
121     char large_buffer[sizeof(small_buffer) + 1] = {};
122     // expected-warning@+1{{called with bigger length than the destination}}
123     EXPECT_DEATH(memcpy(small_buffer, large_buffer, sizeof(large_buffer)));
124     // expected-warning@+1{{called with bigger length than the destination}}
125     EXPECT_DEATH(memmove(small_buffer, large_buffer, sizeof(large_buffer)));
126     // expected-warning@+1{{called with bigger length than the destination}}
127     EXPECT_DEATH(mempcpy(small_buffer, large_buffer, sizeof(large_buffer)));
128     // expected-warning@+1{{called with bigger length than the destination}}
129     EXPECT_DEATH(memset(small_buffer, 0, sizeof(large_buffer)));
130     // expected-warning@+1{{transposed parameters}}
131     memset(small_buffer, sizeof(small_buffer), 0);
132     // expected-warning@+1{{called with bigger length than the destination}}
133     EXPECT_DEATH(bcopy(large_buffer, small_buffer, sizeof(large_buffer)));
134     // expected-warning@+1{{called with bigger length than the destination}}
135     EXPECT_DEATH(bzero(small_buffer, sizeof(large_buffer)));
136   }
137 
138   {
139     const char large_string[] = "Hello!!!";
140     _Static_assert(sizeof(large_string) > sizeof(small_buffer), "");
141 
142     // expected-warning@+1{{destination buffer will always be overflown}}
143     EXPECT_DEATH(strcpy(small_buffer, large_string));
144     // expected-warning@+1{{destination buffer will always be overflown}}
145     EXPECT_DEATH(stpcpy(small_buffer, large_string));
146     // expected-warning@+1{{called with bigger length than the destination}}
147     EXPECT_DEATH(strncpy(small_buffer, large_string, sizeof(large_string)));
148     // expected-warning@+1{{called with bigger length than the destination}}
149     EXPECT_DEATH(stpncpy(small_buffer, large_string, sizeof(large_string)));
150     // expected-warning@+1{{destination buffer will always be overflown}}
151     EXPECT_DEATH(strcat(small_buffer, large_string));
152     // expected-warning@+1{{destination buffer will always be overflown}}
153     EXPECT_DEATH(strncat(small_buffer, large_string, sizeof(large_string)));
154   }
155 
156   {
157     struct {
158       char tiny_buffer[4];
159       char tiny_buffer2[4];
160     } split = {};
161 
162     EXPECT_NO_DEATH(memcpy(split.tiny_buffer, &split, sizeof(split)));
163     EXPECT_NO_DEATH(memcpy(split.tiny_buffer, &split, sizeof(split)));
164     EXPECT_NO_DEATH(memmove(split.tiny_buffer, &split, sizeof(split)));
165     EXPECT_NO_DEATH(mempcpy(split.tiny_buffer, &split, sizeof(split)));
166     EXPECT_NO_DEATH(memset(split.tiny_buffer, 0, sizeof(split)));
167 
168     EXPECT_NO_DEATH(bcopy(&split, split.tiny_buffer, sizeof(split)));
169     EXPECT_NO_DEATH(bzero(split.tiny_buffer, sizeof(split)));
170 
171     const char small_string[] = "Hi!!";
172     _Static_assert(sizeof(small_string) > sizeof(split.tiny_buffer), "");
173 
174 #if _FORTIFY_SOURCE > 1
175     // expected-warning@+2{{destination buffer will always be overflown}}
176 #endif
177     EXPECT_DEATH_STRUCT(strcpy(split.tiny_buffer, small_string));
178 
179 #if _FORTIFY_SOURCE > 1
180     // expected-warning@+2{{destination buffer will always be overflown}}
181 #endif
182     EXPECT_DEATH_STRUCT(stpcpy(split.tiny_buffer, small_string));
183 
184 #if _FORTIFY_SOURCE > 1
185     // expected-warning@+2{{called with bigger length than the destination}}
186 #endif
187     EXPECT_DEATH_STRUCT(
188         strncpy(split.tiny_buffer, small_string, sizeof(small_string)));
189 
190 #if _FORTIFY_SOURCE > 1
191     // expected-warning@+2{{called with bigger length than the destination}}
192 #endif
193     EXPECT_DEATH_STRUCT(
194         stpncpy(split.tiny_buffer, small_string, sizeof(small_string)));
195 
196 #if _FORTIFY_SOURCE > 1
197     // expected-warning@+2{{destination buffer will always be overflown}}
198 #endif
199     EXPECT_DEATH_STRUCT(strcat(split.tiny_buffer, small_string));
200 
201 #if _FORTIFY_SOURCE > 1
202     // expected-warning@+2{{destination buffer will always be overflown}}
203 #endif
204     EXPECT_DEATH_STRUCT(
205         strncat(split.tiny_buffer, small_string, sizeof(small_string)));
206   }
207 }
208 
209 // Since these emit hard errors, it's sort of hard to run them...
210 #ifdef COMPILATION_TESTS
211 namespace compilation_tests {
testFcntl()212 static void testFcntl() {
213   // FIXME(gbiv): Need to fix these; they got dropped.
214 #if 0
215   // expected-error@+1{{either with 2 or 3 arguments, not more}}
216 #endif
217   open("/", 0, 0, 0);
218 #if 0
219   // expected-error@+1{{either with 2 or 3 arguments, not more}}
220 #endif
221   open64("/", 0, 0, 0);
222   // expected-error@+1{{either with 3 or 4 arguments, not more}}
223   openat(0, "/", 0, 0, 0);
224   // expected-error@+1{{either with 3 or 4 arguments, not more}}
225   openat64(0, "/", 0, 0, 0);
226 
227   // expected-error@+1{{needs 3 arguments}}
228   open("/", O_CREAT);
229   // expected-error@+1{{needs 3 arguments}}
230   open("/", O_TMPFILE);
231   // expected-error@+1{{needs 3 arguments}}
232   open64("/", O_CREAT);
233   // expected-error@+1{{needs 3 arguments}}
234   open64("/", O_TMPFILE);
235   // expected-error@+1{{needs 4 arguments}}
236   openat(0, "/", O_CREAT);
237   // expected-error@+1{{needs 4 arguments}}
238   openat(0, "/", O_TMPFILE);
239   // expected-error@+1{{needs 4 arguments}}
240   openat64(0, "/", O_CREAT);
241   // expected-error@+1{{needs 4 arguments}}
242   openat64(0, "/", O_TMPFILE);
243 
244   // Superfluous modes are sometimes bugs, but not often enough to complain
245   // about, apparently.
246 }
247 
testMqueue()248 static void testMqueue() {
249   // FIXME(gbiv): remove mq_open's FORTIFY'ed body from glibc...
250 
251   // expected-error@+1{{with 2 or 4 arguments}}
252   mq_open("/", 0, 0);
253   // expected-error@+1{{with 2 or 4 arguments}}
254   mq_open("/", 0, 0, 0, 0);
255 
256   // expected-error@+1{{needs 4 arguments}}
257   mq_open("/", O_CREAT);
258 }
259 
testFormatStrings()260 static void testFormatStrings() {
261   const auto unsigned_value = std::declval<unsigned long long>();
262   const auto *unknown_string = std::declval<const char *>();
263   const auto va = std::declval<va_list>();
264 
265   {
266     auto some_fd = std::declval<int>();
267     // expected-warning@+1{{format specifies type 'int'}}
268     dprintf(some_fd, "%d", unsigned_value);
269     // expected-warning@+1{{format string is not a string literal}}
270     dprintf(some_fd, unknown_string, unsigned_value);
271     // expected-warning@+1{{format string is not a string literal}}
272     vdprintf(1, unknown_string, va);
273   }
274 
275   {
276     auto *retval = std::declval<char *>();
277     // expected-warning@+2{{ignoring return value}}
278     // expected-warning@+1{{format specifies type 'int'}}
279     asprintf(&retval, "%d", unsigned_value);
280     // expected-warning@+2{{ignoring return value}}
281     // expected-warning@+1{{format string is not a string literal}}
282     asprintf(&retval, unknown_string, unsigned_value);
283     // expected-warning@+2{{ignoring return value}}
284     // expected-warning@+1{{format string is not a string literal}}
285     vasprintf(&retval, unknown_string, va);
286   }
287 
288   {
289     auto *obs = std::declval<obstack *>();
290     // expected-warning@+1{{format specifies type 'int'}}
291     obstack_printf(obs, "%d", unsigned_value);
292     // expected-warning@+1{{format string is not a string literal}}
293     obstack_printf(obs, unknown_string, unsigned_value);
294     // expected-warning@+1{{format string is not a string literal}}
295     obstack_vprintf(obs, unknown_string, va);
296   }
297 
298   // expected-warning@+1{{format specifies type 'int'}}
299   syslog(0, "%d", unsigned_value);
300   // expected-warning@+1{{format string is not a string literal}}
301   syslog(0, unknown_string, unsigned_value);
302   // expected-warning@+1{{format string is not a string literal}}
303   vsyslog(0, unknown_string, va);
304 
305   {
306     auto *file = std::declval<FILE *>();
307     // expected-warning@+1{{format specifies type 'int'}}
308     fprintf(file, "%d", unsigned_value);
309     // expected-warning@+1{{format string is not a string literal}}
310     fprintf(file, unknown_string, unsigned_value);
311     // expected-warning@+1{{format string is not a string literal}}
312     vfprintf(file, unknown_string, va);
313   }
314 
315   // expected-warning@+1{{format specifies type 'int'}}
316   printf("%d", unsigned_value);
317   // expected-warning@+1{{format string is not a string literal}}
318   printf(unknown_string, unsigned_value);
319   // expected-warning@+1{{format string is not a string literal}}
320   vprintf(unknown_string, va);
321 
322   {
323     char buf[128];
324     // expected-warning@+1{{format specifies type 'int'}}
325     sprintf(buf, "%d", unsigned_value);
326     // expected-warning@+1{{format string is not a string literal}}
327     sprintf(buf, unknown_string, unsigned_value);
328     // expected-warning@+1{{format string is not a string literal}}
329     sprintf(buf, unknown_string, va);
330 
331     // expected-warning@+1{{format specifies type 'int'}}
332     snprintf(buf, sizeof(buf), "%d", unsigned_value);
333     // expected-warning@+1{{format string is not a string literal}}
334     snprintf(buf, sizeof(buf), unknown_string, unsigned_value);
335     // expected-warning@+1{{format string is not a string literal}}
336     vsnprintf(buf, sizeof(buf), unknown_string, va);
337   }
338 
339   // Note that glibc doesn't try to specify __format__ attrs for wchar printf
340   // functions, so we don't check for that.
341 }
342 } // namespace compilation_tests
343 #endif
344 
TestPoll()345 static void TestPoll() {
346   struct pollfd invalid_poll_fd = {kBogusFD, 0, 0};
347   {
348     struct pollfd few_fds[] = {invalid_poll_fd, invalid_poll_fd};
349     // expected-warning@+1{{fds buffer too small}}
350     EXPECT_DEATH(poll(few_fds, 3, 0));
351     // expected-warning@+1{{fds buffer too small}}
352     EXPECT_DEATH(ppoll(few_fds, 3, 0, 0));
353   }
354 
355   {
356     struct {
357       struct pollfd few[2];
358       struct pollfd extra[1];
359     } fds = {{invalid_poll_fd, invalid_poll_fd}, {invalid_poll_fd}};
360     _Static_assert(sizeof(fds) >= sizeof(struct pollfd) * 3, "");
361 
362 #if _FORTIFY_SOURCE > 1
363     // expected-warning@+2{{fds buffer too small}}
364 #endif
365     EXPECT_DEATH_STRUCT(poll(fds.few, 3, 0));
366 
367     struct timespec timeout = {};
368 #if _FORTIFY_SOURCE > 1
369     // expected-warning@+2{{fds buffer too small}}
370 #endif
371     EXPECT_DEATH_STRUCT(ppoll(fds.few, 3, &timeout, 0));
372   }
373 }
374 
TestSocket()375 static void TestSocket() {
376   {
377     char small_buffer[8];
378     // expected-warning@+1{{bigger length than size of destination buffer}}
379     EXPECT_DEATH(recv(kBogusFD, small_buffer, sizeof(small_buffer) + 1, 0));
380     // expected-warning@+1{{bigger length than size of destination buffer}}
381     EXPECT_DEATH(
382         recvfrom(kBogusFD, small_buffer, sizeof(small_buffer) + 1, 0, 0, 0));
383   }
384 
385   {
386     struct {
387       char tiny_buffer[4];
388       char tiny_buffer2;
389     } split = {};
390 
391     EXPECT_NO_DEATH(recv(kBogusFD, split.tiny_buffer, sizeof(split), 0));
392     EXPECT_NO_DEATH(
393         recvfrom(kBogusFD, split.tiny_buffer, sizeof(split), 0, 0, 0));
394   }
395 }
396 
TestStdio()397 static void TestStdio() {
398   char small_buffer[8] = {};
399   {
400     // expected-warning@+1{{may overflow the destination buffer}}
401     EXPECT_DEATH(snprintf(small_buffer, sizeof(small_buffer) + 1, ""));
402 
403     va_list va;
404     // expected-warning@+2{{format string is empty}}
405     // expected-warning@+1{{may overflow the destination buffer}}
406     EXPECT_DEATH(vsnprintf(small_buffer, sizeof(small_buffer) + 1, "", va));
407   }
408 
409   // gets is safe here, since stdin is actually /dev/null
410   // expected-warning@+1{{ignoring return value}}
411   EXPECT_NO_DEATH(gets(small_buffer));
412 
413   char *volatile unknown_size_buffer = small_buffer;
414   // Since stdin is /dev/null, gets on a tiny buffer is safe here.
415   // expected-warning@+2{{ignoring return value}}
416   // expected-warning@+1{{please use fgets or getline}}
417   EXPECT_NO_DEATH(gets(unknown_size_buffer));
418 }
419 
TestUnistd()420 static void TestUnistd() {
421   char small_buffer[8];
422 
423   // Return value warnings are (sort of) a part of FORTIFY, so we don't ignore
424   // them.
425   // expected-warning@+2{{ignoring return value of function}}
426   // expected-warning@+1{{bigger length than size of the destination buffer}}
427   EXPECT_DEATH(read(kBogusFD, small_buffer, sizeof(small_buffer) + 1));
428   // expected-warning@+2{{ignoring return value of function}}
429   // expected-warning@+1{{bigger length than size of the destination buffer}}
430   EXPECT_DEATH(pread(kBogusFD, small_buffer, sizeof(small_buffer) + 1, 0));
431   // expected-warning@+2{{ignoring return value of function}}
432   // expected-warning@+1{{bigger length than size of the destination buffer}}
433   EXPECT_DEATH(pread64(kBogusFD, small_buffer, sizeof(small_buffer) + 1, 0));
434   // expected-warning@+2{{ignoring return value of function}}
435   // expected-warning@+1{{bigger length than size of destination buffer}}
436   EXPECT_DEATH(readlink("/", small_buffer, sizeof(small_buffer) + 1));
437   // expected-warning@+2{{ignoring return value of function}}
438   // expected-warning@+1{{bigger length than size of destination buffer}}
439   EXPECT_DEATH(getcwd(small_buffer, sizeof(small_buffer) + 1));
440 
441   // glibc allocates and returns a buffer if you pass null to getcwd
442   // expected-warning@+1{{ignoring return value of function}}
443   EXPECT_NO_DEATH(getcwd(NULL, 0));
444   // expected-warning@+1{{ignoring return value of function}}
445   EXPECT_NO_DEATH(getcwd(NULL, 4096));
446 
447   {
448     char large_buffer[PATH_MAX * 2];
449     // expected-warning@+1{{ignoring return value of function}}
450     EXPECT_NO_DEATH(getwd(large_buffer));
451 
452     char *volatile unknown_size_buffer = large_buffer;
453     // expected-warning@+2{{ignoring return value of function}}
454     // expected-warning@+1{{please use getcwd instead}}
455     EXPECT_NO_DEATH(getwd(unknown_size_buffer));
456   }
457 
458   // expected-warning@+1{{bigger length than size of destination buffer}}
459   EXPECT_DEATH(confstr(0, small_buffer, sizeof(small_buffer) + 1));
460 
461   {
462     gid_t gids[2];
463     // expected-warning@+1{{bigger group count than what can fit}}
464     EXPECT_DEATH(getgroups(3, gids));
465   }
466 
467   // expected-warning@+1{{bigger buflen than size of destination buffer}}
468   EXPECT_DEATH(ttyname_r(kBogusFD, small_buffer, sizeof(small_buffer) + 1));
469   // expected-warning@+1{{bigger buflen than size of destination buffer}}
470   EXPECT_DEATH(getlogin_r(small_buffer, sizeof(small_buffer) + 1));
471   // expected-warning@+1{{bigger buflen than size of destination buffer}}
472   EXPECT_DEATH(gethostname(small_buffer, sizeof(small_buffer) + 1));
473   // expected-warning@+1{{bigger buflen than size of destination buffer}}
474   EXPECT_DEATH(getdomainname(small_buffer, sizeof(small_buffer) + 1));
475 
476   // We've already checked the warn-unused-result warnings; no need to clutter
477   // the code with rechecks...
478 #pragma clang diagnostic push
479 #pragma clang diagnostic ignored "-Wunused-value"
480   struct {
481     char tiny_buffer[4];
482     char tiny_buffer2[4];
483   } split;
484 
485   EXPECT_NO_DEATH(read(kBogusFD, split.tiny_buffer, sizeof(split)));
486   EXPECT_NO_DEATH(pread(kBogusFD, split.tiny_buffer, sizeof(split), 0));
487   EXPECT_NO_DEATH(pread64(kBogusFD, split.tiny_buffer, sizeof(split), 0));
488 
489 #if _FORTIFY_SOURCE > 1
490   // expected-warning@+2{{bigger length than size of destination buffer}}
491 #endif
492   EXPECT_DEATH_STRUCT(readlink("/", split.tiny_buffer, sizeof(split)));
493 #if _FORTIFY_SOURCE > 1
494   // expected-warning@+2{{bigger length than size of destination buffer}}
495 #endif
496   EXPECT_DEATH_STRUCT(getcwd(split.tiny_buffer, sizeof(split)));
497 
498 #if _FORTIFY_SOURCE > 1
499   // expected-warning@+2{{bigger length than size of destination buffer}}
500 #endif
501   EXPECT_DEATH_STRUCT(confstr(kBogusFD, split.tiny_buffer, sizeof(split)));
502 
503   {
504     struct {
505       gid_t tiny_buffer[2];
506       gid_t tiny_buffer2[1];
507     } split_gids;
508 #if _FORTIFY_SOURCE > 1
509     // expected-warning@+2{{bigger group count than what can fit}}
510 #endif
511     EXPECT_DEATH_STRUCT(getgroups(3, split_gids.tiny_buffer));
512   }
513 
514 #if _FORTIFY_SOURCE > 1
515   // expected-warning@+2{{bigger buflen than size of destination buffer}}
516 #endif
517   EXPECT_DEATH_STRUCT(ttyname_r(kBogusFD, split.tiny_buffer, sizeof(split)));
518 #if _FORTIFY_SOURCE > 1
519   // expected-warning@+2{{bigger buflen than size of destination buffer}}
520 #endif
521   EXPECT_DEATH_STRUCT(getlogin_r(split.tiny_buffer, sizeof(split)));
522 #if _FORTIFY_SOURCE > 1
523   // expected-warning@+2{{bigger buflen than size of destination buffer}}
524 #endif
525   EXPECT_DEATH_STRUCT(gethostname(split.tiny_buffer, sizeof(split)));
526 #if _FORTIFY_SOURCE > 1
527   // expected-warning@+2{{bigger buflen than size of destination buffer}}
528 #endif
529   EXPECT_DEATH_STRUCT(getdomainname(split.tiny_buffer, sizeof(split)));
530 
531 #pragma clang diagnostic pop // -Wunused-value
532 }
533 
TestWchar()534 static void TestWchar() {
535   // Sizes here are all expressed in terms of sizeof(wchar_t).
536   const int small_buffer_size = 8;
537   wchar_t small_buffer[small_buffer_size] = {};
538   {
539     const int large_buffer_size = small_buffer_size + 1;
540     wchar_t large_buffer[large_buffer_size];
541 
542     // expected-warning@+1{{length bigger than size of destination buffer}}
543     EXPECT_DEATH(wmemcpy(small_buffer, large_buffer, large_buffer_size));
544     // expected-warning@+1{{length bigger than size of destination buffer}}
545     EXPECT_DEATH(wmemmove(small_buffer, large_buffer, large_buffer_size));
546     // expected-warning@+1{{length bigger than size of destination buffer}}
547     EXPECT_DEATH(wmempcpy(small_buffer, large_buffer, large_buffer_size));
548   }
549 
550   {
551     const wchar_t large_string[] = L"Hello!!!";
552     const int large_string_size = small_buffer_size + 1;
553     _Static_assert(sizeof(large_string) == large_string_size * sizeof(wchar_t),
554                    "");
555 
556     // expected-warning@+1{{length bigger than size of destination buffer}}
557     EXPECT_DEATH(wmemset(small_buffer, 0, small_buffer_size + 1));
558     // expected-warning@+1{{length bigger than size of destination buffer}}
559     EXPECT_DEATH(wcsncpy(small_buffer, large_string, small_buffer_size + 1));
560     // expected-warning@+1{{length bigger than size of destination buffer}}
561     EXPECT_DEATH(wcpncpy(small_buffer, large_string, small_buffer_size + 1));
562 
563     // expected-warning@+2{{ignoring return value of function}}
564     // expected-warning@+1{{length bigger than size of destination buffer}}
565     EXPECT_DEATH(fgetws(small_buffer, sizeof(small_buffer) + 1, 0));
566     // expected-warning@+2{{ignoring return value of function}}
567     // expected-warning@+1{{bigger size than length of destination buffer}}
568     EXPECT_DEATH(fgetws_unlocked(small_buffer, sizeof(small_buffer) + 1, 0));
569 
570     // No diagnostics emitted for either clang or gcc :(
571     EXPECT_DEATH(wcscpy(small_buffer, large_string));
572     EXPECT_DEATH(wcpcpy(small_buffer, large_string));
573     EXPECT_DEATH(wcscat(small_buffer, large_string));
574     EXPECT_DEATH(wcsncat(small_buffer, large_string, large_string_size));
575   }
576 
577   mbstate_t mbs;
578   bzero(&mbs, sizeof(mbs));
579   {
580     const char *src[small_buffer_size * sizeof(wchar_t)];
581     // expected-warning@+1{{called with dst buffer smaller than}}
582     EXPECT_DEATH(mbsrtowcs(small_buffer, src, sizeof(small_buffer) + 1, &mbs));
583   }
584 
585   {
586     const int array_len = 8;
587     char chars[array_len];
588     const char *chars_ptr = chars;
589     wchar_t wchars[array_len];
590     const wchar_t *wchars_ptr = wchars;
591     // expected-warning@+1{{called with dst buffer smaller than}}
592     EXPECT_DEATH(wcsrtombs(chars, &wchars_ptr, array_len + 1, &mbs));
593     // expected-warning@+1{{called with dst buffer smaller than}}
594     EXPECT_DEATH(mbsnrtowcs(wchars, &chars_ptr, 0, array_len + 1, &mbs));
595     // expected-warning@+1{{called with dst buffer smaller than}}
596     EXPECT_DEATH(wcsnrtombs(chars, &wchars_ptr, 0, array_len + 1, &mbs));
597   }
598 
599 
600   struct {
601     wchar_t buf[small_buffer_size - 1];
602     wchar_t extra;
603   } small_split;
604   _Static_assert(sizeof(small_split) == sizeof(small_buffer), "");
605   bzero(&small_split, sizeof(small_split));
606 
607   EXPECT_NO_DEATH(wmemcpy(small_split.buf, small_buffer, small_buffer_size));
608   EXPECT_NO_DEATH(wmemmove(small_split.buf, small_buffer, small_buffer_size));
609   EXPECT_NO_DEATH(wmempcpy(small_split.buf, small_buffer, small_buffer_size));
610 
611   {
612     const wchar_t small_string[] = L"Hello!!";
613     _Static_assert(sizeof(small_buffer) == sizeof(small_string), "");
614 
615     EXPECT_NO_DEATH(wmemset(small_split.buf, 0, small_buffer_size));
616 #if _FORTIFY_SOURCE > 1
617     // expected-warning@+2{{length bigger than size of destination buffer}}
618 #endif
619     EXPECT_DEATH_STRUCT(
620         wcsncpy(small_split.buf, small_string, small_buffer_size));
621 #if _FORTIFY_SOURCE > 1
622     // expected-warning@+2{{length bigger than size of destination buffer}}
623 #endif
624     EXPECT_DEATH_STRUCT(
625         wcpncpy(small_split.buf, small_string, small_buffer_size));
626 
627     // FIXME(gbiv): FORTIFY doesn't warn about this eagerly enough on
628     // _FORTIFY_SOURCE=1.
629     // expected-warning@+4{{ignoring return value of function}}
630 #if _FORTIFY_SOURCE > 1
631     // expected-warning@+2{{length bigger than size of destination buffer}}
632 #endif
633     EXPECT_DEATH(fgetws(small_split.buf, small_buffer_size, 0));
634 
635     // FIXME(gbiv): FORTIFY doesn't warn about this eagerly enough on
636     // _FORTIFY_SOURCE=1.
637     // expected-warning@+4{{ignoring return value of function}}
638 #if _FORTIFY_SOURCE > 1
639     // expected-warning@+2{{bigger size than length of destination buffer}}
640 #endif
641     EXPECT_DEATH(fgetws_unlocked(small_split.buf, small_buffer_size, 0));
642 
643     // No diagnostics emitted for either clang or gcc :(
644     EXPECT_DEATH_STRUCT(wcscpy(small_split.buf, small_string));
645     EXPECT_DEATH_STRUCT(wcpcpy(small_split.buf, small_string));
646     EXPECT_DEATH_STRUCT(wcscat(small_split.buf, small_string));
647     EXPECT_DEATH_STRUCT(
648         wcsncat(small_split.buf, small_string, small_buffer_size));
649   }
650 
651   {
652     // NOREVIEW: STRUCT
653     const char *src[sizeof(small_buffer)] = {};
654     // FIXME(gbiv): _FORTIFY_SOURCE=1 should diagnose this more aggressively
655 #if _FORTIFY_SOURCE > 1
656     // expected-warning@+2{{called with dst buffer smaller than}}
657 #endif
658     EXPECT_DEATH(mbsrtowcs(small_split.buf, src, small_buffer_size, &mbs));
659   }
660 
661   {
662     // NOREVIEW: STRUCT
663     const int array_len = 8;
664     struct {
665       char buf[array_len - 1];
666       char extra;
667     } split_chars;
668     const char *chars_ptr = split_chars.buf;
669     struct {
670       wchar_t buf[array_len - 1];
671       wchar_t extra;
672     } split_wchars;
673     const wchar_t *wchars_ptr = split_wchars.buf;
674 #if _FORTIFY_SOURCE > 1
675     // expected-warning@+2{{called with dst buffer smaller than}}
676 #endif
677     EXPECT_DEATH_STRUCT(
678         wcsrtombs(split_chars.buf, &wchars_ptr, array_len, &mbs));
679 #if _FORTIFY_SOURCE > 1
680     // expected-warning@+2{{called with dst buffer smaller than}}
681 #endif
682     EXPECT_DEATH_STRUCT(
683         mbsnrtowcs(split_wchars.buf, &chars_ptr, 0, array_len, &mbs));
684 #if _FORTIFY_SOURCE > 1
685     // expected-warning@+2{{called with dst buffer smaller than}}
686 #endif
687     EXPECT_DEATH_STRUCT(
688         wcsnrtombs(split_chars.buf, &wchars_ptr, 0, array_len, &mbs));
689   }
690 }
691 
TestStdlib()692 static void TestStdlib() {
693   {
694     char path_buffer[PATH_MAX - 1];
695     // expected-warning@+2{{ignoring return value of function}}
696     // expected-warning@+1{{must be either NULL or at least PATH_MAX bytes}}
697     EXPECT_DEATH(realpath("/", path_buffer));
698     // expected-warning@+1{{ignoring return value of function}}
699     realpath("/", NULL);
700   }
701 
702   char small_buffer[8];
703   // expected-warning@+1{{called with buflen bigger than size of buf}}
704   EXPECT_DEATH(ptsname_r(kBogusFD, small_buffer, sizeof(small_buffer) + 1));
705 
706   {
707     const int wchar_buffer_size = 8;
708     wchar_t wchar_buffer[wchar_buffer_size];
709     // expected-warning@+1{{called with dst buffer smaller than}}
710     EXPECT_DEATH(mbstowcs(wchar_buffer, small_buffer, wchar_buffer_size + 1));
711     // expected-warning@+1{{called with dst buffer smaller than}}
712     EXPECT_DEATH(
713         wcstombs(small_buffer, wchar_buffer, sizeof(small_buffer) + 1));
714   }
715 
716   {
717     struct {
718       char path_buffer[PATH_MAX - 1];
719       char rest[1];
720     } split;
721     // expected-warning@+4{{ignoring return value of function}}
722 #if _FORTIFY_SOURCE > 1
723     // expected-warning@+2{{must be either NULL or at least PATH_MAX bytes}}
724 #endif
725     EXPECT_DEATH_STRUCT(realpath("/", split.path_buffer));
726   }
727 
728   struct {
729     char tiny_buffer[4];
730     char rest[1];
731   } split;
732 #if _FORTIFY_SOURCE > 1
733   // expected-warning@+2{{called with buflen bigger than size of buf}}
734 #endif
735   EXPECT_DEATH_STRUCT(ptsname_r(kBogusFD, split.tiny_buffer, sizeof(split)));
736 
737   {
738     const int tiny_buffer_size = 4;
739     struct {
740       wchar_t tiny_buffer[tiny_buffer_size];
741       wchar_t rest;
742     } wsplit;
743 #if _FORTIFY_SOURCE > 1
744     // expected-warning@+2{{called with dst buffer smaller than}}
745 #endif
746     EXPECT_DEATH_STRUCT(
747         mbstowcs(wsplit.tiny_buffer, small_buffer, tiny_buffer_size + 1));
748 #if _FORTIFY_SOURCE > 1
749     // expected-warning@+2{{called with dst buffer smaller than}}
750 #endif
751     EXPECT_DEATH_STRUCT(
752         wcstombs(split.tiny_buffer, wsplit.tiny_buffer, sizeof(split)));
753   }
754 }
755 
756 /////////////////// Test infrastructure; nothing to see here ///////////////////
757 
758 #define CONCAT2(x, y) x ## y
759 #define CONCAT(x, y) CONCAT2(x, y)
760 
761 // Exported to the driver so we can run these tests.
CONCAT(test_fortify_,_FORTIFY_SOURCE)762 std::vector<Failure> CONCAT(test_fortify_, _FORTIFY_SOURCE)() {
763   std::vector<Failure> result;
764   failures = &result;
765 
766   TestPoll();
767   TestSocket();
768   TestStdio();
769   TestStdlib();
770   TestString();
771   TestUnistd();
772   TestWchar();
773 
774   failures = nullptr;
775   return result;
776 }
777