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