From f343165275ab5a22546f82f75351a876449309a7 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Fri, 5 Oct 2018 16:43:11 +0000 Subject: [PATCH] PR tree-optimization/87490 - ICE in expand_builtin_strnlen with a constant argument and non-constant bound gcc/ChangeLog: PR tree-optimization/87490 * builtins.c (expand_builtin_strnlen): Handle a null data.decl consistently. gcc/testsuite/ChangeLog: PR tree-optimization/87490 * gcc.dg/pr87490.c: New test. * gcc.dg/warn-strnlen-no-nul-2.c: Same. From-SVN: r264876 --- gcc/ChangeLog | 6 ++ gcc/builtins.c | 38 ++++++++--- gcc/testsuite/ChangeLog | 6 ++ gcc/testsuite/gcc.dg/pr87490.c | 13 ++++ gcc/testsuite/gcc.dg/warn-strnlen-no-nul-2.c | 66 ++++++++++++++++++++ 5 files changed, 119 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr87490.c create mode 100644 gcc/testsuite/gcc.dg/warn-strnlen-no-nul-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ad2283099a2..b12413f558f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2018-10-05 Martin Sebor + + PR tree-optimization/87490 + * builtins.c (expand_builtin_strnlen): Handle a null data.decl + consistently. + 2018-10-05 Richard Biener PR tree-optimization/63155 diff --git a/gcc/builtins.c b/gcc/builtins.c index 2cb1996dad3..25e01e4092b 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -3151,21 +3151,39 @@ expand_builtin_strnlen (tree exp, rtx target, machine_mode target_mode) exp, func, min.to_uhwi (), max.to_uhwi (), maxobjsize)) TREE_NO_WARNING (exp) = true; + bool exact = true; if (!len || TREE_CODE (len) != INTEGER_CST) - return NULL_RTX; + { + data.decl = unterminated_array (src, &len, &exact); + if (!data.decl) + return NULL_RTX; + } - if (!TREE_NO_WARNING (exp) - && wi::ltu_p (wi::to_wide (len), min) - && warning_at (loc, OPT_Wstringop_overflow_, - "%K%qD specified bound [%wu, %wu] " - "exceeds the size %E of unterminated array", - exp, func, min.to_uhwi (), max.to_uhwi (), len)) + if (data.decl + && !TREE_NO_WARNING (exp) + && (wi::ltu_p (wi::to_wide (len), min) + || !exact)) { - inform (DECL_SOURCE_LOCATION (data.decl), - "referenced argument declared here"); - TREE_NO_WARNING (exp) = true; + location_t warnloc + = expansion_point_location_if_in_system_header (loc); + + if (warning_at (warnloc, OPT_Wstringop_overflow_, + exact + ? G_("%K%qD specified bound [%wu, %wu] exceeds " + "the size %E of unterminated array") + : G_("%K%qD specified bound [%wu, %wu] may exceed " + "the size of at most %E of unterminated array"), + exp, func, min.to_uhwi (), max.to_uhwi (), len)) + { + inform (DECL_SOURCE_LOCATION (data.decl), + "referenced argument declared here"); + TREE_NO_WARNING (exp) = true; + } } + if (data.decl) + return NULL_RTX; + if (wi::gtu_p (min, wi::to_wide (len))) return expand_expr (len, target, target_mode, EXPAND_NORMAL); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 996ec0b5758..90790612e36 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2018-10-05 Martin Sebor + + PR tree-optimization/87490 + * gcc.dg/pr87490.c: New test. + * gcc.dg/warn-strnlen-no-nul-2.c: Same. + 2018-10-05 Steve Ellcey PR tree-optimization/71625 diff --git a/gcc/testsuite/gcc.dg/pr87490.c b/gcc/testsuite/gcc.dg/pr87490.c new file mode 100644 index 00000000000..61c36e3a69d --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr87490.c @@ -0,0 +1,13 @@ +/* PR tree-optimization/87490 - ICE in expand_builtin_strnlen with a constant + argument and non-constant bound + { dg-do compile } + { dg-options "-O1 -Wall -fno-optimize-strlen" } */ + +void test_O1 (int i) +{ + int n = (i & 3) | 1; + + /* The ICE here triggers at -O1, with tree-ssa-strlen disabled. */ + if (__builtin_strnlen ("", n) != 0) + __builtin_abort (); +} diff --git a/gcc/testsuite/gcc.dg/warn-strnlen-no-nul-2.c b/gcc/testsuite/gcc.dg/warn-strnlen-no-nul-2.c new file mode 100644 index 00000000000..e91e8cef751 --- /dev/null +++ b/gcc/testsuite/gcc.dg/warn-strnlen-no-nul-2.c @@ -0,0 +1,66 @@ +/* Verify that calls to strnlen with an unterminated array and + an excessive non-constant bound are diagnosed. + { dg-do compile } + { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */ + +#include "range.h" + +extern size_t strnlen (const char*, size_t); + +const char a[5] = "12345"; /* { dg-message "declared here" } */ +enum { asz = sizeof a }; + +int v0 = 0; +int v1 = 1; + +void sink (int, ...); + +#define CONCAT(a, b) a ## b +#define CAT(a, b) CONCAT(a, b) + +#define T(str, n) \ + __attribute__ ((noipa)) \ + void CAT (test_, __LINE__) (void) { \ + int i0 = 0, i1 = i0 + 1, i2 = i1 + 1, i3 = i2 + 1; \ + sink (strnlen (str, n), i0, i1, i2, i3); \ + } typedef void dummy_type + + +T (a, UR (asz, -1)); +T (a, UR (asz - 1, -1)); +T (a, UR (asz - 2, -1)); +T (a, UR (asz - 5, -1)); +T (&a[0], UR (asz, -1)); +T (&a[0] + 1, UR (asz, asz + 1)); /* { dg-warning "specified bound \\\[5, 6] exceeds the size 4 of unterminated array" } */ +T (&a[1], UR (asz, 6)); /* { dg-warning "specified bound \\\[5, 6] exceeds the size 4 of unterminated array" } */ +T (&a[1], UR (asz - 1, 7)); +T (&a[v0], UR (asz, 8)); /* { dg-warning "specified bound \\\[5, 8] may exceed the size of at most 5 of unterminated array" } */ +T (&a[v0] + 1, UR (asz, 9)); /* { dg-warning "specified bound \\\[5, 9] may exceed the size of at most 5 of unterminated array" } */ + +T (a, UR (asz + 1, asz + 2)); /* { dg-warning "specified bound \\\[6, 7] exceeds the size 5 " } */ +T (&a[0], UR (asz + 1, 10)); /* { dg-warning "unterminated" } */ +T (&a[0] + 1, UR (asz - 1, 11)); +T (&a[0] + 1, UR (asz + 1, 12)); /* { dg-warning "unterminated" } */ +T (&a[1], UR (asz + 1, 13)); /* { dg-warning "unterminated" } */ +T (&a[v0], UR (asz + 1, 14)); /* { dg-warning "unterminated" } */ +T (&a[v0] + 1, UR (asz + 1, 15)); /* { dg-warning "unterminated" } */ + +T (&a[v0] + 1, UR (DIFF_MAX, SIZE_MAX)); /* { dg-warning "unterminated" } */ + +T (&a[v0] + 1, UR (DIFF_MAX + (size_t)1, SIZE_MAX)); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size " } */ + + +const char c[4] = "1234"; + +void test (int n0) +{ + char a[] = "123"; + + if (n0 < 4) + n0 = 4; + int n1 = __builtin_strlen (a); + + int n = n0 < n1 ? n1 : n0; + + sink (strnlen (c + n, n + 1)); /* { dg-warning "specified bound \\\[5, \[0-9\]+] may exceed the size of at most 4 of unterminated array" } */ +} -- 2.30.2