[gcc r10-9458] Fix segfault during encoding of CONSTRUCTORs

Eric Botcazou ebotcazou@gcc.gnu.org
Fri Mar 19 09:46:41 GMT 2021


https://gcc.gnu.org/g:376f564b870a0afa64403a9aaf9f0ff1fc7153cf

commit r10-9458-g376f564b870a0afa64403a9aaf9f0ff1fc7153cf
Author: Eric Botcazou <ebotcazou@adacore.com>
Date:   Fri Mar 19 09:21:11 2021 +0100

    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.

Diff:
---
 gcc/fold-const.c | 44 +++++++++++++++++++++++++++++++-------------
 1 file changed, 31 insertions(+), 13 deletions(-)

diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 07ec9ab2dfa..f23ccc29922 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -7943,21 +7943,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;
 	  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_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (init), cnt, ce)
@@ -7968,19 +7968,37 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
 	      bool full = false;
 	      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 ();
 		}
 
 	      curpos = pos;


More information about the Gcc-cvs mailing list