diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2021-03-19 09:21:11 +0100 |
---|---|---|
committer | Eric Botcazou <ebotcazou@adacore.com> | 2021-03-19 09:25:23 +0100 |
commit | b980edba506442c846cc779243ceeffd13065740 (patch) | |
tree | 0cc3db8d427a637ef5e93d1ac113907e6e4e971c /gcc/fold-const.c | |
parent | 287e3e8466f44f9d395a2e4dcfcda56cc34ceb1c (diff) | |
download | gcc-b980edba506442c846cc779243ceeffd13065740.zip gcc-b980edba506442c846cc779243ceeffd13065740.tar.gz gcc-b980edba506442c846cc779243ceeffd13065740.tar.bz2 |
Fix segfault during encoding of CONSTRUCTORs
The segfault occurs in native_encode_initializer when it is encoding the
CONSTRUCTOR for an array whose lower bound is negative (it's OK in Ada).
The computation of the current position is done in HOST_WIDE_INT and this
does not work for arrays whose original range has a negative lower bound
and a positive upper bound; the computation must be done in sizetype
instead so that it may wrap around.
gcc/
PR middle-end/99641
* fold-const.c (native_encode_initializer) <CONSTRUCTOR>: For an
array type, do the computation of the current position in sizetype.
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 45 |
1 files changed, 32 insertions, 13 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index e0bdb4b..1ebc73d 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -8051,21 +8051,21 @@ native_encode_initializer (tree init, unsigned char *ptr, int len, int o = off == -1 ? 0 : off; if (TREE_CODE (type) == ARRAY_TYPE) { - HOST_WIDE_INT min_index; + tree min_index; unsigned HOST_WIDE_INT cnt; HOST_WIDE_INT curpos = 0, fieldsize, valueinit = -1; constructor_elt *ce; - if (TYPE_DOMAIN (type) == NULL_TREE - || !tree_fits_shwi_p (TYPE_MIN_VALUE (TYPE_DOMAIN (type)))) + if (!TYPE_DOMAIN (type) + || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST) return 0; fieldsize = int_size_in_bytes (TREE_TYPE (type)); if (fieldsize <= 0) return 0; - min_index = tree_to_shwi (TYPE_MIN_VALUE (TYPE_DOMAIN (type))); - if (ptr != NULL) + min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type)); + if (ptr) memset (ptr, '\0', MIN (total_bytes - off, len)); for (cnt = 0; ; cnt++) @@ -8084,21 +8084,40 @@ native_encode_initializer (tree init, unsigned char *ptr, int len, break; else pos = total_bytes; + if (index && TREE_CODE (index) == RANGE_EXPR) { - if (!tree_fits_shwi_p (TREE_OPERAND (index, 0)) - || !tree_fits_shwi_p (TREE_OPERAND (index, 1))) + if (TREE_CODE (TREE_OPERAND (index, 0)) != INTEGER_CST + || TREE_CODE (TREE_OPERAND (index, 1)) != INTEGER_CST) + return 0; + offset_int wpos + = wi::sext (wi::to_offset (TREE_OPERAND (index, 0)) + - wi::to_offset (min_index), + TYPE_PRECISION (sizetype)); + wpos *= fieldsize; + if (!wi::fits_shwi_p (pos)) return 0; - pos = (tree_to_shwi (TREE_OPERAND (index, 0)) - min_index) - * fieldsize; - count = (tree_to_shwi (TREE_OPERAND (index, 1)) - - tree_to_shwi (TREE_OPERAND (index, 0))); + pos = wpos.to_shwi (); + offset_int wcount + = wi::sext (wi::to_offset (TREE_OPERAND (index, 1)) + - wi::to_offset (TREE_OPERAND (index, 0)), + TYPE_PRECISION (sizetype)); + if (!wi::fits_shwi_p (wcount)) + return 0; + count = wcount.to_shwi (); } else if (index) { - if (!tree_fits_shwi_p (index)) + if (TREE_CODE (index) != INTEGER_CST) + return 0; + offset_int wpos + = wi::sext (wi::to_offset (index) + - wi::to_offset (min_index), + TYPE_PRECISION (sizetype)); + wpos *= fieldsize; + if (!wi::fits_shwi_p (wpos)) return 0; - pos = (tree_to_shwi (index) - min_index) * fieldsize; + pos = wpos.to_shwi (); } if (mask && !CONSTRUCTOR_NO_CLEARING (init) && curpos != pos) |