From: Jakub Jelinek Date: Sat, 11 Feb 2023 14:57:54 +0000 (+0100) Subject: ipa-cp: Punt for too large offsets [PR108605] X-Git-Tag: basepoints/gcc-14~1389 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=00a49047b504b27a8dd19d819c7bc48d54078767;p=thirdparty%2Fgcc.git ipa-cp: Punt for too large offsets [PR108605] Seems most of IPA uses unsigned type for byte offsets ipa-param-manipulation.h: unsigned unit_offset; ipa-param-manipulation.h: unsigned unit_offset; ipa-param-manipulation.h: void register_replacement (tree base, unsigned unit_offset, tree replacement); ipa-param-manipulation.h: tree lookup_replacement (tree base, unsigned unit_offset); ipa-param-manipulation.h: unsigned unit_offset); ipa-prop.h: unsigned unit_offset; ipa-prop.h: tree get_value (int index, unsigned unit_offset, bool by_ref) const; ipa-prop.h: tree get_value (int index, unsigned unit_offset) const; ipa-prop.h: const ipa_argagg_value *get_elt (int index, unsigned unit_offset) const; ipa-cp.cc:ipa_argagg_value_list::get_elt (int index, unsigned unit_offset) const ipa-cp.cc: unsigned prev_unit_offset = 0; ipa-cp.cc:ipa_argagg_value_list::get_value (int index, unsigned unit_offset) const ipa-cp.cc:ipa_argagg_value_list::get_value (int index, unsigned unit_offset, ipa-cp.cc: unsigned other_offset = other.m_elts[i].unit_offset; ipa-cp.cc: unsigned prev_unit_offset = 0; ipa-cp.cc: unsigned prev_unit_offset = 0; ipa-cp.cc: unsigned this_offset = elts[i].unit_offset; ipa-cp.cc: unsigned prev_unit_offset = 0; ipa-cp.cc: unsigned unit_offset = aglat->offset / BITS_PER_UNIT; ipa-cp.cc: unsigned prev_unit_offset = 0; ipa-param-manipulation.cc: unsigned unit_offset; ipa-param-manipulation.cc:isra_get_ref_base_and_offset (tree expr, tree *base_p, unsigned *unit_offset_p) ipa-param-manipulation.cc: unsigned unit_offset, ipa-param-manipulation.cc: unsigned unit_offset) ipa-param-manipulation.cc:ipa_param_body_adjustments::lookup_replacement (tree base, unsigned unit_offset) ipa-param-manipulation.cc: unsigned unit_offset; ipa-prop.cc: unsigned unit_offset = bit_offset / BITS_PER_UNIT; ipa-sra.cc: unsigned unit_offset; ipa-sra.cc: unsigned unit_offset; ipa-sra.cc: unsigned unit_offset, unsigned unit_size) ipa-sra.cc: unsigned offset = argacc->unit_offset + delta_offset; so before converting a HOST_WIDE_INT bit offset to unsigned byte offset we need to punt for too large offsets. Some places do that, e.g. isra_get_ref_base_and_offset has if (offset < 0 || (offset / BITS_PER_UNIT) > UINT_MAX) return false; but ipa_agg_value_from_jfunc doesn't. The following patch fixes that. 2023-02-11 Jakub Jelinek PR ipa/108605 * ipa-cp.cc (ipa_agg_value_from_jfunc): Return NULL_TREE also if item->offset bit position is too large to be representable as unsigned int byte position. * c-c++-common/pr108605.c: New test. --- diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc index 826bbc6222b7..4b8dedc0c518 100644 --- a/gcc/ipa-cp.cc +++ b/gcc/ipa-cp.cc @@ -1982,7 +1982,9 @@ ipa_agg_value_from_jfunc (ipa_node_params *info, cgraph_node *node, tree value = NULL_TREE; int src_idx; - if (item->offset < 0 || item->jftype == IPA_JF_UNKNOWN) + if (item->offset < 0 + || item->jftype == IPA_JF_UNKNOWN + || item->offset >= (HOST_WIDE_INT) UINT_MAX * BITS_PER_UNIT) return NULL_TREE; if (item->jftype == IPA_JF_CONST) diff --git a/gcc/testsuite/c-c++-common/pr108605.c b/gcc/testsuite/c-c++-common/pr108605.c new file mode 100644 index 000000000000..418b37d70192 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr108605.c @@ -0,0 +1,24 @@ +/* PR ipa/108605 */ +/* { dg-do compile { target { lp64 || llp64 } } } */ +/* { dg-options "-O2" } */ + +struct S { + char a, b, c; + int d[__INT_MAX__], e; +}; + +void +foo (struct S *s) +{ + if (s->b && s->c != 0) + __builtin_abort (); +} + +void +bar (void) +{ + struct S s[2]; + s[0].a = 0; + s[0].e = 0; + foo (s); +}