111
|
1 /* PR middle-end/79376 - wrong lower bound with %s and non-constant
|
|
2 strings in -Wformat-overflow
|
|
3 { dg-do compile }
|
|
4 { dg-options "-O2 -Wall -Wformat-overflow=1 -ftrack-macro-expansion=0" } */
|
|
5
|
|
6 typedef __SIZE_TYPE__ size_t;
|
|
7
|
|
8 #define INT_MAX __INT_MAX__
|
|
9 #define INT_MIN (-INT_MAX - 1)
|
|
10
|
|
11 /* When debugging, define LINE to the line number of the test case to exercise
|
|
12 and avoid exercising any of the others. The buffer and objsize macros
|
|
13 below make use of LINE to avoid warnings for other lines. */
|
|
14 #ifndef LINE
|
|
15 # define LINE 0
|
|
16 #endif
|
|
17
|
|
18 extern int int_value (void);
|
|
19
|
131
|
20 static int int_range (int min, int max)
|
111
|
21 {
|
|
22 int n = int_value ();
|
|
23 return n < min || max < n ? min : n;
|
|
24 }
|
|
25
|
131
|
26 static const char*
|
111
|
27 choose_string (const char *s1, const char *s2, const char *s3)
|
|
28 {
|
|
29 int i = int_value ();
|
|
30 return i < 0 ? s1 : 0 < i ? s3 : s2;
|
|
31 }
|
|
32
|
|
33 void sink (char*, char*);
|
|
34
|
|
35 int dummy_sprintf (char*, const char*, ...);
|
|
36
|
|
37 char buffer [256];
|
|
38 extern char *ptr;
|
|
39
|
|
40 const char s0[] = "";
|
|
41 const char s1[] = "1";
|
|
42 const char s2[] = "12";
|
|
43 const char s3[] = "123";
|
|
44 const char s4[] = "1234";
|
|
45 const char s5[] = "12345";
|
|
46 const char s6[] = "123456";
|
|
47 const char s7[] = "1234567";
|
|
48 const char s8[] = "12345678";
|
|
49 const char s9[] = "123456789";
|
|
50 extern const char sx[];
|
|
51 extern const char sy[];
|
|
52
|
|
53 /* Evaluate to an array of SIZE characters when non-negative, or to
|
|
54 a pointer to an unknown object otherwise. */
|
|
55 #define buffer(size) \
|
|
56 ((0 <= size) ? buffer + sizeof buffer - (size) : ptr)
|
|
57
|
|
58 /* Helper to expand function to either __builtin_f or dummy_f to
|
|
59 make debugging GCC easy. */
|
|
60 #define FUNC(f) \
|
|
61 ((!LINE || LINE == __LINE__) ? __builtin_ ## f : dummy_ ## f)
|
|
62
|
|
63 /* Macro to verify that calls to __builtin_sprintf (i.e., with no size
|
|
64 argument) issue diagnostics by correctly determining the size of
|
|
65 the destination buffer. */
|
|
66 #define T(size, ...) \
|
|
67 (FUNC (sprintf) (buffer (size), __VA_ARGS__), \
|
|
68 sink (buffer, ptr))
|
|
69
|
|
70 /* Return a value in the range [MIN, MAX]. */
|
|
71 #define R(min, max) int_range (min, max)
|
|
72
|
|
73 /* Return one of the strings S1, S2, S3. */
|
|
74 #define S(s1, s2, s3) choose_string (s1, s2, s3)
|
|
75
|
|
76 struct S {
|
|
77 char a1[1];
|
|
78 char a2[2];
|
|
79 char a3[3];
|
|
80 char a4[4];
|
|
81 char a5[5];
|
|
82 char ax[];
|
|
83 };
|
|
84
|
|
85 void test_strings (struct S *s)
|
|
86 {
|
|
87 T (0, "%-s", S (s->a1, s->a1, s1)); /* { dg-warning "writing up to 1 byte" } */
|
|
88 T (0, "%-s", S (s->a1, s->a2, s1)); /* { dg-warning "writing up to 1 byte" } */
|
|
89 T (0, "%-s", S (s->a2, s->a1, s1)); /* { dg-warning "writing up to 1 byte" } */
|
|
90
|
|
91 T (0, "%-s", S (s->a1, s1, s->a1)); /* { dg-warning "writing up to 1 byte" } */
|
|
92 T (0, "%-s", S (s->a1, s1, s->a2)); /* { dg-warning "writing up to 1 byte" } */
|
|
93 T (0, "%-s", S (s->a2, s1, s->a1)); /* { dg-warning "writing up to 1 byte" } */
|
|
94
|
|
95 T (0, "%-s", S (s1, s->a1, s1)); /* { dg-warning "writing up to 1 byte" } */
|
|
96 T (0, "%-s", S (s1, s->a1, s1)); /* { dg-warning "writing up to 1 byte" } */
|
|
97 T (0, "%-s", S (s1, s->a2, s1)); /* { dg-warning "writing up to 1 byte" } */
|
|
98
|
|
99 T (0, "%-s", S (s->a1, s->a1, s2)); /* { dg-warning "writing up to 2 bytes" } */
|
|
100 T (0, "%-s", S (s->a1, s->a2, s2)); /* { dg-warning "writing up to 2 bytes" } */
|
|
101 T (0, "%-s", S (s->a2, s->a1, s2)); /* { dg-warning "writing up to 2 bytes" } */
|
|
102
|
|
103 T (0, "%-s", S (s->a1, s2, s->a1)); /* { dg-warning "writing up to 2 bytes" } */
|
|
104 T (0, "%-s", S (s->a1, s2, s->a2)); /* { dg-warning "writing up to 2 bytes" } */
|
|
105 T (0, "%-s", S (s->a2, s2, s->a1)); /* { dg-warning "writing up to 2 bytes" } */
|
|
106
|
|
107 T (0, "%-s", S (s2, s->a1, s1)); /* { dg-warning "writing up to 2 bytes" } */
|
|
108 T (0, "%-s", S (s2, s->a1, s1)); /* { dg-warning "writing up to 2 bytes" } */
|
|
109 T (0, "%-s", S (s2, s->a2, s1)); /* { dg-warning "writing up to 2 bytes" } */
|
|
110
|
|
111 T (0, "%-s", S (s->a1, s->a1, s2)); /* { dg-warning "writing up to 2 bytes" } */
|
|
112 T (0, "%-s", S (s->a1, s->a2, s2)); /* { dg-warning "writing up to 2 bytes" } */
|
|
113 T (0, "%-s", S (s->a2, s->a1, s2)); /* { dg-warning "writing up to 2 bytes" } */
|
|
114
|
|
115 T (0, "%-s", S (s->a1, s2, s->a1)); /* { dg-warning "writing up to 2 bytes" } */
|
|
116 T (0, "%-s", S (s->a1, s2, s->a2)); /* { dg-warning "writing up to 2 bytes" } */
|
|
117 T (0, "%-s", S (s->a2, s2, s->a1)); /* { dg-warning "writing up to 2 bytes" } */
|
|
118
|
|
119 T (0, "%-s", S (s2, s->a1, s1)); /* { dg-warning "writing up to 2 bytes" } */
|
|
120 T (0, "%-s", S (s3, s->a1, s2)); /* { dg-warning "writing up to 3 bytes" } */
|
|
121 T (0, "%-s", S (s4, s->a2, s3)); /* { dg-warning "writing up to 4 bytes" } */
|
|
122
|
|
123 T (0, "%-s", S (s->a3, s->a5, s3)); /* { dg-warning "writing up to 4 bytes" } */
|
|
124 T (0, "%-s", S (s->a3, s->a5, s3)); /* { dg-warning "writing up to 4 bytes" } */
|
|
125 T (0, "%-s", S (s->a3, s->a5, s3)); /* { dg-warning "writing up to 4 bytes" } */
|
|
126
|
|
127 T (0, "%-s", S (s->a3, s3, s->a5)); /* { dg-warning "writing up to 4 bytes" } */
|
|
128 T (0, "%-s", S (s->a5, s3, s->a3)); /* { dg-warning "writing up to 4 bytes" } */
|
|
129 T (0, "%-s", S (s->a3, s3, s->a5)); /* { dg-warning "writing up to 4 bytes" } */
|
|
130
|
|
131 T (0, "%-s", S (s3, s->a1, s4)); /* { dg-warning "writing up to 4 bytes" } */
|
|
132 T (0, "%-s", S (s4, s->a2, s3)); /* { dg-warning "writing up to 4 bytes" } */
|
|
133 }
|
|
134
|
|
135 void test_strings_with_width (struct S *s)
|
|
136 {
|
|
137 T (0, "%*s", /* { dg-warning "writing up to 4 bytes" } */
|
|
138 R (0, 1),
|
|
139 S (s->a3, s->a5, s3));
|
|
140
|
|
141 T (0, "%*s", /* { dg-warning "writing up to 4 bytes" } */
|
|
142 R (0, 4),
|
|
143 S (s->a3, s->a5, s3));
|
|
144
|
|
145 T (0, "%*s", /* { dg-warning "writing between 1 and 4 bytes" } */
|
|
146 R (1, 4),
|
|
147 S (s->a3, s->a5, s3));
|
|
148
|
|
149 T (0, "%*s", /* { dg-warning "writing between 2 and 4 bytes" } */
|
|
150 R (2, 4),
|
|
151 S (s->a3, s->a5, s3));
|
|
152
|
|
153 T (0, "%*s", /* { dg-warning "writing between 3 and 4 bytes" } */
|
|
154 R (3, 4),
|
|
155 S (s->a3, s->a5, s3));
|
|
156
|
|
157 T (0, "%*s", /* { dg-warning "writing between 3 and 5 bytes" } */
|
|
158 R (3, 5),
|
|
159 S (s->a3, s->a5, s3));
|
|
160
|
|
161 T (0, "%*s", /* { dg-warning "writing between 3 and 9 bytes" } */
|
|
162 R (3, 9),
|
|
163 S (s->a3, s->a5, s3));
|
|
164
|
|
165 T (3, "%*s", /* { dg-warning "writing between 3 and 9 bytes" } */
|
|
166 R (3, 9),
|
|
167 S (s->a3, s->a5, s3));
|
|
168
|
|
169 /* The longest string fits but the terminating nul will overflow. Since
|
|
170 the null won't overflow with the shorter strings the warning is a "may
|
|
171 write." */
|
|
172 T (4, "%*s", /* { dg-warning "may write a terminating nul" } */
|
|
173 R (3, 9),
|
|
174 S (s->a3, s->a5, s3));
|
|
175 }
|
|
176
|
|
177 void test_strings_with_width_and_precisin (struct S *s)
|
|
178 {
|
|
179 T (0, "%*.*s", /* { dg-warning "writing up to 1 byte" } */
|
|
180 R (0, 1),
|
|
181 R (0, 1),
|
|
182 S (s->a3, s->a5, s3));
|
|
183
|
|
184 T (0, "%*.*s", /* { dg-warning "writing up to 2 bytes" } */
|
|
185 R (0, 2),
|
|
186 R (0, 1),
|
|
187 S (s->a3, s->a5, s3));
|
|
188
|
|
189 T (0, "%*.*s", /* { dg-warning "writing up to 9 bytes" } */
|
|
190 R (0, 9),
|
|
191 R (0, 1),
|
|
192 S (s->a3, s->a5, s3));
|
|
193
|
|
194 /* Since the longest string/array fits there is no warning even if
|
|
195 the maximum width would cause overflow. */
|
|
196 T (6, "%*.*s",
|
|
197 R (0, 9),
|
|
198 R (0, 1),
|
|
199 S (s->a3, s->a5, s3));
|
|
200
|
|
201 T (0, "%*.*s", /* { dg-warning "writing up to 2 bytes" } */
|
|
202 R (0, 2),
|
|
203 R (0, 2),
|
|
204 S (s->a3, s->a5, s3));
|
|
205
|
|
206 T (0, "%*.*s", /* { dg-warning "writing up to 3 bytes" } */
|
|
207 R (0, 3),
|
|
208 R (0, 2),
|
|
209 S (s->a3, s->a5, s3));
|
|
210 }
|