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
test_sprintf(const char * s)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
test_snprintf(void)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
test_vsprintf(__builtin_va_list va)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
test_vsnprintf(__builtin_va_list va)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;
105