diff mbox series

[Ada] Compiler may blow up on array aggregates whose size is very large

Message ID 20190813083157.GA38616@adacore.com
State New
Headers show
Series [Ada] Compiler may blow up on array aggregates whose size is very large | expand

Commit Message

Pierre-Marie de Rodat Aug. 13, 2019, 8:31 a.m. UTC
The compiler may crash when compiling array aggregates where the
computation of the size produces a very large number that overflows
(possibly producing a small result), such as with an aggregate of a type
that is an array of arrays, where each array range has close to
Integer'Last elements. That can lead to Aggr_Size_OK returning
incorrectly returning True, following on to allocating a very large
array in function Flatten that blows the stack.  The size computation
was being performed using type Int, so this was changed to use universal
arithmetic.

Tested on x86_64-pc-linux-gnu, committed on trunk

2019-08-13  Gary Dismukes  <dismukes@adacore.com>

gcc/ada/

	* exp_aggr.adb (Aggr_Size_OK): Compute the aggregate size using
	universal arithmetic, to avoid situations where the size
	computation overflows.

gcc/testsuite/

	* gnat.dg/aggr26.adb: New testcase.
diff mbox series

Patch

--- gcc/ada/exp_aggr.adb
+++ gcc/ada/exp_aggr.adb
@@ -344,7 +344,7 @@  package body Exp_Aggr is
       Lo   : Node_Id;
       Hi   : Node_Id;
       Indx : Node_Id;
-      Siz  : Int;
+      Size : Uint;
       Lov  : Uint;
       Hiv  : Uint;
 
@@ -468,7 +468,7 @@  package body Exp_Aggr is
          Max_Aggr_Size := 5000;
       end if;
 
-      Siz  := Component_Count (Component_Type (Typ));
+      Size := UI_From_Int (Component_Count (Component_Type (Typ)));
 
       Indx := First_Index (Typ);
       while Present (Indx) loop
@@ -538,14 +538,17 @@  package body Exp_Aggr is
                return False;
             end if;
 
-            Siz := Siz * UI_To_Int (Rng);
-         end;
+            --  Compute the size using universal arithmetic to avoid the
+            --  possibility of overflow on very large aggregates.
 
-         if Siz <= 0
-           or else Siz > Max_Aggr_Size
-         then
-            return False;
-         end if;
+            Size := Size * Rng;
+
+            if Size <= 0
+              or else Size > Max_Aggr_Size
+            then
+               return False;
+            end if;
+         end;
 
          --  Bounds must be in integer range, for later array construction
 

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/aggr26.adb
@@ -0,0 +1,10 @@ 
+--  { dg-do compile }
+
+procedure Aggr26 is
+
+    type Row is array (Positive) of Integer;
+    H : array (Positive) of Row := (others => (others => 0));  --  { dg-warning "\"Storage_Error\" will be raised at run time" }
+
+begin
+   null;
+end Aggr26;