Skip to content

Commit

Permalink
Fix segfault during encoding of CONSTRUCTORs
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Eric Botcazou committed Mar 19, 2021
1 parent 287e3e8 commit b980edb
Showing 1 changed file with 32 additions and 13 deletions.
45 changes: 32 additions & 13 deletions gcc/fold-const.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++)
Expand All @@ -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)
Expand Down

0 comments on commit b980edb

Please sign in to comment.