aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/Wstringop-overflow-46.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/gcc.dg/Wstringop-overflow-46.c')
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-46.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-46.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-46.c
new file mode 100644
index 0000000..a4d78b2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-46.c
@@ -0,0 +1,97 @@
+/* PR middle-end/97023 - missing warning on buffer overflow in chained mempcpy
+ Verify that out of bounds writes by built-ins to objects through pointers
+ returned by memchr() are diagnosed.
+ { dg-do compile }
+ { dg-options "-O2" } */
+
+#include "range.h"
+
+void* malloc (size_t);
+void* memchr (void*, int, size_t);
+void* memset (void*, int, size_t);
+
+void sink (void*, ...);
+
+void nowarn_memchr_cst_memset_cst (const void *s)
+{
+ char *p = malloc (4);
+ sink (p);
+
+ p = memchr (p, '1', 4);
+ memset (p, 0, 4);
+}
+
+void nowarn_memchr_uint_memset_cst (const void *s, unsigned n)
+{
+ char *p = malloc (4);
+ sink (p);
+
+ p = memchr (p, '1', n);
+ memset (p, 0, 4);
+}
+
+void nowarn_memchr_sz_memset_cst (const void *s, size_t n)
+{
+ char *p = malloc (4);
+ sink (p);
+
+ p = memchr (p, '1', n);
+ memset (p, 0, 4);
+}
+
+void nowarn_memchr_anti_range_memset_cst (const void *s, size_t n)
+{
+ char *p = malloc (4);
+ sink (p);
+
+ if (n == 0)
+ n = 1;
+
+ p = memchr (p, '1', n);
+ memset (p, 0, 4);
+}
+
+void warn_memchr_cst_memset_cst (const void *s)
+{
+ char *p = malloc (4); // { dg-message "at offset \\\[0, 4] into destination object of size 4 " "note" }
+ sink (p);
+
+ p = memchr (p, '1', 4);
+ memset (p, 0, 5); // { dg-warning "writing 5 bytes into a region of size 4 " }
+}
+
+void warn_memchr_var_memset_cst (const void *s, unsigned n)
+{
+ char *p = malloc (4); // { dg-message "at offset \\\[0, 4] into destination object of size 4 " "note" }
+ sink (p);
+
+ p = memchr (p, '1', n);
+ memset (p, 0, 5); // { dg-warning "writing 5 bytes into a region of size 4 " }
+}
+
+void warn_memchr_var_memset_range (const void *s, unsigned n)
+{
+ /* The offsets in the first two notes are bounded by the size of
+ the allocated object. The real upper bound of the offset in
+ the last note includes the upper bound f the offset of the pointer
+ returned from the previous memchr() call, but it ends up getting
+ constrained to the bounds of the allocated object so it's the same
+ as in the first two notes. The exact value probably isn't too
+ important. */
+ char *p0 = malloc (UR (5, 7));
+ // { dg-message "at offset \\\[0, 7] into destination object of size \\\[5, 7]" "note" { target *-*-* } .-1 }
+ // { dg-message "at offset \\\[1, 7] into destination object of size \\\[5, 7]" "note" { target *-*-* } .-2 }
+ // { dg-message "at offset \\\[2, 7] into destination object of size \\\[5, 7]" "note" { target *-*-* } .-3 }
+
+ sink (p0);
+ char *p1 = memchr (p0, '1', n);
+ memset (p1, 0, UR (8, 9)); // { dg-warning "writing between 8 and 9 bytes into a region of size 7 " }
+
+ sink (p0);
+ p1 = memchr (p0 + 1, '2', n);
+ memset (p1, 0, UR (7, 9)); // { dg-warning "writing between 7 and 9 bytes into a region of size 6 " }
+
+ sink (p0);
+ char *p2 = memchr (p1 + 1, '3', n);
+ memset (p2, 0, UR (6, 9)); // { dg-warning "writing between 6 and 9 bytes into a region of size 5 " }
+}