37320c3514f458eca08a554e1e88057a39869ca2
[platform/upstream/glibc.git] / debug / tst-chk1.c
1 /* Copyright (C) 2004 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <fcntl.h>
21 #include <paths.h>
22 #include <setjmp.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28
29 char *temp_filename;
30 static void do_prepare (void);
31 static int do_test (void);
32 #define PREPARE(argc, argv) do_prepare ()
33 #define TEST_FUNCTION do_test ()
34 #include "../test-skeleton.c"
35
36 static void
37 do_prepare (void)
38 {
39   int temp_fd = create_temp_file ("tst-chk1.", &temp_filename);
40   if (temp_fd == -1)
41     {
42       printf ("cannot create temporary file: %m\n");
43       exit (1);
44     }
45
46   const char *strs = "abcdefgh\nABCDEFGHI\nabcdefghij\nABCDEFGHIJ";
47   if (write (temp_fd, strs, strlen (strs)) != strlen (strs))
48     {
49       puts ("could not write test strings into file");
50       unlink (temp_filename);
51       exit (1);
52     }
53 }
54
55 volatile int chk_fail_ok;
56 volatile int ret;
57 jmp_buf chk_fail_buf;
58
59 static void
60 handler (int sig)
61 {
62   if (chk_fail_ok)
63     {
64       chk_fail_ok = 0;
65       longjmp (chk_fail_buf, 1);
66     }
67   else
68     _exit (127);
69 }
70
71 char buf[10];
72 volatile size_t l0;
73 volatile char *p;
74 const char *str1 = "JIHGFEDCBA";
75 const char *str2 = "F";
76 const char *str3 = "%s%n%s%n";
77 const char *str4 = "Hello, ";
78 const char *str5 = "World!\n";
79 char buf2[10] = "%s";
80 int num1 = 67;
81 int num2 = 987654;
82
83 #define FAIL() \
84   do { printf ("Failure on line %d\n", __LINE__); ret = 1; } while (0)
85 #define CHK_FAIL_START \
86   chk_fail_ok = 1;                              \
87   if (! setjmp (chk_fail_buf))                  \
88     {
89 #define CHK_FAIL_END \
90       chk_fail_ok = 0;                          \
91       FAIL ();                                  \
92     }
93 #if __USE_FORTIFY_LEVEL >= 2
94 #define CHK_FAIL2_START CHK_FAIL_START
95 #define CHK_FAIL2_END CHK_FAIL_END
96 #else
97 #define CHK_FAIL2_START
98 #define CHK_FAIL2_END
99 #endif
100
101 static int
102 do_test (void)
103 {
104   struct sigaction sa;
105   sa.sa_handler = handler;
106   sa.sa_flags = 0;
107   sigemptyset (&sa.sa_mask);
108
109   sigaction (SIGABRT, &sa, NULL);
110
111   /* Avoid all the buffer overflow messages on stderr.  */
112   int fd = open (_PATH_DEVNULL, O_WRONLY);
113   if (fd == -1)
114     close (STDERR_FILENO);
115   else
116     {
117       dup2 (fd, STDERR_FILENO);
118       close (fd);
119     }
120   setenv ("LIBC_FATAL_STDERR_", "1", 1);
121
122   struct A { char buf1[9]; char buf2[1]; } a;
123
124   printf ("Test checking routines at fortify level %d\n",
125 #ifdef __USE_FORTIFY_LEVEL
126           (int) __USE_FORTIFY_LEVEL
127 #else
128           0
129 #endif
130           );
131
132   /* These ops can be done without runtime checking of object size.  */
133   memcpy (buf, "abcdefghij", 10);
134   memmove (buf + 1, buf, 9);
135   if (memcmp (buf, "aabcdefghi", 10))
136     FAIL ();
137
138   if (mempcpy (buf + 5, "abcde", 5) != buf + 10 || memcmp (buf, "aabcdabcde", 10))
139     FAIL ();
140
141   memset (buf + 8, 'j', 2);
142   if (memcmp (buf, "aabcdabcjj", 10))
143     FAIL ();
144
145   strcpy (buf + 4, "EDCBA");
146   if (memcmp (buf, "aabcEDCBA", 10))
147     FAIL ();
148
149   if (stpcpy (buf + 8, "F") != buf + 9 || memcmp (buf, "aabcEDCBF", 10))
150     FAIL ();
151
152   strncpy (buf + 6, "X", 4);
153   if (memcmp (buf, "aabcEDX\0\0", 10))
154     FAIL ();
155
156   if (sprintf (buf + 7, "%s", "67") != 2 || memcmp (buf, "aabcEDX67", 10))
157     FAIL ();
158
159   if (snprintf (buf + 7, 3, "%s", "987654") != 6
160       || memcmp (buf, "aabcEDX98", 10))
161     FAIL ();
162
163   /* These ops need runtime checking, but shouldn't __chk_fail.  */
164   memcpy (buf, "abcdefghij", l0 + 10);
165   memmove (buf + 1, buf, l0 + 9);
166   if (memcmp (buf, "aabcdefghi", 10))
167     FAIL ();
168
169   if (mempcpy (buf + 5, "abcde", l0 + 5) != buf + 10 || memcmp (buf, "aabcdabcde", 10))
170     FAIL ();
171
172   memset (buf + 8, 'j', l0 + 2);
173   if (memcmp (buf, "aabcdabcjj", 10))
174     FAIL ();
175
176   strcpy (buf + 4, str1 + 5);
177   if (memcmp (buf, "aabcEDCBA", 10))
178     FAIL ();
179
180   if (stpcpy (buf + 8, str2) != buf + 9 || memcmp (buf, "aabcEDCBF", 10))
181     FAIL ();
182
183   strncpy (buf + 6, "X", l0 + 4);
184   if (memcmp (buf, "aabcEDX\0\0", 10))
185     FAIL ();
186
187   if (sprintf (buf + 7, "%d", num1) != 2 || memcmp (buf, "aabcEDX67", 10))
188     FAIL ();
189
190   if (snprintf (buf + 7, 3, "%d", num2) != 6 || memcmp (buf, "aabcEDX98", 10))
191     FAIL ();
192
193   buf[l0 + 8] = '\0';
194   strcat (buf, "A");
195   if (memcmp (buf, "aabcEDX9A", 10))
196     FAIL ();
197
198   buf[l0 + 7] = '\0';
199   strncat (buf, "ZYXWV", l0 + 2);
200   if (memcmp (buf, "aabcEDXZY", 10))
201     FAIL ();
202
203   memcpy (a.buf1, "abcdefghij", l0 + 10);
204   memmove (a.buf1 + 1, a.buf1, l0 + 9);
205   if (memcmp (a.buf1, "aabcdefghi", 10))
206     FAIL ();
207
208   if (mempcpy (a.buf1 + 5, "abcde", l0 + 5) != a.buf1 + 10
209       || memcmp (a.buf1, "aabcdabcde", 10))
210     FAIL ();
211
212   memset (a.buf1 + 8, 'j', l0 + 2);
213   if (memcmp (a.buf1, "aabcdabcjj", 10))
214     FAIL ();
215
216 #if __USE_FORTIFY_LEVEL < 2
217   /* The following tests are supposed to crash with -D_FORTIFY_SOURCE=2
218      and sufficient GCC support, as the string operations overflow
219      from a.buf1 into a.buf2.  */
220   strcpy (a.buf1 + 4, str1 + 5);
221   if (memcmp (a.buf1, "aabcEDCBA", 10))
222     FAIL ();
223
224   if (stpcpy (a.buf1 + 8, str2) != a.buf1 + 9 || memcmp (a.buf1, "aabcEDCBF", 10))
225     FAIL ();
226
227   strncpy (a.buf1 + 6, "X", l0 + 4);
228   if (memcmp (a.buf1, "aabcEDX\0\0", 10))
229     FAIL ();
230
231   if (sprintf (a.buf1 + 7, "%d", num1) != 2 || memcmp (a.buf1, "aabcEDX67", 10))
232     FAIL ();
233
234   if (snprintf (a.buf1 + 7, 3, "%d", num2) != 6
235       || memcmp (a.buf1, "aabcEDX98", 10))
236     FAIL ();
237
238   a.buf1[l0 + 8] = '\0';
239   strcat (a.buf1, "A");
240   if (memcmp (a.buf1, "aabcEDX9A", 10))
241     FAIL ();
242
243   a.buf1[l0 + 7] = '\0';
244   strncat (a.buf1, "ZYXWV", l0 + 2);
245   if (memcmp (a.buf1, "aabcEDXZY", 10))
246     FAIL ();
247
248 #endif
249
250 #if __USE_FORTIFY_LEVEL >= 1
251   /* Now check if all buffer overflows are caught at runtime.  */
252
253   CHK_FAIL_START
254   memcpy (buf + 1, "abcdefghij", l0 + 10);
255   CHK_FAIL_END
256
257   CHK_FAIL_START
258   memmove (buf + 2, buf + 1, l0 + 9);
259   CHK_FAIL_END
260
261   CHK_FAIL_START
262   p = mempcpy (buf + 6, "abcde", l0 + 5);
263   CHK_FAIL_END
264
265   CHK_FAIL_START
266   memset (buf + 9, 'j', l0 + 2);
267   CHK_FAIL_END
268
269   CHK_FAIL_START
270   strcpy (buf + 5, str1 + 5);
271   CHK_FAIL_END
272
273   CHK_FAIL_START
274   p = stpcpy (buf + 9, str2);
275   CHK_FAIL_END
276
277   CHK_FAIL_START
278   strncpy (buf + 7, "X", l0 + 4);
279   CHK_FAIL_END
280
281   CHK_FAIL_START
282   sprintf (buf + 8, "%d", num1);
283   CHK_FAIL_END
284
285   CHK_FAIL_START
286   snprintf (buf + 8, l0 + 3, "%d", num2);
287   CHK_FAIL_END
288
289   memcpy (buf, str1 + 2, l0 + 9);
290   CHK_FAIL_START
291   strcat (buf, "AB");
292   CHK_FAIL_END
293
294   memcpy (buf, str1 + 3, l0 + 8);
295   CHK_FAIL_START
296   strncat (buf, "ZYXWV", l0 + 3);
297   CHK_FAIL_END
298
299   CHK_FAIL_START
300   memcpy (a.buf1 + 1, "abcdefghij", l0 + 10);
301   CHK_FAIL_END
302
303   CHK_FAIL_START
304   memmove (a.buf1 + 2, a.buf1 + 1, l0 + 9);
305   CHK_FAIL_END
306
307   CHK_FAIL_START
308   p = mempcpy (a.buf1 + 6, "abcde", l0 + 5);
309   CHK_FAIL_END
310
311   CHK_FAIL_START
312   memset (a.buf1 + 9, 'j', l0 + 2);
313   CHK_FAIL_END
314
315 #if __USE_FORTIFY_LEVEL >= 2
316 # define O 0
317 #else
318 # define O 1
319 #endif
320
321   CHK_FAIL_START
322   strcpy (a.buf1 + (O + 4), str1 + 5);
323   CHK_FAIL_END
324
325   CHK_FAIL_START
326   p = stpcpy (a.buf1 + (O + 8), str2);
327   CHK_FAIL_END
328
329   CHK_FAIL_START
330   strncpy (a.buf1 + (O + 6), "X", l0 + 4);
331   CHK_FAIL_END
332
333   CHK_FAIL_START
334   sprintf (a.buf1 + (O + 7), "%d", num1);
335   CHK_FAIL_END
336
337   CHK_FAIL_START
338   snprintf (a.buf1 + (O + 7), l0 + 3, "%d", num2);
339   CHK_FAIL_END
340
341   memcpy (a.buf1, str1 + (3 - O), l0 + 8 + O);
342   CHK_FAIL_START
343   strcat (a.buf1, "AB");
344   CHK_FAIL_END
345
346   memcpy (a.buf1, str1 + (4 - O), l0 + 7 + O);
347   CHK_FAIL_START
348   strncat (a.buf1, "ZYXWV", l0 + 3);
349   CHK_FAIL_END
350 #endif
351
352   /* Now checks for %n protection.  */
353
354   /* Constant literals passed directly are always ok
355      (even with warnings about possible bugs from GCC).  */
356   int n1, n2;
357   if (sprintf (buf, "%s%n%s%n", str2, &n1, str2, &n2) != 2
358       || n1 != 1 || n2 != 2)
359     FAIL ();
360
361   /* In this case the format string is not known at compile time,
362      but resides in read-only memory, so is ok.  */
363   if (snprintf (buf, 4, str3, str2, &n1, str2, &n2) != 2
364       || n1 != 1 || n2 != 2)
365     FAIL ();
366
367   strcpy (buf2 + 2, "%n%s%n");
368   /* When the format string is writable and contains %n,
369      with -D_FORTIFY_SOURCE=2 it causes __chk_fail.  */
370   CHK_FAIL2_START
371   if (sprintf (buf, buf2, str2, &n1, str2, &n1) != 2)
372     FAIL ();
373   CHK_FAIL2_END
374
375   CHK_FAIL2_START
376   if (snprintf (buf, 3, buf2, str2, &n1, str2, &n1) != 2)
377     FAIL ();
378   CHK_FAIL2_END
379
380   /* But if there is no %n, even writable format string
381      should work.  */
382   buf2[6] = '\0';
383   if (sprintf (buf, buf2 + 4, str2) != 1)
384     FAIL ();
385
386   /* Constant literals passed directly are always ok
387      (even with warnings about possible bugs from GCC).  */
388   if (printf ("%s%n%s%n", str4, &n1, str5, &n2) != 14
389       || n1 != 7 || n2 != 14)
390     FAIL ();
391
392   /* In this case the format string is not known at compile time,
393      but resides in read-only memory, so is ok.  */
394   if (printf (str3, str4, &n1, str5, &n2) != 14
395       || n1 != 7 || n2 != 14)
396     FAIL ();
397
398   strcpy (buf2 + 2, "%n%s%n");
399   /* When the format string is writable and contains %n,
400      with -D_FORTIFY_SOURCE=2 it causes __chk_fail.  */
401   CHK_FAIL2_START
402   if (printf (buf2, str4, &n1, str5, &n1) != 14)
403     FAIL ();
404   CHK_FAIL2_END
405
406   /* But if there is no %n, even writable format string
407      should work.  */
408   buf2[6] = '\0';
409   if (printf (buf2 + 4, str5) != 7)
410     FAIL ();
411
412   FILE *fp = stdout;
413
414   /* Constant literals passed directly are always ok
415      (even with warnings about possible bugs from GCC).  */
416   if (fprintf (fp, "%s%n%s%n", str4, &n1, str5, &n2) != 14
417       || n1 != 7 || n2 != 14)
418     FAIL ();
419
420   /* In this case the format string is not known at compile time,
421      but resides in read-only memory, so is ok.  */
422   if (fprintf (fp, str3, str4, &n1, str5, &n2) != 14
423       || n1 != 7 || n2 != 14)
424     FAIL ();
425
426   strcpy (buf2 + 2, "%n%s%n");
427   /* When the format string is writable and contains %n,
428      with -D_FORTIFY_SOURCE=2 it causes __chk_fail.  */
429   CHK_FAIL2_START
430   if (fprintf (fp, buf2, str4, &n1, str5, &n1) != 14)
431     FAIL ();
432   CHK_FAIL2_END
433
434   /* But if there is no %n, even writable format string
435      should work.  */
436   buf2[6] = '\0';
437   if (fprintf (fp, buf2 + 4, str5) != 7)
438     FAIL ();
439
440   if (freopen (temp_filename, "r", stdin) == NULL)
441     {
442       puts ("could not open temporary file");
443       exit (1);
444     }
445
446   if (gets (buf) != buf || memcmp (buf, "abcdefgh", 9))
447     FAIL ();
448   if (gets (buf) != buf || memcmp (buf, "ABCDEFGHI", 10))
449     FAIL ();
450
451 #if __USE_FORTIFY_LEVEL >= 1
452   CHK_FAIL_START
453   if (gets (buf) != buf)
454     FAIL ();
455   CHK_FAIL_END
456 #endif
457
458   if (freopen (temp_filename, "r", stdin) == NULL)
459     {
460       puts ("could not open temporary file");
461       exit (1);
462     }
463
464   if (fseek (stdin, 9 + 10 + 11, SEEK_SET))
465     {
466       puts ("could not seek in test file");
467       exit (1);
468     }
469
470 #if __USE_FORTIFY_LEVEL >= 1
471   CHK_FAIL_START
472   if (gets (buf) != buf)
473     FAIL ();
474   CHK_FAIL_END
475 #endif
476
477   return ret;
478 }