diff mbox series

[COMMITTED,GCC12] Backport of 111009 patch.

Message ID 483435e7-95cd-4430-90d5-934fa3322885@redhat.com
State New
Headers show
Series [COMMITTED,GCC12] Backport of 111009 patch. | expand

Commit Message

Andrew MacLeod May 13, 2024, 5:49 p.m. UTC
Same patch for gcc12.

bootstraps and passes all tests on x86_64-pc-linux-gnu

On 5/9/24 10:32, Andrew MacLeod wrote:
> As requested, backported the patch for 111009 to resolve incorrect 
> ranges from addr_expr and committed to GCC 13 branch.
>
> bootstraps and passes all tests on x86_64-pc-linux-gnu
>
> Andrew
diff mbox series

Patch

commit b5d079c37e9eee15c0bfe34ffcae31e551192777
Author: Andrew MacLeod <amacleod@redhat.com>
Date:   Fri May 10 13:56:01 2024 -0400

    Fix range-ops operator_addr.
    
    Lack of symbolic information prevents op1_range from being able to draw
    the same conclusions as fold_range can.
    
            PR tree-optimization/111009
            gcc/
            * range-op.cc (operator_addr_expr::op1_range): Be more restrictive.
            * value-range.h (contains_zero_p): New.
    
            gcc/testsuite/
            * gcc.dg/pr111009.c: New.

diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index bf95f5fbaa1..2e0d67b70b6 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -3825,7 +3825,17 @@  operator_addr_expr::op1_range (irange &r, tree type,
 			       const irange &op2,
 			       relation_kind rel ATTRIBUTE_UNUSED) const
 {
-  return operator_addr_expr::fold_range (r, type, lhs, op2);
+   if (empty_range_varying (r, type, lhs, op2))
+    return true;
+
+  // Return a non-null pointer of the LHS type (passed in op2), but only
+  // if we cant overflow, eitherwise a no-zero offset could wrap to zero.
+  // See PR 111009.
+  if (!contains_zero_p (lhs) && TYPE_OVERFLOW_UNDEFINED (type))
+    r = range_nonzero (type);
+  else
+    r.set_varying (type);
+  return true;
 }
 
 
diff --git a/gcc/testsuite/gcc.dg/pr111009.c b/gcc/testsuite/gcc.dg/pr111009.c
new file mode 100644
index 00000000000..3accd9ac063
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr111009.c
@@ -0,0 +1,38 @@ 
+/* PR tree-optimization/111009 */
+/* { dg-do run } */
+/* { dg-options "-O3 -fno-strict-overflow" } */
+
+struct dso {
+ struct dso * next;
+ int maj;
+};
+
+__attribute__((noipa)) static void __dso_id__cmp_(void) {}
+
+__attribute__((noipa))
+static int bug(struct dso * d, struct dso *dso)
+{
+ struct dso **p = &d;
+ struct dso *curr = 0;
+
+ while (*p) {
+  curr = *p;
+  // prevent null deref below
+  if (!dso) return 1;
+  if (dso == curr) return 1;
+
+  int *a = &dso->maj;
+  // null deref
+  if (!(a && *a)) __dso_id__cmp_();
+
+  p = &curr->next;
+ }
+ return 0;
+}
+
+__attribute__((noipa))
+int main(void) {
+    struct dso d = { 0, 0, };
+    bug(&d, 0);
+}
+
diff --git a/gcc/value-range.h b/gcc/value-range.h
index d4cba22d540..22f5fc68d7c 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -605,6 +605,16 @@  irange::normalize_kind ()
     }
 }
 
+inline bool
+contains_zero_p (const irange &r)
+{
+  if (r.undefined_p ())
+    return false;
+
+  tree zero = build_zero_cst (r.type ());
+  return r.contains_p (zero);
+}
+
 // Return the maximum value for TYPE.
 
 inline tree