1 /* PR middle-end/79448 - unhelpful -Wformat-truncation=2 warning
2    { dg-do compile }
3    { dg-options "-O2 -Wformat -Wformat-truncation=2 -ftrack-macro-expansion=0" }
4    { dg-require-effective-target ptr32plus } */
5 
6 typedef __SIZE_TYPE__  size_t;
7 typedef __WCHAR_TYPE__ wchar_t;
8 
9 #define INT_MAX __INT_MAX__
10 #define INT_MIN (-INT_MAX - 1)
11 
12 /* When debugging, define LINE to the line number of the test case to exercise
13    and avoid exercising any of the others.  The buffer and objsize macros
14    below make use of LINE to avoid warnings for other lines.  */
15 #ifndef LINE
16 # define LINE 0
17 #endif
18 
19 extern int int_value (void);
20 extern size_t size_value (void);
21 
int_range(int min,int max)22 int int_range (int min, int max)
23 {
24   int n = int_value ();
25   return n < min || max < n ? min : n;
26 }
27 
28 void sink (int, char*, char*);
29 
30 int dummy_snprintf (char*, size_t, const char*, ...);
31 
32 char fixed_buffer [256];
33 extern char *unknown_buffer;
34 extern size_t unknown_size;
35 
36 /* Helper to expand function to either __builtin_f or dummy_f to
37    make debugging GCC easy.  */
38 #define FUNC(f)							\
39   ((!LINE || LINE == __LINE__) ? __builtin_ ## f : dummy_ ## f)
40 
41 /* Helper test macro.  */
42 #define T(size, ...)					\
43   do {							\
44     size_t n = size < 0 ? unknown_size : size;		\
45     char *buf = size < 0 ? unknown_buffer		\
46       : n < sizeof fixed_buffer				\
47       ? fixed_buffer + sizeof fixed_buffer - size	\
48       : unknown_buffer;					\
49     FUNC (snprintf) (buf, n, __VA_ARGS__);		\
50     sink (0, fixed_buffer, unknown_buffer);		\
51   } while (0)
52 
53 /* Return a value in the range [MIN, MAX].  */
54 #define IR(min, max)  int_range (min, max)
55 
56 struct Arrays
57 {
58   char a1[1];
59   char a4k[4096];
60   char a4kp1[4097];
61 #if INT_MAX < LONG_MAX
62   char amax[INT_MAX];
63 #else
64   char amax[32767];
65 #endif
66   char ax[];
67 };
68 
test_string_unchecked(const char * s,const struct Arrays * ar)69 void test_string_unchecked (const char *s, const struct Arrays *ar)
70 {
71   /* Verify there is no warning with strings of unknown length.  */
72   T (-1, "%-s", s);
73   T (-1, "%-s", ar->ax);
74 
75   T (-1, "%s%s", s, s);
76   T (-1, "%s%s", "", s);
77   T (-1, "%s%s", s, "1");
78   T (-1, "%s%s", "1", s);
79 
80   /* Verify there is no warning with strings of length that cannot
81      exceed 4k (because of the array size).  */
82   T (-1, "%-s", ar->a1);
83   T (-1, "%-s", ar->a4k);
84 
85   /* Verify there's no "exceeds minimum required size of 4095" warning
86      with multiple %s directives and a combination of strings of unknown
87      (and potentially unbounded) length and strings whose length is
88      bounded by the size of the arrays they are stored in.  */
89   T (-1, "%s%s", s, ar->a4k);
90   T (-1, "%s%s", ar->a4k, s);
91   T (-1, "%s%s", ar->a4k, ar->a4k);
92   T (-1, "%s%s", ar->a4k, "123");
93   T (-1, "%s%s", "123", ar->a4k);
94   T (-1, "%s%s", ar->ax, ar->a4k);
95   T (-1, "%s%s", ar->a4k, ar->ax);
96 
97   /* Verify that an array that fits a string longer than 4095 bytes
98      does trigger a warning.  */
99   T (-1, "%-s", ar->a4kp1);   /* { dg-warning "directive output between 0 and 4096 bytes may exceed minimum required size of 4095" } */
100 
101   /* Also verify that a %s directive with width greater than 4095
102      triggers a warning even if the argument is not longer than 4k.  */
103   T (-1, "%*s", 4096, ar->a4k);   /* { dg-warning "directive output of 4096 bytes exceeds minimum required size of 4095" } */
104 
105   /* Verify that precision constrains the putput and suppresses the 4k
106      warning.  */
107   T (-1, "%.*s", 4095, ar->a4kp1);
108 
109   T (-1, "%s %s", s, "");
110   T (-1, "%s %s", "", s);
111   T (-1, "%s %s", s, "1");
112   T (-1, "%s %s", "1", s);
113 
114   T (-1, "%s%s%s", s, "1", s);
115   T (-1, "%s%s%s", "1", s, "1");
116   T (-1, "%s%s%s", s, s, s);
117   T (-1, "%*s%*s%*s", 4093, s, 4094, s, 4095, s);
118   T (-1, "%s %s %s", s, s, s);
119   T (-1, "%s %s %s", ar->a4k, ar->a4k, ar->a4k);
120   T (-1, "%s %s %s", ar->ax, ar->ax, ar->ax);
121 
122   /* Verify that an array of INT_MAX elements doesn't trigger the INT_MAX
123      warning (LP64 only).  */
124   T (-1, "%-s", ar->amax);   /* { dg-warning "directive output between 0 and \[0-9\]+ bytes may exceed minimum required size of 4095" } */
125 }
126 
127 #undef T
128 /* Helper test macro.  */
129 #define T(size, ...)					\
130   do {							\
131     size_t n = size < 0 ? unknown_size : size;		\
132     char *buf = size < 0 ? unknown_buffer		\
133       : n < sizeof fixed_buffer				\
134       ? fixed_buffer + sizeof fixed_buffer - size	\
135       : unknown_buffer;					\
136     int r = FUNC (snprintf) (buf, n, __VA_ARGS__);	\
137     sink (r, fixed_buffer, unknown_buffer);		\
138   } while (0)
139 
test_string_checked(const char * s,const struct Arrays * ar)140 void test_string_checked (const char *s, const struct Arrays *ar)
141 {
142   /* Verify there is no warning with strings of unknown length.  */
143   T (-1, "%-s", s);
144   T (-1, "%-s", ar->ax);
145 
146   T (-1, "%s%s", s, s);
147   T (-1, "%s%s", "", s);
148   T (-1, "%s%s", s, "1");
149   T (-1, "%s%s", "1", s);
150 
151   /* Verify there is no warning with strings of length that cannot
152      exceed 4k (because of the array size).  */
153   T (-1, "%-s", ar->a1);
154   T (-1, "%-s", ar->a4k);
155 
156   /* Verify there's no "exceeds minimum required size of 4095" warning
157      with multiple %s directives and a combination of strings of unknown
158      (and potentially unbounded) length and strings whose length is
159      bounded by the size of the arrays they are stored in.  */
160   T (-1, "%s%s", s, ar->a4k);
161   T (-1, "%s%s", ar->a4k, s);
162   T (-1, "%s%s", ar->a4k, ar->a4k);
163   T (-1, "%s%s", ar->a4k, "123");
164   T (-1, "%s%s", "123", ar->a4k);
165   T (-1, "%s%s", ar->ax, ar->a4k);
166   T (-1, "%s%s", ar->a4k, ar->ax);
167 
168   /* Verify that an array that fits a string longer than 4095 bytes
169      does trigger a warning.  */
170   T (-1, "%-s", ar->a4kp1);   /* { dg-warning "directive output between 0 and 4096 bytes may exceed minimum required size of 4095" } */
171 
172   /* Also verify that a %s directive with width greater than 4095
173      triggers a warning even if the argument is not longer than 4k.  */
174   T (-1, "%*s", 4096, ar->a4k);   /* { dg-warning "directive output of 4096 bytes exceeds minimum required size of 4095" } */
175 
176   /* Verify that precision constrains the putput and suppresses the 4k
177      warning.  */
178   T (-1, "%.*s", 4095, ar->a4kp1);
179 
180   T (-1, "%s %s", s, "");
181   T (-1, "%s %s", "", s);
182   T (-1, "%s %s", s, "1");
183   T (-1, "%s %s", "1", s);
184 
185   T (-1, "%s%s%s", s, "1", s);
186   T (-1, "%s%s%s", "1", s, "1");
187   T (-1, "%s%s%s", s, s, s);
188   T (-1, "%*s%*s%*s", 4093, s, 4094, s, 4095, s);
189   T (-1, "%s %s %s", s, s, s);
190   T (-1, "%s %s %s", ar->a4k, ar->a4k, ar->a4k);
191   T (-1, "%s %s %s", ar->ax, ar->ax, ar->ax);
192 
193   T (-1, "%-s", ar->amax);   /* { dg-warning "directive output between 0 and \[0-9\]+ bytes may exceed minimum required size of 4095" } */
194 }
195