1/* Copyright (C) 2004, 2005 Free Software Foundation. 2 3 Ensure builtin __strncat_chk performs correctly. */ 4 5extern void abort (void); 6typedef __SIZE_TYPE__ size_t; 7extern size_t strlen (const char *); 8extern void *memcpy (void *, const void *, size_t); 9extern char *strcat (char *, const char *); 10extern char *strncat (char *, const char *, size_t); 11extern int memcmp (const void *, const void *, size_t); 12extern char *strcpy (char *, const char *); 13extern int strcmp (const char *, const char *); 14extern void *memset (void *, int, size_t); 15 16#include "chk.h" 17 18const char s1[] = "123"; 19char p[32] = ""; 20char *s2 = "defg"; 21char *s3 = "FGH"; 22char *s4; 23size_t l1 = 1; 24char *s5; 25int x = 123; 26 27void 28__attribute__((noinline)) 29test1 (void) 30{ 31 const char *const s1 = "hello world"; 32 const char *const s2 = ""; 33 const char *s3; 34 char dst[64], *d2; 35 36 /* Following strncat calls should be all optimized out. */ 37 chk_calls = 0; 38 strncat_disallowed = 1; 39 strcat_disallowed = 1; 40 strcpy (dst, s1); 41 if (strncat (dst, "", 100) != dst || strcmp (dst, s1)) 42 abort (); 43 strcpy (dst, s1); 44 if (strncat (dst, s2, 100) != dst || strcmp (dst, s1)) 45 abort (); 46 strcpy (dst, s1); d2 = dst; 47 if (strncat (++d2, s2, 100) != dst+1 || d2 != dst+1 || strcmp (dst, s1)) 48 abort (); 49 strcpy (dst, s1); d2 = dst; 50 if (strncat (++d2+5, s2, 100) != dst+6 || d2 != dst+1 || strcmp (dst, s1)) 51 abort (); 52 strcpy (dst, s1); d2 = dst; 53 if (strncat (++d2+5, s1+11, 100) != dst+6 || d2 != dst+1 || strcmp (dst, s1)) 54 abort (); 55 strcpy (dst, s1); d2 = dst; 56 if (strncat (++d2+5, s1, 0) != dst+6 || d2 != dst+1 || strcmp (dst, s1)) 57 abort (); 58 strcpy (dst, s1); d2 = dst; s3 = s1; 59 if (strncat (++d2+5, ++s3, 0) != dst+6 || d2 != dst+1 || strcmp (dst, s1) 60 || s3 != s1 + 1) 61 abort (); 62 strcpy (dst, s1); d2 = dst; 63 if (strncat (++d2+5, "", ++x) != dst+6 || d2 != dst+1 || x != 124 64 || strcmp (dst, s1)) 65 abort (); 66 if (chk_calls) 67 abort (); 68 strcat_disallowed = 0; 69 70 /* These __strncat_chk calls should be optimized into __strcat_chk, 71 as strlen (src) <= len. */ 72 strcpy (dst, s1); 73 if (strncat (dst, "foo", 3) != dst || strcmp (dst, "hello worldfoo")) 74 abort (); 75 strcpy (dst, s1); 76 if (strncat (dst, "foo", 100) != dst || strcmp (dst, "hello worldfoo")) 77 abort (); 78 strcpy (dst, s1); 79 if (strncat (dst, s1, 100) != dst || strcmp (dst, "hello worldhello world")) 80 abort (); 81 if (chk_calls != 3) 82 abort (); 83 84 chk_calls = 0; 85 /* The following calls have side-effects in dest, so are not checked. */ 86 strcpy (dst, s1); d2 = dst; 87 if (__builtin___strncat_chk (++d2, s1, 100, os (++d2)) != dst+1 88 || d2 != dst+1 || strcmp (dst, "hello worldhello world")) 89 abort (); 90 strcpy (dst, s1); d2 = dst; 91 if (__builtin___strncat_chk (++d2+5, s1, 100, os (++d2+5)) != dst+6 92 || d2 != dst+1 || strcmp (dst, "hello worldhello world")) 93 abort (); 94 strcpy (dst, s1); d2 = dst; 95 if (__builtin___strncat_chk (++d2+5, s1+5, 100, os (++d2+5)) != dst+6 96 || d2 != dst+1 || strcmp (dst, "hello world world")) 97 abort (); 98 if (chk_calls) 99 abort (); 100 101 chk_calls = 0; 102 strcat_disallowed = 1; 103 104 /* Test at least one instance of the __builtin_ style. We do this 105 to ensure that it works and that the prototype is correct. */ 106 strcpy (dst, s1); 107 if (__builtin_strncat (dst, "", 100) != dst || strcmp (dst, s1)) 108 abort (); 109 110 if (chk_calls) 111 abort (); 112 strncat_disallowed = 0; 113 strcat_disallowed = 0; 114} 115 116/* Test whether compile time checking is done where it should 117 and so is runtime object size checking. */ 118void 119__attribute__((noinline)) 120test2 (void) 121{ 122 struct A { char buf1[10]; char buf2[10]; } a; 123 char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4]; 124 char buf3[20]; 125 int i; 126 127 /* The following calls should do runtime checking. */ 128 memset (&a, '\0', sizeof (a)); 129 s5 = (char *) &a; 130 __asm __volatile ("" : : "r" (s5) : "memory"); 131 chk_calls = 0; 132 strncat (a.buf1 + 2, s3 + 3, l1 - 1); 133 strncat (r, s3 + 2, l1); 134 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7]; 135 memset (r, '\0', 3); 136 __asm __volatile ("" : : "r" (r) : "memory"); 137 strncat (r, s2 + 2, l1 + 1); 138 strncat (r + 2, s3 + 3, l1 - 1); 139 r = buf3; 140 for (i = 0; i < 4; ++i) 141 { 142 if (i == l1 - 1) 143 r = &a.buf1[1]; 144 else if (i == l1) 145 r = &a.buf2[7]; 146 else if (i == l1 + 1) 147 r = &buf3[5]; 148 else if (i == l1 + 2) 149 r = &a.buf1[9]; 150 } 151 strncat (r, s2 + 4, l1); 152 if (chk_calls != 5) 153 abort (); 154 155 /* Following have known destination and known source length, 156 but we don't know the length of dest string, so runtime checking 157 is needed too. */ 158 memset (&a, '\0', sizeof (a)); 159 chk_calls = 0; 160 s5 = (char *) &a; 161 __asm __volatile ("" : : "r" (s5) : "memory"); 162 strncat (a.buf1 + 2, "a", 5); 163 strncat (r, "def", 0); 164 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7]; 165 memset (r, '\0', 3); 166 __asm __volatile ("" : : "r" (r) : "memory"); 167 strncat (r, s1 + 1, 2); 168 if (chk_calls != 2) 169 abort (); 170 chk_calls = 0; 171 strcat_disallowed = 1; 172 /* Unknown destination and source, no checking. */ 173 strncat (s4, s3, l1 + 1); 174 strcat_disallowed = 0; 175 if (chk_calls) 176 abort (); 177} 178 179/* Test whether runtime and/or compile time checking catches 180 buffer overflows. */ 181void 182__attribute__((noinline)) 183test3 (void) 184{ 185 struct A { char buf1[10]; char buf2[10]; } a; 186 char buf3[20]; 187 188 memset (&a, '\0', sizeof (a)); 189 memset (buf3, '\0', sizeof (buf3)); 190 s5 = (char *) &a; 191 __asm __volatile ("" : : "r" (s5) : "memory"); 192 s5 = buf3; 193 __asm __volatile ("" : : "r" (s5) : "memory"); 194 chk_fail_allowed = 1; 195 /* Runtime checks. */ 196 if (__builtin_setjmp (chk_fail_buf) == 0) 197 { 198 strncat (&a.buf2[9], s2 + 3, 4); 199 abort (); 200 } 201 if (__builtin_setjmp (chk_fail_buf) == 0) 202 { 203 strncat (&a.buf2[7], s3 + strlen (s3) - 3, 3); 204 abort (); 205 } 206 if (__builtin_setjmp (chk_fail_buf) == 0) 207 { 208 strncat (&buf3[19], "abcde", 1); 209 abort (); 210 } 211 chk_fail_allowed = 0; 212} 213 214void 215main_test (void) 216{ 217#ifndef __OPTIMIZE__ 218 /* Object size checking is only intended for -O[s123]. */ 219 return; 220#endif 221 __asm ("" : "=r" (s2) : "0" (s2)); 222 __asm ("" : "=r" (s3) : "0" (s3)); 223 __asm ("" : "=r" (l1) : "0" (l1)); 224 s4 = p; 225 test1 (); 226 memset (p, '\0', sizeof (p)); 227 test2 (); 228 test3 (); 229} 230