aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2021-03-19 09:21:11 +0100
committerEric Botcazou <ebotcazou@adacore.com>2021-03-19 09:25:23 +0100
commitb980edba506442c846cc779243ceeffd13065740 (patch)
tree0cc3db8d427a637ef5e93d1ac113907e6e4e971c /gcc/fold-const.c
parent287e3e8466f44f9d395a2e4dcfcda56cc34ceb1c (diff)
downloadgcc-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.c45
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)