From e3329a782fc0e51b9a4ddfc6938a484ec4b03084 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 12 Jun 2018 18:05:13 +0000 Subject: [PATCH] PR tree-optimization/85259 - Missing -Wstringop-overflow= since r256683 gcc/ChangeLog: PR tree-optimization/85259 * builtins.c (compute_objsize): Handle constant offsets. * gimple-ssa-warn-restrict.c (maybe_diag_offset_bounds): Return true iff a warning has been issued. * gimple.h (gimple_nonartificial_location): New function. * tree-ssa-strlen.c (maybe_diag_stxncpy_trunc): Call gimple_nonartificial_location and handle -Wno-system-headers. (handle_builtin_stxncpy): Same. gcc/testsuite/ChangeLog: PR tree-optimization/85259 * gcc.dg/Wstringop-overflow-5.c: New test. * gcc.dg/Wstringop-overflow-6.c: New test. From-SVN: r261518 --- gcc/ChangeLog | 11 +++ gcc/builtins.c | 23 ++++- gcc/gimple-ssa-warn-restrict.c | 93 +++++++++++---------- gcc/gimple.h | 14 ++++ gcc/testsuite/ChangeLog | 6 ++ gcc/testsuite/gcc.dg/Wstringop-overflow-5.c | 58 +++++++++++++ gcc/testsuite/gcc.dg/Wstringop-overflow-6.c | 59 +++++++++++++ gcc/tree-ssa-strlen.c | 7 +- 8 files changed, 223 insertions(+), 48 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/Wstringop-overflow-5.c create mode 100644 gcc/testsuite/gcc.dg/Wstringop-overflow-6.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b1b32998fde..aa0247df98f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2018-06-12 Martin Sebor + + PR tree-optimization/85259 + * builtins.c (compute_objsize): Handle constant offsets. + * gimple-ssa-warn-restrict.c (maybe_diag_offset_bounds): Return + true iff a warning has been issued. + * gimple.h (gimple_nonartificial_location): New function. + * tree-ssa-strlen.c (maybe_diag_stxncpy_trunc): Call + gimple_nonartificial_location and handle -Wno-system-headers. + (handle_builtin_stxncpy): Same. + 2018-06-12 Martin Sebor PR c/85931 diff --git a/gcc/builtins.c b/gcc/builtins.c index 8707e0cfbc3..6b3e6b2ea96 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -3326,10 +3326,29 @@ compute_objsize (tree dest, int ostype) { /* compute_builtin_object_size fails for addresses with non-constant offsets. Try to determine the range of - such an offset here and use it to adjus the constant + such an offset here and use it to adjust the constant size. */ tree off = gimple_assign_rhs2 (stmt); - if (TREE_CODE (off) == SSA_NAME + if (TREE_CODE (off) == INTEGER_CST) + { + if (tree size = compute_objsize (dest, ostype)) + { + wide_int wioff = wi::to_wide (off); + wide_int wisiz = wi::to_wide (size); + + /* Ignore negative offsets for now. For others, + use the lower bound as the most optimistic + estimate of the (remaining) size. */ + if (wi::sign_mask (wioff)) + ; + else if (wi::ltu_p (wioff, wisiz)) + return wide_int_to_tree (TREE_TYPE (size), + wi::sub (wisiz, wioff)); + else + return size_zero_node; + } + } + else if (TREE_CODE (off) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (off))) { wide_int min, max; diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c index cc50fba21d7..7dedb24fb9d 100644 --- a/gcc/gimple-ssa-warn-restrict.c +++ b/gcc/gimple-ssa-warn-restrict.c @@ -1593,8 +1593,6 @@ maybe_diag_offset_bounds (location_t loc, gcall *call, tree func, int strict, loc = expansion_point_location_if_in_system_header (loc); - tree type; - char rangestr[2][64]; if (ooboff[0] == ooboff[1] || (ooboff[0] != ref.offrange[0] @@ -1605,6 +1603,8 @@ maybe_diag_offset_bounds (location_t loc, gcall *call, tree func, int strict, (long long) ooboff[0].to_shwi (), (long long) ooboff[1].to_shwi ()); + bool warned = false; + if (oobref == error_mark_node) { if (ref.sizrange[0] == ref.sizrange[1]) @@ -1614,6 +1614,8 @@ maybe_diag_offset_bounds (location_t loc, gcall *call, tree func, int strict, (long long) ref.sizrange[0].to_shwi (), (long long) ref.sizrange[1].to_shwi ()); + tree type; + if (DECL_P (ref.base) && TREE_CODE (type = TREE_TYPE (ref.base)) == ARRAY_TYPE) { @@ -1621,19 +1623,22 @@ maybe_diag_offset_bounds (location_t loc, gcall *call, tree func, int strict, "%G%qD pointer overflow between offset %s " "and size %s accessing array %qD with type %qT", call, func, rangestr[0], rangestr[1], ref.base, type)) - inform (DECL_SOURCE_LOCATION (ref.base), - "array %qD declared here", ref.base); + { + inform (DECL_SOURCE_LOCATION (ref.base), + "array %qD declared here", ref.base); + warned = true; + } else - warning_at (loc, OPT_Warray_bounds, - "%G%qD pointer overflow between offset %s " - "and size %s", - call, func, rangestr[0], rangestr[1]); + warned = warning_at (loc, OPT_Warray_bounds, + "%G%qD pointer overflow between offset %s " + "and size %s", + call, func, rangestr[0], rangestr[1]); } else - warning_at (loc, OPT_Warray_bounds, - "%G%qD pointer overflow between offset %s " - "and size %s", - call, func, rangestr[0], rangestr[1]); + warned = warning_at (loc, OPT_Warray_bounds, + "%G%qD pointer overflow between offset %s " + "and size %s", + call, func, rangestr[0], rangestr[1]); } else if (oobref == ref.base) { @@ -1664,22 +1669,26 @@ maybe_diag_offset_bounds (location_t loc, gcall *call, tree func, int strict, "of object %qD with type %qT"), call, func, rangestr[0], ref.base, TREE_TYPE (ref.base))) - inform (DECL_SOURCE_LOCATION (ref.base), - "%qD declared here", ref.base); + { + inform (DECL_SOURCE_LOCATION (ref.base), + "%qD declared here", ref.base); + warned = true; + } } else if (ref.basesize < maxobjsize) - warning_at (loc, OPT_Warray_bounds, - form - ? G_("%G%qD forming offset %s is out of the bounds " - "[0, %wu]") - : G_("%G%qD offset %s is out of the bounds [0, %wu]"), - call, func, rangestr[0], ref.basesize.to_uhwi ()); + warned = warning_at (loc, OPT_Warray_bounds, + form + ? G_("%G%qD forming offset %s is out " + "of the bounds [0, %wu]") + : G_("%G%qD offset %s is out " + "of the bounds [0, %wu]"), + call, func, rangestr[0], ref.basesize.to_uhwi ()); else - warning_at (loc, OPT_Warray_bounds, - form - ? G_("%G%qD forming offset %s is out of bounds") - : G_("%G%qD offset %s is out of bounds"), - call, func, rangestr[0]); + warned = warning_at (loc, OPT_Warray_bounds, + form + ? G_("%G%qD forming offset %s is out of bounds") + : G_("%G%qD offset %s is out of bounds"), + call, func, rangestr[0]); } else if (TREE_CODE (ref.ref) == MEM_REF) { @@ -1688,24 +1697,25 @@ maybe_diag_offset_bounds (location_t loc, gcall *call, tree func, int strict, type = TREE_TYPE (type); type = TYPE_MAIN_VARIANT (type); - warning_at (loc, OPT_Warray_bounds, - "%G%qD offset %s from the object at %qE is out " - "of the bounds of %qT", - call, func, rangestr[0], ref.base, type); + warned = warning_at (loc, OPT_Warray_bounds, + "%G%qD offset %s from the object at %qE is out " + "of the bounds of %qT", + call, func, rangestr[0], ref.base, type); } else { - type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref)); - - warning_at (loc, OPT_Warray_bounds, - "%G%qD offset %s from the object at %qE is out " - "of the bounds of referenced subobject %qD with type %qT " - "at offset %wu", - call, func, rangestr[0], ref.base, TREE_OPERAND (ref.ref, 1), - type, ref.refoff.to_uhwi ()); + tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref)); + + warned = warning_at (loc, OPT_Warray_bounds, + "%G%qD offset %s from the object at %qE is out " + "of the bounds of referenced subobject %qD with " + "type %qT at offset %wu", + call, func, rangestr[0], ref.base, + TREE_OPERAND (ref.ref, 1), type, + ref.refoff.to_uhwi ()); } - return true; + return warned; } /* Check a CALL statement for restrict-violations and issue warnings @@ -1815,12 +1825,7 @@ bool check_bounds_or_overlap (gcall *call, tree dst, tree src, tree dstsize, tree srcsize, bool bounds_only /* = false */) { - location_t loc = gimple_location (call); - - if (tree block = gimple_block (call)) - if (location_t *pbloc = block_nonartificial_location (block)) - loc = *pbloc; - + location_t loc = gimple_nonartificial_location (call); loc = expansion_point_location_if_in_system_header (loc); tree func = gimple_call_fndecl (call); diff --git a/gcc/gimple.h b/gcc/gimple.h index 00a9f207bdf..ab095f63908 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -1796,6 +1796,20 @@ gimple_has_location (const gimple *g) } +/* Return non-artificial location information for statement G. */ + +static inline location_t +gimple_nonartificial_location (const gimple *g) +{ + location_t *ploc = NULL; + + if (tree block = gimple_block (g)) + ploc = block_nonartificial_location (block); + + return ploc ? *ploc : gimple_location (g); +} + + /* Return the file name of the location of STMT. */ static inline const char * diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f009f2b4768..9ab1822be6e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -3,6 +3,12 @@ PR fortran/44491 * gfortran.dg/pr44491.f90: New testcase +2018-06-12 Martin Sebor + + PR tree-optimization/85259 + * gcc.dg/Wstringop-overflow-5.c: New test. + * gcc.dg/Wstringop-overflow-6.c: New test. + 2018-06-12 Martin Sebor PR c/85931 diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-5.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-5.c new file mode 100644 index 00000000000..4abce01b5f8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-5.c @@ -0,0 +1,58 @@ +/* PR tree-optimization/85259 - Missing -Wstringop-overflow= since r256683 + { dg-do compile } + { dg-options "-O2 -Wstringop-overflow" } */ + +extern char* strcpy (char*, const char*); +extern char* strcat (char*, const char*); + +char a1[1]; +char a2[2]; +char a3[3]; +char a4[4]; +char a5[5]; +char a6[6]; +char a7[7]; +char a8[8]; + +/* Verify that at least one instance of -Wstringop-overflow is issued + for each pair of strcpy/strcat calls. */ + +void test_strcpy_strcat_1 (void) +{ + strcpy (a1, "1"), strcat (a1, "2"); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ +} + +void test_strcpy_strcat_2 (void) +{ + strcpy (a2, "12"), strcat (a2, "3"); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ +} + +void test_strcpy_strcat_3 (void) +{ + strcpy (a3, "123"), strcat (a3, "4"); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ +} + +void test_strcpy_strcat_4 (void) +{ + strcpy (a4, "1234"), strcat (a4, "5"); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ +} + +void test_strcpy_strcat_5 (void) +{ + strcpy (a5, "12345"), strcat (a5, "6"); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ +} + +void test_strcpy_strcat_6 (void) +{ + strcpy (a6, "123456"), strcat (a6, "7"); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ +} + +void test_strcpy_strcat_7 (void) +{ + strcpy (a7, "1234567"), strcat (a7, "8"); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ +} + +void test_strcpy_strcat_8 (void) +{ + strcpy (a8, "12345678"), strcat (a8, "9"); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-6.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-6.c new file mode 100644 index 00000000000..9284a87aeb0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-6.c @@ -0,0 +1,59 @@ +/* PR tree-optimization/85259 - Missing -Wstringop-overflow= since r256683 + { dg-do compile } + { dg-options "-O2 -Wstringop-overflow -ftrack-macro-expansion=0" } */ + +#define bos1(p) __builtin_object_size (p, 1) +#define strcat(d, s) __builtin___strcat_chk (d, s, bos1 (d)) +#define strcpy(d, s) __builtin___strcpy_chk (d, s, bos1 (d)) + +char a1[1]; +char a2[2]; +char a3[3]; +char a4[4]; +char a5[5]; +char a6[6]; +char a7[7]; +char a8[8]; + +/* Verify that at least one instance of -Wstringop-overflow is issued + for each pair of strcpy/strcat calls. */ + +void test_strcpy_strcat_1 (void) +{ + strcpy (a1, "1"), strcat (a1, "2"); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ +} + +void test_strcpy_strcat_2 (void) +{ + strcpy (a2, "12"), strcat (a2, "3"); /* { dg-warning "\\\[-Wstringop-overflow=]" "bug 86121" { xfail *-*-* } } */ +} + +void test_strcpy_strcat_3 (void) +{ + strcpy (a3, "123"), strcat (a3, "4"); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ +} + +void test_strcpy_strcat_4 (void) +{ + strcpy (a4, "1234"), strcat (a4, "5"); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ +} + +void test_strcpy_strcat_5 (void) +{ + strcpy (a5, "12345"), strcat (a5, "6"); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ +} + +void test_strcpy_strcat_6 (void) +{ + strcpy (a6, "123456"), strcat (a6, "7"); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ +} + +void test_strcpy_strcat_7 (void) +{ + strcpy (a7, "1234567"), strcat (a7, "8"); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ +} + +void test_strcpy_strcat_8 (void) +{ + strcpy (a8, "12345678"), strcat (a8, "9"); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ +} diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index cc1f5f48e34..8794cc240c8 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -1886,7 +1886,9 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt) } } - location_t callloc = gimple_location (stmt); + location_t callloc = gimple_nonartificial_location (stmt); + callloc = expansion_point_location_if_in_system_header (callloc); + tree func = gimple_call_fndecl (stmt); if (lenrange[0] != 0 || !wi::neg_p (lenrange[1])) @@ -2069,7 +2071,8 @@ handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *gsi) to strlen(S)). */ strinfo *silen = get_strinfo (pss->first); - location_t callloc = gimple_location (stmt); + location_t callloc = gimple_nonartificial_location (stmt); + callloc = expansion_point_location_if_in_system_header (callloc); tree func = gimple_call_fndecl (stmt); -- 2.30.2