]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ipa/116296 - avoid overflow in modref_access_node::contains
authorRichard Biener <rguenther@suse.de>
Tue, 27 Jan 2026 12:01:19 +0000 (13:01 +0100)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 27 Jan 2026 14:59:55 +0000 (15:59 +0100)
The following aovids overflow when scaling the param offset
difference by BITS_PER_UNIT by using poly_offset_int instead of
poly_int64 for the computations.

PR ipa/116296
* ipa-modref-tree.cc (modref_access_node::contains): Use
poly_offset_int for the param offset difference and the
overlap computation.

* gcc.dg/torture/pr116296.c: New testcase.

gcc/ipa-modref-tree.cc
gcc/testsuite/gcc.dg/torture/pr116296.c [new file with mode: 0644]

index b94bbc9bdd798580713021a533f2fd3bf669a116..73faa919b6c698446291cc276fc15795e11dc4fb 100644 (file)
@@ -59,7 +59,7 @@ modref_access_node::operator == (const modref_access_node &a) const
 bool
 modref_access_node::contains (const modref_access_node &a) const
 {
-  poly_int64 aoffset_adj = 0;
+  poly_offset_int aoffset_adj = 0;
   if (parm_index != MODREF_UNKNOWN_PARM)
     {
       if (parm_index != a.parm_index)
@@ -80,7 +80,8 @@ modref_access_node::contains (const modref_access_node &a) const
              a.offset may result in non-negative offset again.
              Ubsan fails on val << LOG_BITS_PER_UNIT where val
              is negative.  */
-          aoffset_adj = (a.parm_offset - parm_offset)
+          aoffset_adj = (poly_offset_int::from (a.parm_offset, SIGNED)
+                         - poly_offset_int::from (parm_offset, SIGNED))
                         * BITS_PER_UNIT;
        }
     }
@@ -96,10 +97,14 @@ modref_access_node::contains (const modref_access_node &a) const
              || !known_le (size, a.size)))
        return false;
       if (known_size_p (max_size))
-       return known_subrange_p (a.offset + aoffset_adj,
-                                a.max_size, offset, max_size);
+       return known_subrange_p (poly_offset_int::from (a.offset, SIGNED)
+                                + aoffset_adj, a.max_size,
+                                poly_offset_int::from (offset, SIGNED),
+                                max_size);
       else
-       return known_le (offset, a.offset + aoffset_adj);
+       return known_le (poly_offset_int::from (offset, SIGNED),
+                        poly_offset_int::from (a.offset, SIGNED)
+                        + aoffset_adj);
     }
   return true;
 }
diff --git a/gcc/testsuite/gcc.dg/torture/pr116296.c b/gcc/testsuite/gcc.dg/torture/pr116296.c
new file mode 100644 (file)
index 0000000..4170a10
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target int32plus } */
+
+short g(unsigned long h, int i[11][11], short c)
+{
+  for (unsigned long j = 0; j < h; j -= 0x105f000000000000ull)
+    c = c > i[j][j];
+  return c;
+}