111
|
1 /* { dg-do compile } */
|
|
2 /* { dg-options "-O2 -Wformat -Wformat-overflow=2 -ftrack-macro-expansion=0" } */
|
|
3
|
|
4 typedef __SIZE_TYPE__ size_t;
|
|
5
|
|
6 #define INT_MAX __INT_MAX__
|
|
7 #define INT_MIN (-INT_MAX - 1)
|
|
8
|
|
9 #ifndef LINE
|
|
10 # define LINE 0
|
|
11 #endif
|
|
12
|
|
13 int dummy_sprintf (char*, const char*, ...);
|
|
14 void sink (void*);
|
|
15
|
|
16 char buffer[4096];
|
|
17 char *ptr;
|
|
18
|
|
19 /* Helper to expand function to either __builtin_f or dummy_f to
|
|
20 make debugging GCC easy. */
|
|
21 #define FUNC(f) \
|
|
22 ((!LINE || LINE == __LINE__) ? __builtin_ ## f : dummy_ ## f)
|
|
23
|
|
24 /* Evaluate to an array of SIZE characters when non-negative, or to
|
|
25 a pointer to an unknown object otherwise. */
|
|
26 #define buffer(size) \
|
|
27 ((0 <= size) ? buffer + sizeof buffer - (size) : ptr)
|
|
28
|
|
29 #define T(bufsize, fmt, ...) \
|
|
30 do { \
|
|
31 char *buf = buffer (bufsize); \
|
|
32 FUNC (sprintf)(buf, fmt, __VA_ARGS__); \
|
|
33 sink (buf); \
|
|
34 } while (0)
|
|
35
|
|
36
|
|
37 /* Identity function to verify that the checker figures out the value
|
|
38 of the operand even when it's not constant (i.e., makes use of
|
|
39 inlining and constant propagation information). */
|
|
40
|
131
|
41 static int i (int x) { return x; }
|
|
42 static const char* s (const char *str) { return str; }
|
111
|
43
|
|
44 /* Function to "generate" a unique unknown number (as far as GCC can
|
|
45 tell) each time it's called. It prevents the optimizer from being
|
|
46 able to narrow down the ranges of possible values in test functions
|
|
47 with repeated references to the same variable. */
|
|
48 extern int value (void);
|
|
49
|
|
50 /* Return a value in the range [MIN, MAX]. */
|
131
|
51 static int range (int min, int max)
|
111
|
52 {
|
|
53 int val = value ();
|
|
54 return val < min || max < val ? min : val;
|
|
55 }
|
|
56
|
|
57 #define R(min, max) range (min, max)
|
|
58
|
|
59 /* Verify that the checker can detect buffer overflow when the "%s"
|
|
60 argument is in a known range of lengths and one or both of which
|
|
61 exceed the size of the destination. */
|
|
62
|
|
63 void test_sprintf_chk_string (const char *s)
|
|
64 {
|
|
65 T (1, "%*s", R (0, 1), ""); /* { dg-warning "may write a terminating nul" } */
|
|
66 T (1, "%*s", R (-2, -1), ""); /* { dg-warning "writing up to 2 bytes" } */
|
|
67 T (1, "%*s", R (-3, 2), ""); /* { dg-warning "writing up to 3 bytes" } */
|
|
68 T (1, "%*s", R (-4, 5), ""); /* { dg-warning "writing up to 5 bytes" } */
|
|
69
|
|
70 T (1, "%*s", R ( -5, 6), "1"); /* { dg-warning "writing between 1 and 6 bytes" } */
|
|
71 T (1, "%*s", R ( -6, 7), "12"); /* { dg-warning "writing between 2 and 7 bytes" } */
|
|
72
|
|
73 T (1, "%.*s", R (0, 1), "");
|
|
74 T (1, "%.*s", R (0, 1), s); /* { dg-warning "may write a terminating nul" } */
|
|
75 T (1, "%.*s", R (-2, -1), "");
|
|
76 T (1, "%.*s", R (-2, -1), s); /* { dg-warning "may write a terminating nul" } */
|
|
77 T (1, "%.*s", R (-3, 2), "");
|
|
78 T (1, "%.*s", R (-4, 5), "");
|
|
79
|
|
80 T (1, "%.*s", R ( -5, 6), "1"); /* { dg-warning "may write a terminating nul" } */
|
|
81 T (1, "%.*s", R ( -6, 7), "12"); /* { dg-warning "writing up to 2 bytes " } */
|
|
82 T (1, "%.*s", R ( 1, 7), "12"); /* { dg-warning "writing between 1 and 2 bytes " } */
|
|
83 T (1, "%.*s", R ( 2, 7), "12"); /* { dg-warning "writing 2 bytes " } */
|
|
84
|
|
85 T (1, "%*.*s", R (0, 1), R (0, 1), ""); /* { dg-warning "may write a terminating nul" } */
|
|
86 T (1, "%*.*s", R (0, 2), R (0, 1), ""); /* { dg-warning "directive writing up to 2 bytes into a region of size 1" } */
|
|
87 T (1, "%*.*s", R (0, 3), R (0, 1), ""); /* { dg-warning "writing up to 3 bytes" } */
|
|
88
|
|
89 T (1, "%*.*s", R (0, 1), R (0, 1), "1"); /* { dg-warning "may write a terminating nul" } */
|
|
90 T (1, "%*.*s", R (0, 2), R (0, 1), "1"); /* { dg-warning "writing up to 2 bytes" } */
|
|
91 T (1, "%*.*s", R (0, 3), R (0, 1), "1"); /* { dg-warning "writing up to 3 bytes" } */
|
|
92
|
|
93 T (1, "%*.*s", R (0, 1), R (0, 1), "12"); /* { dg-warning "may write a terminating nul" } */
|
|
94 T (1, "%*.*s", R (0, 2), R (0, 1), "12"); /* { dg-warning "writing up to 2 bytes" } */
|
|
95 T (1, "%*.*s", R (0, 3), R (0, 1), "12"); /* { dg-warning "writing up to 3 bytes" } */
|
|
96
|
|
97 T (1, "%*.*s", R (0, 1), R (0, 1), "123"); /* { dg-warning "may write a terminating nul" } */
|
|
98 T (1, "%*.*s", R (0, 2), R (0, 1), "123"); /* { dg-warning "writing up to 2 bytes" } */
|
|
99 T (1, "%*.*s", R (0, 3), R (0, 1), "123"); /* { dg-warning "writing up to 3 bytes" } */
|
|
100 T (1, "%*.*s", R (0, 3), R (0, 1), s); /* { dg-warning "writing up to 3 bytes" } */
|
|
101
|
|
102 T (1, "%*.*s", R (0, 1), R (0, 2), "123"); /* { dg-warning "writing up to 2 bytes" } */
|
|
103 T (1, "%*.*s", R (0, 2), R (0, 2), "123"); /* { dg-warning "writing up to 2 bytes" } */
|
|
104 T (1, "%*.*s", R (0, 3), R (0, 2), "123"); /* { dg-warning "writing up to 3 bytes" } */
|
|
105 T (1, "%*.*s", R (0, 3), R (0, 2), s); /* { dg-warning "writing up to 3 bytes" } */
|
|
106
|
|
107 T (1, "%*.*s", R (0, 1), R (0, 3), "123"); /* { dg-warning "writing up to 3 bytes" } */
|
|
108 T (1, "%*.*s", R (0, 2), R (0, 3), "123"); /* { dg-warning "writing up to 3 bytes" } */
|
|
109 T (1, "%*.*s", R (0, 3), R (0, 3), "123"); /* { dg-warning "writing up to 3 bytes" } */
|
|
110 T (1, "%*.*s", R (0, 3), R (0, 3), s); /* { dg-warning "writing up to 3 bytes" } */
|
|
111
|
|
112 T (1, "%*.*s", R (1, 1), R (0, 3), "123"); /* { dg-warning "writing between 1 and 3 bytes" } */
|
|
113 T (1, "%*.*s", R (1, 2), R (0, 3), "123"); /* { dg-warning "writing between 1 and 3 bytes" } */
|
|
114 T (1, "%*.*s", R (1, 3), R (0, 3), "123"); /* { dg-warning "writing between 1 and 3 bytes" } */
|
|
115 T (1, "%*.*s", R (1, 3), R (0, 3), s); /* { dg-warning "writing between 1 and 3 bytes" } */
|
|
116
|
|
117 T (1, "%*.*s", R (1, 1), R (1, 3), "123"); /* { dg-warning "writing between 1 and 3 bytes" } */
|
|
118 T (1, "%*.*s", R (1, 2), R (1, 3), "123"); /* { dg-warning "writing between 1 and 3 bytes" } */
|
|
119 T (1, "%*.*s", R (1, 3), R (1, 3), "123"); /* { dg-warning "writing between 1 and 3 bytes" } */
|
|
120 T (1, "%*.*s", R (1, 3), R (1, 3), s); /* { dg-warning "writing between 1 and 3 bytes" } */
|
|
121
|
|
122 T (1, "%*.*s", R (2, 3), R (1, 3), "123"); /* { dg-warning "writing between 2 and 3 bytes" } */
|
|
123 T (1, "%*.*s", R (3, 4), R (1, 3), "123"); /* { dg-warning "writing between 3 and 4 bytes" } */
|
|
124 T (1, "%*.*s", R (4, 5), R (1, 3), "123"); /* { dg-warning "writing between 4 and 5 bytes" } */
|
|
125 T (1, "%*.*s", R (2, 3), R (1, 3), s); /* { dg-warning "writing between 2 and 3 bytes" } */
|
|
126 }
|
|
127
|
|
128 void test_sprintf_chk_int (int w, int p, int i)
|
|
129 {
|
|
130 T (1, "%*d", w, 0); /* { dg-warning "may write a terminating nul|directive writing between 1 and \[0-9\]+ bytes" } */
|
|
131 T (1, "%*d", w, i); /* { dg-warning "may write a terminating nul|directive writing between 1 and \[0-9\]+ bytes" } */
|
|
132
|
|
133 T (1, "%*d", R (-1, 1), 0); /* { dg-warning "writing a terminating nul" } */
|
|
134 T (1, "%*d", R ( 0, 1), 0); /* { dg-warning "writing a terminating nul" } */
|
|
135 T (1, "%+*d", R ( 0, 1), 0); /* { dg-warning "directive writing 2 bytes" } */
|
|
136 T (1, "%+*u", R ( 0, 1), 0); /* { dg-warning "writing a terminating nul" } */
|
|
137 T (2, "%*d", R (-3, -2), 0); /* { dg-warning "directive writing between 1 and 3 bytes" } */
|
|
138 T (2, "%*d", R (-3, -1), 0); /* { dg-warning "directive writing between 1 and 3 bytes" } */
|
|
139 T (2, "%*d", R (-3, 0), 0); /* { dg-warning "directive writing between 1 and 3 bytes" } */
|
|
140 T (2, "%*d", R (-2, -1), 0); /* { dg-warning "may write a terminating nul" } */
|
|
141 T (2, "%*d", R (-2, 2), 0); /* { dg-warning "may write a terminating nul" } */
|
|
142 T (2, "%*d", R (-1, 2), 0); /* { dg-warning "may write a terminating nul" } */
|
|
143 T (2, "%*d", R ( 0, 2), 0); /* { dg-warning "may write a terminating nul" } */
|
|
144 T (2, "%*d", R ( 1, 2), 0); /* { dg-warning "may write a terminating nul" } */
|
|
145
|
|
146 T (1, "%.*d", p, 0); /* { dg-warning "may write a terminating nul|directive writing up to \[0-9\]+ bytes" } */
|
|
147 T (1, "%.*d", p, i); /* { dg-warning "may write a terminating nul||directive writing up to \[0-9\]+ bytes" } */
|
|
148 T (1, "%.*d", R (INT_MIN, -1), 0); /* { dg-warning "writing a terminating nul" } */
|
|
149 T (1, "%.*d", R (INT_MIN, 0), 0); /* { dg-warning "may write a terminating nul" } */
|
|
150 T (1, "%.*d", R (-2, -1), 0); /* { dg-warning "writing a terminating nul" } */
|
|
151 T (1, "%.*d", R (-1, 1), 0); /* { dg-warning "may write a terminating nul" } */
|
|
152 T (1, "%.*d", R ( 0, 1), 0); /* { dg-warning "may write a terminating nul" } */
|
|
153 T (1, "%.*d", R ( 0, 2), 0); /* { dg-warning "directive writing up to 2 bytes" } */
|
|
154 T (1, "%.*d", R ( 0, INT_MAX - 1), 0); /* { dg-warning "directive writing up to \[0-9\]+ bytes" } */
|
|
155 T (1, "%.*d", R ( 1, INT_MAX - 1), 0); /* { dg-warning "directive writing between 1 and \[0-9\]+ bytes" } */
|
|
156 }
|
|
157
|
|
158 /* { dg-prune-output "flag used with .%.. gnu_printf format" } */
|