111
|
1 /* PR tree-optimization/77671 - missing -Wformat-overflow warning
|
|
2 on sprintf overflow with "%s"
|
|
3
|
|
4 Negative test verifying that sprintf family calls that must not
|
|
5 be transformed into calls to other functions (such as memcpy)
|
|
6 are preserved.
|
|
7
|
|
8 { dg-compile }
|
|
9 { dg-options "-O2 -Wformat -Wno-format-truncation -Wno-format-zero-length -fdump-tree-optimized" } */
|
|
10
|
|
11 void sink (char*, ...);
|
|
12
|
|
13 extern char buffer[];
|
|
14
|
|
15 /* String exactly 4100 characters long (plus the terminating NUL). */
|
|
16 extern const char s4100[4101];
|
|
17
|
|
18 void test_sprintf (const char *s)
|
|
19 {
|
|
20 /* Macros to test the function call while eignoring and using
|
|
21 the return value, respectively. */
|
|
22 #define IGN(...) __builtin_sprintf (buffer, __VA_ARGS__), sink (buffer)
|
|
23 #define USE(...) sink (buffer, __builtin_sprintf (buffer, __VA_ARGS__))
|
|
24
|
|
25 /* All of the following calls to sprintf must be emitted (and not
|
|
26 transformed into memcpy, strcpy, or similar). */
|
|
27
|
|
28 /* Verify that a sprintf call with output in excess of the maximum
|
|
29 of 4095 bytes is not transformed into memcpy/strcpy when its
|
|
30 return value is used (the call may fail with EOVERFLOW but
|
|
31 the error is only detectable when the function's negative return
|
|
32 value indicates errno is valid ). */
|
|
33 USE (s4100);
|
|
34
|
|
35 USE ("%s", s4100);
|
|
36
|
|
37 /* Same as above but with string of unknown length (which could
|
|
38 be in excess of 4K long). */
|
|
39 USE (s);
|
|
40 USE ("%s", s);
|
|
41 }
|
|
42
|
|
43
|
|
44 void test_snprintf (void)
|
|
45 {
|
|
46 #undef IGN
|
|
47 #define IGN(N, ...) __builtin_snprintf (buffer, N, __VA_ARGS__); sink (buffer)
|
|
48
|
|
49 /* All of the following calls to sprintf must be emitted (and not
|
|
50 transformed into memcpy, strcpy, or similar). */
|
|
51
|
|
52 /* Truncated output could be optimized into strncpy (not done yet). */
|
|
53 IGN (1, "123");
|
|
54 IGN (1, s4100);
|
|
55
|
|
56 IGN (1, "%s", "123");
|
|
57 IGN (1, "%s", s4100);
|
|
58
|
|
59 /* Output in excess of the maximum of 4095 bytes. */
|
|
60 IGN (4097, s4100);
|
|
61
|
|
62 IGN (4097, "%s", s4100);
|
|
63 }
|
|
64
|
|
65
|
|
66 void test_vsprintf (__builtin_va_list va)
|
|
67 {
|
|
68 #undef IGN
|
|
69 #define IGN(fmt) __builtin_vsprintf (buffer, fmt, va); sink (buffer)
|
|
70
|
|
71 /* All of the following calls to vsprintf must be emitted (and not
|
|
72 transformed into memcpy, strcpy, or similar). */
|
|
73
|
|
74 /* Output in excess of the maximum of 4095 bytes. */
|
|
75 IGN (s4100);
|
|
76 }
|
|
77
|
|
78
|
|
79 void test_vsnprintf (__builtin_va_list va)
|
|
80 {
|
|
81 #undef IGN
|
|
82 #define IGN(N, fmt) __builtin_vsnprintf (buffer, N, fmt, va); sink (buffer)
|
|
83
|
|
84 /* All of the following calls to vsnprintf must be emitted (and not
|
|
85 transformed into memcpy, strcpy, or similar). */
|
|
86
|
|
87 /* Truncated output could be optimized into strncpy (not done yet). */
|
|
88 IGN (1, "123");
|
|
89 IGN (1, s4100);
|
|
90
|
|
91 /* Output in excess of the maximum of 4095 bytes. */
|
|
92 IGN (4097, s4100);
|
|
93 }
|
|
94
|
|
95 /* { dg-final { scan-tree-dump-times "builtin_sprintf" 4 "optimized" } }
|
|
96 { dg-final { scan-tree-dump-times "builtin_snprintf" 6 "optimized" } }
|
|
97 { dg-final { scan-tree-dump-times "builtin_vsprintf" 1 "optimized" } }
|
|
98 { dg-final { scan-tree-dump-times "builtin_vsnprintf" 3 "optimized" } } */
|
|
99
|
|
100 #define S10 "0123456789"
|
|
101 #define S100 S10 S10 S10 S10 S10 S10 S10 S10 S10 S10
|
|
102 #define S1000 S100 S100 S100 S100 S100 S100 S100 S100 S100 S100
|
|
103
|
|
104 const char s4100[4101] = S1000 S1000 S1000 S1000 S100;
|