aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2024-03-12 10:23:19 +0100
committerJakub Jelinek <jakub@redhat.com>2024-03-12 10:23:19 +0100
commit39737cdf002637c7a652e9c3e36f369cfce581e5 (patch)
treeacfe62ce9b77705b5f5e05fc34e3a9e11a7d9740
parentcdf0c6604d03afd7f544dd8bd5d43d9ded059ada (diff)
downloadgcc-39737cdf002637c7a652e9c3e36f369cfce581e5.zip
gcc-39737cdf002637c7a652e9c3e36f369cfce581e5.tar.gz
gcc-39737cdf002637c7a652e9c3e36f369cfce581e5.tar.bz2
strlen: Fix another spot that can create invalid ranges [PR114293]
This PR is similar to PR110603 fixed with r14-8487, except in a different spot. From the memset with -1 size of non-zero value we determine minimum of (size_t) -1 and the code uses PTRDIFF_MAX - 2 (not really sure I understand why it is - 2 and not - 1, e.g. heap allocated array with PTRDIFF_MAX char elements which contain '\0' in the last element should be fine, no? One can still represent arr[PTRDIFF_MAX] - arr[0] and arr[0] - arr[PTRDIFF_MAX] in ptrdiff_t and strlen (arr) == PTRDIFF_MAX - 1) as the maximum, so again invalid range. As in the other case, it is just UB that can lead to that, and we have choice to only keep the min and use +inf for max, or only keep max and use 0 for min, or not set the range at all, or use [min, min] or [max, max] etc. The following patch uses [min, +inf]. 2024-03-12 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/114293 * tree-ssa-strlen.cc (strlen_pass::handle_builtin_strlen): If max is smaller than min, set max to ~(size_t)0. * gcc.dg/pr114293.c: New test.
-rw-r--r--gcc/testsuite/gcc.dg/pr114293.c10
-rw-r--r--gcc/tree-ssa-strlen.cc2
2 files changed, 12 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/pr114293.c b/gcc/testsuite/gcc.dg/pr114293.c
new file mode 100644
index 0000000..eb49ede
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr114293.c
@@ -0,0 +1,10 @@
+/* PR tree-optimization/114293 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -w" } */
+
+int
+foo (int x)
+{
+ __builtin_memset (&x, 5, -1);
+ return __builtin_strlen ((char *) &x);
+}
diff --git a/gcc/tree-ssa-strlen.cc b/gcc/tree-ssa-strlen.cc
index 20540c5..e09c9cc 100644
--- a/gcc/tree-ssa-strlen.cc
+++ b/gcc/tree-ssa-strlen.cc
@@ -2341,6 +2341,8 @@ strlen_pass::handle_builtin_strlen ()
wide_int min = wi::to_wide (old);
wide_int max
= wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node)) - 2;
+ if (wi::gtu_p (min, max))
+ max = wi::to_wide (TYPE_MAX_VALUE (TREE_TYPE (lhs)));
set_strlen_range (lhs, min, max);
}
else