aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Sebor <msebor@gcc.gnu.org>2017-01-10 14:54:15 -0700
committerMartin Sebor <msebor@gcc.gnu.org>2017-01-10 14:54:15 -0700
commiteb07c7cffb2ca361e793281ca142b2f8063aa0e1 (patch)
tree082ec7518c01c45d3ae0445135abb05700e30116 /gcc
parentb9f4757f8eb94d4b145613ee5047f3f95452f9d2 (diff)
downloadgcc-eb07c7cffb2ca361e793281ca142b2f8063aa0e1.zip
gcc-eb07c7cffb2ca361e793281ca142b2f8063aa0e1.tar.gz
gcc-eb07c7cffb2ca361e793281ca142b2f8063aa0e1.tar.bz2
PR middle-end/78245 - missing -Wformat-length on an overflow of a dynamically allocated buffer
gcc/testsuite/ChangeLog: PR middle-end/78245 * gcc.dg/tree-ssa/builtin-sprintf-warn-3.c: Add tests. gcc/ChangeLog: PR middle-end/78245 * gimple-ssa-sprintf.c (get_destination_size): Call {init,fini}object_sizes. * tree-object-size.c (addr_object_size): Adjust. (pass_through_call): Adjust. (pass_object_sizes::execute): Adjust. * tree-object-size.h (fini_object_sizes): Declare. From-SVN: r244293
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gimple-ssa-sprintf.c5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-3.c124
-rw-r--r--gcc/tree-object-size.c2
-rw-r--r--gcc/tree-object-size.h1
4 files changed, 118 insertions, 14 deletions
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index 166b34b..9b327f6 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -2723,6 +2723,9 @@ get_destination_size (tree dest)
a member array as opposed to the whole enclosing object), otherwise
use type-zero object size to determine the size of the enclosing
object (the function fails without optimization in this type). */
+
+ init_object_sizes ();
+
int ost = optimize > 0;
unsigned HOST_WIDE_INT size;
if (compute_builtin_object_size (dest, ost, &size))
@@ -3120,6 +3123,8 @@ pass_sprintf_length::execute (function *fun)
}
}
+ fini_object_sizes ();
+
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-3.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-3.c
index 1ca0a66..eb59781 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-3.c
@@ -1,5 +1,10 @@
-/* { dg-do compile } */
-/* { dg-options "-O2 -Wformat -Wformat-length=1 -ftrack-macro-expansion=0" } */
+/* Verify that all sprintf built-ins detect overflow involving directives
+ with non-constant arguments known to be constrained by some range of
+ values, and even when writing into dynamically allocated buffers.
+ -O2 (-ftree-vrp) is necessary for the tests involving ranges to pass,
+ otherwise -O1 is sufficient.
+ { dg-do compile }
+ { dg-options "-O2 -Wformat -Wformat-length=1 -ftrack-macro-expansion=0" } */
typedef __SIZE_TYPE__ size_t;
@@ -9,18 +14,26 @@ typedef __SIZE_TYPE__ size_t;
#define bos(x) __builtin_object_size (x, 0)
-#define T(bufsize, fmt, ...) \
- do { \
- if (!LINE || __LINE__ == LINE) \
- { \
- char *d = (char *)__builtin_malloc (bufsize); \
- __builtin___sprintf_chk (d, 0, bos (d), fmt, __VA_ARGS__); \
- sink (d); \
- } \
- } while (0)
+/* Defined (and redefined) to the allocation function to use, either
+ malloc, or alloca, or a VLA. */
+#define ALLOC(p, n) (p) = __builtin_malloc (n)
-void
-sink (void*);
+/* Defined (and redefined) to the sprintf function to exercise. */
+#define TEST_SPRINTF(d, maxsize, objsize, fmt, ...) \
+ __builtin___sprintf_chk (d, 0, objsize, fmt, __VA_ARGS__)
+
+#define T(bufsize, fmt, ...) \
+ do { \
+ if (!LINE || __LINE__ == LINE) \
+ { \
+ char *d; \
+ ALLOC (d, bufsize); \
+ TEST_SPRINTF (d, 0, bos (d), fmt, __VA_ARGS__); \
+ sink (d); \
+ } \
+ } while (0)
+
+void sink (void*);
/* Identity function to verify that the checker figures out the value
of the operand even when it's not constant (i.e., makes use of
@@ -362,3 +375,88 @@ void test_too_large (char *d, int x, __builtin_va_list va)
__builtin___vsnprintf_chk (d, ptrmax_m1, 0, ptrmax_m1, "%c", va); /* { dg-warning "specified bound \[0-9\]+ exceeds .INT_MAX." "PTRDIFF_MAX - 1" { target lp64 } } */
__builtin___vsnprintf_chk (d, ptrmax, 0, ptrmax, "%c", va); /* { dg-warning "specified bound \[0-9\]+ exceeds .INT_MAX." "PTRDIFF_MAX" { target lp64 } } */
}
+
+/* Exercise ordinary sprintf with malloc. */
+#undef TEST_SPRINTF
+#define TEST_SPRINTF(d, maxsize, objsize, fmt, ...) \
+ __builtin_sprintf (d, fmt, __VA_ARGS__)
+
+void test_sprintf_malloc (const char *s, const char *t)
+{
+#define x x ()
+
+ T (1, "%-s", x ? "" : "1"); /* { dg-warning "nul past the end" } */
+ T (1, "%-s", x ? "1" : ""); /* { dg-warning "nul past the end" } */
+ T (1, "%-s", x ? s : "1"); /* { dg-warning "nul past the end" } */
+ T (1, "%-s", x ? "1" : s); /* { dg-warning "nul past the end" } */
+ T (1, "%-s", x ? s : t);
+
+ T (2, "%-s", x ? "" : "1");
+ T (2, "%-s", x ? "" : s);
+ T (2, "%-s", x ? "1" : "");
+ T (2, "%-s", x ? s : "");
+ T (2, "%-s", x ? "1" : "2");
+ T (2, "%-s", x ? "" : "12"); /* { dg-warning "nul past the end" } */
+ T (2, "%-s", x ? "12" : ""); /* { dg-warning "nul past the end" } */
+
+ T (2, "%-s", x ? "" : "123"); /* { dg-warning "into a region" } */
+ T (2, "%-s", x ? "123" : ""); /* { dg-warning "into a region" } */
+
+#undef x
+}
+
+/* Exercise ordinary sprintf with alloca. */
+#undef ALLOC
+#define ALLOC(p, n) (p) = __builtin_alloca (n)
+
+void test_sprintf_alloca (const char *s, const char *t)
+{
+#define x x ()
+
+ T (1, "%-s", x ? "" : "1"); /* { dg-warning "nul past the end" } */
+ T (1, "%-s", x ? "1" : ""); /* { dg-warning "nul past the end" } */
+ T (1, "%-s", x ? s : "1"); /* { dg-warning "nul past the end" } */
+ T (1, "%-s", x ? "1" : s); /* { dg-warning "nul past the end" } */
+ T (1, "%-s", x ? s : t);
+
+ T (2, "%-s", x ? "" : "1");
+ T (2, "%-s", x ? "" : s);
+ T (2, "%-s", x ? "1" : "");
+ T (2, "%-s", x ? s : "");
+ T (2, "%-s", x ? "1" : "2");
+ T (2, "%-s", x ? "" : "12"); /* { dg-warning "nul past the end" } */
+ T (2, "%-s", x ? "12" : ""); /* { dg-warning "nul past the end" } */
+
+ T (2, "%-s", x ? "" : "123"); /* { dg-warning "into a region" } */
+ T (2, "%-s", x ? "123" : ""); /* { dg-warning "into a region" } */
+
+#undef x
+}
+
+/* Exercise ordinary sprintf with a VLA. */
+#undef ALLOC
+#define ALLOC(p, n) char vla [i (n)]; (p) = vla
+
+void test_sprintf_vla (const char *s, const char *t)
+{
+#define x x ()
+
+ T (1, "%-s", x ? "" : "1"); /* { dg-warning "nul past the end" } */
+ T (1, "%-s", x ? "1" : ""); /* { dg-warning "nul past the end" } */
+ T (1, "%-s", x ? s : "1"); /* { dg-warning "nul past the end" } */
+ T (1, "%-s", x ? "1" : s); /* { dg-warning "nul past the end" } */
+ T (1, "%-s", x ? s : t);
+
+ T (2, "%-s", x ? "" : "1");
+ T (2, "%-s", x ? "" : s);
+ T (2, "%-s", x ? "1" : "");
+ T (2, "%-s", x ? s : "");
+ T (2, "%-s", x ? "1" : "2");
+ T (2, "%-s", x ? "" : "12"); /* { dg-warning "nul past the end" } */
+ T (2, "%-s", x ? "12" : ""); /* { dg-warning "nul past the end" } */
+
+ T (2, "%-s", x ? "" : "123"); /* { dg-warning "into a region" } */
+ T (2, "%-s", x ? "123" : ""); /* { dg-warning "into a region" } */
+
+#undef x
+}
diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c
index 71ec7b2..eb08b33 100644
--- a/gcc/tree-object-size.c
+++ b/gcc/tree-object-size.c
@@ -1235,7 +1235,7 @@ init_object_sizes (void)
/* Destroy data structures after the object size computation. */
-static void
+void
fini_object_sizes (void)
{
int object_size_type;
diff --git a/gcc/tree-object-size.h b/gcc/tree-object-size.h
index 500a834..1b55805 100644
--- a/gcc/tree-object-size.h
+++ b/gcc/tree-object-size.h
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
#define GCC_TREE_OBJECT_SIZE_H
extern void init_object_sizes (void);
+extern void fini_object_sizes (void);
extern bool compute_builtin_object_size (tree, int, unsigned HOST_WIDE_INT *);
#endif // GCC_TREE_OBJECT_SIZE_H