The following fixes a latent issue in chrec_fold_plus_poly_poly
which suffers from being prone to signed overflow UB in the way
it associates additions when accumulating two polynomical CHRECs.
Similar to r16-2781-gafafae097232e7 the following catches the
obvious cases when constants are involved without trying to address
the actual underlying issue.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.
PR tree-optimization/125652
* tree-chrec.cc (chrec_fold_plus_poly_poly): Avoid UB
integer overflow in accumulating CHREC_RIGHT.
* gcc.dg/torture/pr125652.c: New testcase.
---
gcc/testsuite/gcc.dg/torture/pr125652.c | 32 +++++++++++++++++++++++++
gcc/tree-chrec.cc | 10 ++++++++
2 files changed, 42 insertions(+)
create mode 100644 gcc/testsuite/gcc.dg/torture/pr125652.c
diff --git a/gcc/testsuite/gcc.dg/torture/pr125652.c
b/gcc/testsuite/gcc.dg/torture/pr125652.c
new file mode 100644
index 00000000000..a99da3fb5ca
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr125652.c
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+/* { dg-require-effective-target int32plus } */
+
+#include <stdint.h>
+
+int a, b, c, d;
+
+void e(int64_t f, int64_t g)
+{
+ int64_t h = 1, *i, **j;
+ while (1)
+ {
+ i = &h;
+ j = &i;
+ if (h <= h + f - ~h)
+ break;
+ *i += g;
+ }
+ c *= 2;
+ d = a >> b + d;
+}
+
+int f123()
+{
+ e(-2147483627, 4611686018427387904);
+ return 0;
+}
+
+int main()
+{
+ return f123();
+}
diff --git a/gcc/tree-chrec.cc b/gcc/tree-chrec.cc
index f02314aa570..9869389a7b9 100644
--- a/gcc/tree-chrec.cc
+++ b/gcc/tree-chrec.cc
@@ -127,6 +127,16 @@ chrec_fold_plus_poly_poly (enum tree_code code,
if (chrec_zerop (right))
return left;
+ /* When we have an evolution in a non-wrapping type and in the process of
+ accumulating CHREC_RIGHT there was overflow this indicates in the
+ association that happened in accumulating the CHRECs clearly involved UB.
+ Avoid this. When accumulating two CHRECs we basically turn
+ (a + INCR1) + INCR2 into a + (INCR1 + INCR2) which is not always valid.
+ Note this check only catches few invalid cases. */
+ else if ((INTEGRAL_TYPE_P (type) && ! TYPE_OVERFLOW_WRAPS (type))
+ && TREE_CODE (right) == INTEGER_CST
+ && TREE_OVERFLOW (right))
+ return chrec_dont_know;
else
return build_polynomial_chrec
(CHREC_VARIABLE (poly0), left, right);
--
2.51.0