aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/Wstringop-overflow-60.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/gcc.dg/Wstringop-overflow-60.c')
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-60.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-60.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-60.c
new file mode 100644
index 0000000..8c9de20
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-60.c
@@ -0,0 +1,72 @@
+/* Test derived from Glibc's getifaddrs_internal. The code could be
+ rewritten to avoid the warning for the memcpy call but since unions
+ are designed to have their members treated as interchangeable there
+ isn't a whole lot to be gained from issuing one.
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern void* memcpy (void*, const void*, size_t);
+
+struct sockaddr
+{
+ short sa_family;
+ char sa_data[14];
+};
+
+struct in_addr
+{
+ int s_addr;
+};
+
+struct in6_addr
+{
+ union
+ {
+ char __u6_addr8[16];
+ short __u6_addr16[8];
+ int __u6_addr32[4];
+ } __in6_u;
+};
+
+struct sockaddr_in
+{
+ short sin_family;
+ short sin_port;
+ struct in_addr sin_addr;
+ unsigned char sin_zero[sizeof (struct sockaddr) -
+ (sizeof (short)) -
+ sizeof (short) -
+ sizeof (struct in_addr)];
+};
+
+struct sockaddr_in6
+{
+ short sin6_family;
+ short sin6_port;
+ int sin6_flowinfo;
+ struct in6_addr sin6_addr;
+ int sin6_scope_id;
+};
+
+union
+{
+ struct sockaddr sa;
+ struct sockaddr_in s4;
+ struct sockaddr_in6 s6;
+} u1, u2;
+
+struct sockaddr *sa;
+
+void test_unconditional (void *p)
+{
+ sa = &u1.sa;
+ memcpy (&((struct sockaddr_in6 *) sa)->sin6_addr, p, 16);
+}
+
+void test_conditional (void *p, int i)
+{
+ sa = i ? &u1.sa : &u2.sa;
+ memcpy (&((struct sockaddr_in6 *) sa)->sin6_addr, p, 16);
+}