mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-24 04:10:29 +08:00
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
This commit is contained in:
parent
b9f4757f8e
commit
eb07c7cffb
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user