1 /* Copyright (C) 2004, 2005 Free Software Foundation.
3 Ensure builtin __snprintf_chk performs correctly. */
5 extern void abort (void);
6 typedef __SIZE_TYPE__
size_t;
7 extern size_t strlen(const char *);
8 extern void *memcpy (void *, const void *, size_t);
9 extern char *strcpy (char *, const char *);
10 extern int memcmp (const void *, const void *, size_t);
11 extern void *memset (void *, int, size_t);
12 extern int sprintf (char *, const char *, ...);
13 extern int snprintf (char *, size_t, const char *, ...);
17 const char s1
[] = "123";
23 static char buffer
[32];
24 char * volatile ptr
= "barf"; /* prevent constant propagation to happen when whole program assumptions are made. */
27 __attribute__((noinline
))
31 /* snprintf_disallowed = 1; */
33 memset (buffer
, 'A', 32);
34 snprintf (buffer
, 4, "foo");
35 if (memcmp (buffer
, "foo", 4) || buffer
[4] != 'A')
38 memset (buffer
, 'A', 32);
39 if (snprintf (buffer
, 4, "foo bar") != 7)
41 if (memcmp (buffer
, "foo", 4) || buffer
[4] != 'A')
44 memset (buffer
, 'A', 32);
45 snprintf (buffer
, 32, "%s", "bar");
46 if (memcmp (buffer
, "bar", 4) || buffer
[4] != 'A')
49 memset (buffer
, 'A', 32);
50 if (snprintf (buffer
, 21, "%s", "bar") != 3)
52 if (memcmp (buffer
, "bar", 4) || buffer
[4] != 'A')
55 snprintf_disallowed
= 0;
57 memset (buffer
, 'A', 32);
58 if (snprintf (buffer
, 4, "%d%d%d", (int) l1
, (int) l1
+ 1, (int) l1
+ 12)
61 if (memcmp (buffer
, "121", 4) || buffer
[4] != 'A')
64 memset (buffer
, 'A', 32);
65 if (snprintf (buffer
, 32, "%d%d%d", (int) l1
, (int) l1
+ 1, (int) l1
+ 12)
68 if (memcmp (buffer
, "1213", 5) || buffer
[5] != 'A')
74 memset (buffer
, 'A', 32);
75 snprintf (buffer
, strlen (ptr
) + 1, "%s", ptr
);
76 if (memcmp (buffer
, "barf", 5) || buffer
[5] != 'A')
79 memset (buffer
, 'A', 32);
80 snprintf (buffer
, l1
+ 31, "%d - %c", (int) l1
+ 27, *ptr
);
81 if (memcmp (buffer
, "28 - b\0AAAAA", 12))
89 snprintf (s4
, l1
+ 6, "%d - %c", (int) l1
- 17, ptr
[1]);
90 if (memcmp (s4
, "-16 - \0AAA", 10))
96 /* Test whether compile time checking is done where it should
97 and so is runtime object size checking. */
99 __attribute__((noinline
))
102 struct A
{ char buf1
[10]; char buf2
[10]; } a
;
103 char *r
= l1
== 1 ? &a
.buf1
[5] : &a
.buf2
[4];
107 /* The following calls should do runtime checking
108 - length is not known, but destination is. */
110 snprintf (a
.buf1
+ 2, l1
, "%s", s3
+ 3);
111 snprintf (r
, l1
+ 4, "%s%c", s3
+ 3, s3
[3]);
112 r
= l1
== 1 ? __builtin_alloca (4) : &a
.buf2
[7];
113 snprintf (r
, strlen (s2
) - 2, "%c %s", s2
[2], s2
+ 4);
114 snprintf (r
+ 2, l1
, s3
+ 3);
116 for (i
= 0; i
< 4; ++i
)
122 else if (i
== l1
+ 1)
124 else if (i
== l1
+ 2)
127 snprintf (r
, l1
, s2
+ 4);
131 /* Following have known destination and known source length,
132 so if optimizing certainly shouldn't result in the checking
135 /* snprintf_disallowed = 1; */
136 snprintf (a
.buf1
+ 2, 4, "");
137 snprintf (r
, 1, "a");
138 r
= l1
== 1 ? __builtin_alloca (4) : &a
.buf2
[7];
139 snprintf (r
, 3, "%s", s1
+ 1);
141 for (i
= 0; i
< 4; ++i
)
147 else if (i
== l1
+ 1)
149 else if (i
== l1
+ 2)
152 snprintf (r
, 1, "%s", "");
153 snprintf (r
, 0, "%s", "");
154 snprintf_disallowed
= 0;
155 /* Unknown destination and source, no checking. */
156 snprintf (s4
, l1
+ 31, "%s %d", s3
, 0);
161 /* Test whether runtime and/or compile time checking catches
164 __attribute__((noinline
))
167 struct A
{ char buf1
[10]; char buf2
[10]; } a
;
170 chk_fail_allowed
= 1;
171 /* Runtime checks. */
172 if (__builtin_setjmp (chk_fail_buf
) == 0)
174 snprintf (&a
.buf2
[9], l1
+ 1, "%c%s", s2
[3], s2
+ 4);
177 if (__builtin_setjmp (chk_fail_buf
) == 0)
179 snprintf (&a
.buf2
[7], l1
+ 30, "%s%c", s3
+ strlen (s3
) - 2, *s3
);
182 if (__builtin_setjmp (chk_fail_buf
) == 0)
184 snprintf (&a
.buf2
[7], l1
+ 3, "%d", (int) l1
+ 9999);
187 /* This should be detectable at compile time already. */
188 if (__builtin_setjmp (chk_fail_buf
) == 0)
190 snprintf (&buf3
[19], 2, "a");
193 if (__builtin_setjmp (chk_fail_buf
) == 0)
195 snprintf (&buf3
[17], 4, "a");
198 if (__builtin_setjmp (chk_fail_buf
) == 0)
200 snprintf (&buf3
[17], 4, "%s", "abc");
203 chk_fail_allowed
= 0;
210 /* Object size checking is only intended for -O[s123]. */
213 __asm ("" : "=r" (s2
) : "0" (s2
));
214 __asm ("" : "=r" (s3
) : "0" (s3
));
215 __asm ("" : "=r" (l1
) : "0" (l1
));