[Ada] Access to uninitialized memory by predicate check

Message ID 20190709075203.GA103049@adacore.com
State New
Headers show
Series
  • [Ada] Access to uninitialized memory by predicate check
Related show

Commit Message

Pierre-Marie de Rodat July 9, 2019, 7:52 a.m.
This patch fixes an exception or erroneous execution, when the
declaration for an object of a composite type that has a dynanic
predicate is initialized with an aggregate that requires expansion into
individual components. Prior to this patch the predicate check for the
object appeared before intialization was performed, thus accessing
uninitialized memory.

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

2019-07-09  Ed Schonberg  <schonberg@adacore.com>

gcc/ada/

	* sem_ch3.adb (Analyze_Object_Declaration): If the object type
	is a composite type that has a dynamic predicate and, the
	expression in the declaration is an aggregate, the generated
	predicate check must appear after the expanded code for the
	aggregate, which will appear after the rewritten object
	declarastion.

gcc/testsuite/

	* gnat.dg/predicate10.adb, gnat.dg/predicate10_pkg.adb,
	gnat.dg/predicate10_pkg.ads: New testcase.

Patch

--- gcc/ada/sem_ch3.adb
+++ gcc/ada/sem_ch3.adb
@@ -3649,8 +3649,10 @@  package body Sem_Ch3 is
    --  Ghost mode.
 
    procedure Analyze_Object_Declaration (N : Node_Id) is
-      Loc   : constant Source_Ptr := Sloc (N);
-      Id    : constant Entity_Id  := Defining_Identifier (N);
+      Loc       : constant Source_Ptr := Sloc (N);
+      Id        : constant Entity_Id  := Defining_Identifier (N);
+      Next_Decl : constant Node_Id := Next (N);
+
       Act_T : Entity_Id;
       T     : Entity_Id;
 
@@ -3912,6 +3914,11 @@  package body Sem_Ch3 is
             A_Id := Get_Aspect_Id (Chars (Identifier (A)));
             while Present (A) loop
                if A_Id = Aspect_Alignment or else A_Id = Aspect_Address then
+
+                  --  Set flag on object entity, for later processing at
+                  --  the freeze point.
+
+                  Set_Has_Delayed_Aspects (Id);
                   return True;
                end if;
 
@@ -4495,8 +4502,21 @@  package body Sem_Ch3 is
             null;
 
          else
-            Insert_After (N,
-              Make_Predicate_Check (T, New_Occurrence_Of (Id, Loc)));
+            --  The check must be inserted after the expanded aggregate
+            --  expansion code, if any.
+
+            declare
+               Check : constant Node_Id :=
+                 Make_Predicate_Check (T, New_Occurrence_Of (Id, Loc));
+
+            begin
+               if No (Next_Decl) then
+                  Append_To (List_Containing (N), Check);
+
+               else
+                  Insert_Before (Next_Decl, Check);
+               end if;
+            end;
          end if;
       end if;
 

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/predicate10.adb
@@ -0,0 +1,9 @@ 
+--  { dg-do run }
+
+with Predicate10_Pkg; use Predicate10_Pkg;
+
+procedure Predicate10 is
+   X : I_Pointer := new Integer'(0);
+begin
+   Foo (1, X);
+end;

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/predicate10_pkg.adb
@@ -0,0 +1,10 @@ 
+package body Predicate10_Pkg is
+   procedure Foo (
+     Length  : Natural;
+     Initial : I_Pointer
+   ) is
+      A : NI_Array  := (1 .. Length => Initial);
+   begin
+      null;
+   end Foo;
+end;

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/predicate10_pkg.ads
@@ -0,0 +1,13 @@ 
+package Predicate10_Pkg is
+   type I_Array is array (Positive range <>) of access Integer;
+
+   subtype NI_Array is I_Array with Dynamic_Predicate =>
+     (for all I of NI_Array => I /= null);
+
+   type I_Pointer is access Integer;
+
+   procedure Foo (
+     Length  : Natural;
+     Initial : I_Pointer
+   );
+end;