1 /* PR tree-optimization/89350 - Wrong -Wstringop-overflow warning
2    on a variable offset from the end of an array
3    Test exercising -Wstringop-truncation alone, with -Warray-bounds
4    explicitly disabled.
5    { dg-do compile }
6    { dg-options "-O2 -Wno-array-bounds -Wstringop-overflow -ftrack-macro-expansion=0" }  */
7 
8 #include "range.h"
9 
10 extern void* memcpy (void*, const void*, size_t);
11 extern void* memset (void*, int, size_t);
12 
13 void sink (void*);
14 
15 extern char ga7[7];
16 
17 
18 #define T(d, n) (memcpy ((d), s, (n)), sink (d))
19 
test_memcpy_array_cst_range_off(const void * s)20 void test_memcpy_array_cst_range_off (const void *s)
21 {
22   char *d = ga7 + 1;
23 
24   T (d + UR (1, 2), 1);
25   T (d + UR (1, 2), 5);
26 
27   T (d + UR (0, 1), 6);
28   /* The warning below should be "writing" but the [0, 1] range
29      is somehow lost and get_range_info() returns VR_VARYING.  */
30   T (d + UR (0, 1), 7);       /* { dg-warning ".memcpy. writing 7 bytes into a region of size 6 overflows the destination" "pr89428" { xfail *-*-* } } */
31   T (d + UR (1, 2), 6);       /* { dg-warning ".memcpy. writing 6 bytes into a region of size 5 overflows the destination" } */
32   T (d + UR (1, 2), 7);       /* { dg-warning "writing 7 bytes into a region of size 5 " } */
33 
34   T (d + SR (-3, -2), 1);     /* { dg-warning "writing 1 byte into a region of size 0 " } */
35   T (d + SR (-2, -1), 1);
36   T (d + SR (-2, -1), 2);     /* { dg-warning "writing 2 bytes into a region of size 7 " "pr89428" { xfail *-*-* } } */
37   T (d + SR (-2, -1), 9);     /* { dg-warning "writing 9 bytes into a region of size 7 " } */
38 
39   d = ga7 + 7;
40   T (d + SR (-7, -6), 1);
41   T (d + SR (-7, -1), 1);
42   T (d + SR (-2, -1), 3);     /* { dg-warning "writing 3 bytes into a region of size 2 " } */
43 
44   T (d + UR (1, 2), 1);       /* { dg-warning "writing 1 byte into a region of size 0 " } */
45 }
46 
47 
test_memcpy_array_range_range_off(const void * s)48 void test_memcpy_array_range_range_off (const void *s)
49 {
50   char *d = ga7 + UR (0, 1);
51   T (d + SR (-1, 0), 1);
52   T (d + SR (-1, 0), 7);
53   T (d + SR (-1, 0), 8);       /* { dg-warning "writing 8 bytes into a region of size 7 " } */
54   T (d + SR (-1, 0), 9);       /* { dg-warning "writing 9 bytes into a region of size 7 " "pr89350" } */
55 }
56 
57 
58 #undef T
59 #define T(d, n) (memset ((d), 0, (n)), sink (d))
60 
test_memset_array_unsigned_off(void)61 void test_memset_array_unsigned_off (void)
62 {
63   char *d = ga7 + 1;
64 
65   T (d + UR (1, 2), 1);
66   T (d + UR (1, 2), 5);
67 
68   T (d + UR (0, 1), 6);
69   T (d + UR (0, 1), 7);       /* { dg-warning ".memset. writing 6 bytes into a region of size 5 overflows the destination" "pr89428" { xfail *-*-* } } */
70   T (d + UR (1, 2), 6);       /* { dg-warning ".memset. writing 6 bytes into a region of size 5 overflows the destination" } */
71   T (d + UR (1, 2), 7);       /* { dg-warning "writing 7 bytes into a region of size 5 " } */
72 
73   T (d + SR (-3, -2), 1);     /* { dg-warning "writing 1 byte into a region of size 0 " } */
74   T (d + SR (-2, -1), 1);
75   T (d + SR (-2, -1), 2);     /* { dg-warning "writing 2 bytes into a region of size 7 " "pr89428" { xfail *-*-* } } */
76   T (d + SR (-2, -1), 9);     /* { dg-warning "writing 9 bytes into a region of size 7 " } */
77 
78   d = ga7 + 7;
79   T (d + SR (-7, -6), 1);
80   T (d + SR (-7, -1), 1);
81   T (d + SR (-2, -1), 3);     /* { dg-warning "writing 3 bytes into a region of size 2 " } */
82 
83   T (d + UR (1, 2), 1);       /* { dg-warning "writing 1 byte into a region of size 0 " } */
84 }
85 
86 
87 
88 struct MemArray { char a7[7], a3[3], c; };
89 
90 extern struct MemArray gma;
91 
test_memset_memarray(void)92 void test_memset_memarray (void)
93 {
94   char *d = gma.a7 + 1;
95 
96   T (d + UR (1, 2), 1);
97   T (d + UR (1, 2), 5);
98 
99   T (d + UR (0, 1), 6);
100   T (d + UR (0, 1), 7);       /* { dg-warning ".memset. writing 6 bytes into a region of size 5 overflows the destination" "pr89428" { xfail *-*-* } } */
101   T (d + UR (1, 2), 6);       /* { dg-warning ".memset. writing 6 bytes into a region of size 5 overflows the destination" "pr89350" { xfail *-*-* } } */
102   T (d + UR (1, 2), 7);       /* { dg-warning "writing 7 bytes into a region of size 5 " "pr85350" { xfail *-*-* } } */
103 
104 }
105 
106 
107 #undef T
108 #define T(d, n) (memcpy ((d), s, (n)), sink (d))
109 
test_memcpy_array_signed_off(const void * s)110 void test_memcpy_array_signed_off (const void *s)
111 {
112   char *d = ga7 + 1;
113 
114   T (d + SR (-7, 7), 7);
115   T (d + SR (-1, 1), 7);
116   T (d + SR (-1, 1), 9);      /* { dg-warning "writing 9 bytes into a region of size " } */
117   T (d + SR (-1, 2), 9);      /* { dg-warning "writing 9 bytes into a region of size " } */
118   T (d + SR (1, 2), 1);
119   T (d + SR (1, 2), 5);
120 
121   T (d + SR (0, 1), 6);
122   T (d + UR (1, 2), 7);       /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
123 }
124