1 /* { dg-additional-options "-Wno-unused-but-set-variable" } */
2 /* { dg-require-effective-target alloca } */
8 /* Tests with symbolic values. */
10 void test1 (size_t size
)
12 char *buf
= (char *)__builtin_malloc (size
);
15 buf
[size
] = '\0'; /* { dg-warning "heap-based buffer overflow" } */
19 void test2 (size_t size
)
21 char *buf
= (char *)__builtin_malloc (size
);
24 buf
[size
+ 1] = '\0'; /* { dg-warning "heap-based buffer overflow" } */
28 void test3 (size_t size
, size_t op
)
30 char *buf
= (char *)__builtin_malloc (size
);
33 buf
[size
+ op
] = '\0'; /* { dg-warning "heap-based buffer overflow" } */
37 void test4 (size_t size
, unsigned short s
)
39 char *buf
= (char *)__builtin_alloca (size
);
40 buf
[size
+ s
] = '\0'; /* { dg-warning "stack-based buffer overflow" } */
43 void test5 (size_t size
)
45 int32_t *buf
= (int32_t *)__builtin_alloca (4 * size
);
46 buf
[size
] = 42; /* { dg-warning "stack-based buffer overflow" } */
49 void test6 (size_t size
)
51 int32_t *buf
= (int32_t *)__builtin_alloca (4 * size
);
52 memset (buf
, 0, 4 * size
);
53 int32_t last
= *(buf
+ 4 * size
); /* { dg-warning "stack-based buffer over-read" } */
56 void test7 (size_t size
)
58 int32_t *buf
= (int32_t *)__builtin_alloca (4 * size
+ 3); /* { dg-warning "allocated buffer size is not a multiple of the pointee's size" } */
59 buf
[size
] = 42; /* { dg-warning "stack-based buffer overflow" } */
62 /* Test where the offset itself is not out-of-bounds
63 but multiple bytes are read. */
65 void test8 (size_t size
, size_t offset
)
69 memcpy (dst
, src
, size
+ offset
); /* { dg-line test8 } */
70 /* { dg-warning "over-read" "warning" { target *-*-* } test8 } */
71 /* { dg-warning "overflow" "warning" { target *-*-* } test8 } */
74 void test9 (size_t size
, size_t offset
)
78 memcpy (dst
, src
, 4 * size
+ 1); /* { dg-line test9 } */
79 /* { dg-warning "over-read" "warning" { target *-*-* } test9 } */
80 /* { dg-warning "overflow" "warning" { target *-*-* } test9 } */
83 /* Test for no false-positives. */
85 void test10 (size_t size
)
87 int32_t buf
[4 * size
];
88 /* 4 * size is smaller than 4 * 4 * size. */
92 void test11 (size_t size
)
94 int32_t *buf
= (int32_t *)__builtin_alloca (4 * size
+ 5); /* { dg-warning "allocated buffer size is not a multiple of the pointee's size" } */
98 void test12 (size_t size
, size_t offset
)
104 void test13 (size_t size
, int offset
)
107 /* We don't know whether offset is positive or not. */
108 buf
[size
+ offset
] = 42;
111 void test14 (size_t size
, size_t offset
, size_t offset2
)
114 /* We don't know whether offset > offset2. */
115 buf
[size
+ offset
- offset2
] = 42;
118 void test15 (size_t a
, size_t b
)
121 /* We can't reason about a*b < a+b either. */
127 char *test98 (const char *x
, const char *y
)
129 size_t len_x
= __builtin_strlen (x
);
130 size_t len_y
= __builtin_strlen (y
);
131 size_t sz
= len_x
+ len_y
+ 1;
132 char *result
= (char *)__builtin_malloc (sz
);
135 __builtin_memcpy (result
, x
, len_x
);
136 __builtin_memcpy (result
+ len_x
, y
, len_y
);
137 result
[len_x
+ len_y
] = '\0';
141 char *test99 (const char *x
, const char *y
)
143 size_t len_x
= __builtin_strlen (x
);
144 size_t len_y
= __builtin_strlen (y
);
145 /* BUG (root cause): forgot to add 1 for terminator. */
146 size_t sz
= len_x
+ len_y
;
147 char *result
= (char *)__builtin_malloc (sz
);
150 __builtin_memcpy (result
, x
, len_x
);
151 __builtin_memcpy (result
+ len_x
, y
, len_y
);
152 /* BUG (symptom): off-by-one out-of-bounds write to heap. */
153 result
[len_x
+ len_y
] = '\0'; /* { dg-warning "heap-based buffer overflow" } */