diff gcc/testsuite/c-c++-common/Wstringop-overflow.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gcc/testsuite/c-c++-common/Wstringop-overflow.c	Thu Oct 25 07:37:49 2018 +0900
@@ -0,0 +1,158 @@
+/* PR middle-end/81117 - Improve buffer overflow checking in strncpy
+   { dg-do compile }
+   { dg-options "-O2 -Wstringop-overflow -Wno-stringop-truncation -ftrack-macro-expansion=0" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+#if __cplusplus
+extern "C" {
+#endif
+
+size_t strlen (const char*);
+char* strncat (char*, const char*, size_t);
+char* strncpy (char*, const char*, size_t);
+#if __cplusplus
+}
+#endif
+
+const char ar[] = "123";
+
+void test_strncat (char **d, const char* s, int i)
+{
+  /* Use a fresh pointer for each test to prevent the optimizer from
+     eliminating redundant writes into the same destination.  Avoid
+     calling functions like sink() on the result that would have to
+     be assumed to change the source string by the alias oracle.  */
+#define T(d, s, len) strncat (*d++, (s), (len))
+
+  T (d, "",    0);
+  T (d, "",    1);
+  T (d, "",    2);
+  T (d, "",    3);
+  T (d, "123", 0);
+  /* The following two calls truncate the copy and are diagnosed
+     by -Wstringop-truncation but there is evidence of overflow so
+     they're not diagnosed by -Wstringop-overflow.  */
+  T (d, "123", 1);
+  T (d, "123", 2);
+
+  T (d, "123", 3);                /* { dg-warning ".strncat\[^\n\r\]* specified bound 3 equals source length" } */
+  T (d, "123", 4);
+  T (d, "123", 9);
+
+  T (d, s, strlen (s));           /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
+  T (d, s, strlen (s) + 1);       /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
+  /* The following could also be diagnosed by -Wstringop-truncation
+     (with some effort to distinguish the pattern from others like
+     the one above.  */
+  T (d, s, strlen (s) - 1);       /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
+  T (d, s, strlen (s) - i);       /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
+
+  /* The following is dubious but not necessarily a smoking gun.  */
+  T (d, s, strlen (s) - strlen (s));
+
+  {
+    signed char n = strlen (s);   /* { dg-message "length computed here" } */
+    T (d, s, n);                  /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
+  }
+
+  {
+    short n = strlen (s);         /* { dg-message "length computed here" } */
+    T (d, s, n);                  /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
+  }
+
+  {
+    int n = strlen (s);           /* { dg-message "length computed here" } */
+    T (d, s, n);                  /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
+  }
+
+  {
+    unsigned n = strlen (s);      /* { dg-message "length computed here" } */
+    T (d, s, n);                  /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
+  }
+
+  {
+    size_t n;
+    n = strlen (s);               /* { dg-message "length computed here" } */
+    T (d, s, n);                  /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
+  }
+
+  {
+    size_t n;
+    n = strlen (s) - 1;           /* { dg-message "length computed here" } */
+    T (d, s, n);                  /* { dg-message ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
+  }
+
+  {
+    /* This doesn't overflow so iit should not be diagnosed.  */
+    size_t n = strlen (s) - strlen (s);
+    T (d, s, n);
+  }
+
+  {
+    size_t n = i < strlen (s) ? i : strlen (s);   /* { dg-message "length computed here" } */
+    T (d, s, n);                  /* { dg-message ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */
+  }
+}
+
+
+void test_strncpy (char **d, const char* s, int i)
+{
+#undef T
+#define T(d, s, len) strncpy (*d++, (s), (len))
+
+  T (d, "",    0);
+  T (d, "",    1);
+  T (d, "",    2);
+  T (d, "",    3);
+  T (d, "123", 0);
+  T (d, "123", 1);
+  T (d, "123", 2);
+  T (d, "123", 3);
+  T (d, "123", 4);
+  T (d, "123", 9);
+
+  T (d, "123", sizeof "123");
+  T (d, ar, sizeof ar);
+
+  T (d, s, strlen (s));       /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+
+  {
+    int n = strlen (s);       /* { dg-message "length computed here" } */
+    T (d, s, n);              /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+  }
+
+  {
+    unsigned n = strlen (s);   /* { dg-message "length computed here" } */
+    T (d, s, n);               /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+  }
+
+  {
+    size_t n;
+    n = strlen (s);           /* { dg-message "length computed here" } */
+    T (d, s, n);              /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+  }
+
+  {
+    size_t n;
+    n = strlen (s) - 1;       /* { dg-message "length computed here" } */
+    T (d, s, n);              /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+  }
+
+  {
+    /* This is diagnosed by -Wstringop-truncation.  Verify that it isn't
+       also diagnosed by -Wstringop-overflow.  */
+    size_t n = strlen (s) - strlen (s);
+    T (d, s, n);
+  }
+
+  {
+    /* This use of strncpy is certainly dubious and it could well be
+       diagnosed by -Wstringop-truncation but it isn't.  That it is
+       diagnosed with -Wstringop-overflow is more by accident than
+       by design.  -Wstringop-overflow considers any dependency of
+       the bound on strlen(s) a potential bug.  */
+    size_t n = i < strlen (s) ? i : strlen (s);   /* { dg-message "length computed here" } */
+    T (d, s, n);                  /* { dg-message ".strncpy\[^\n\r]* specified bound depends on the length of the source argument" } */
+  }
+}