Patchwork [Ada] Proper handling of meaningless size clauses

login
register
mail settings
Submitter Arnaud Charlet
Date July 9, 2012, 1:05 p.m.
Message ID <20120709130544.GA16576@adacore.com>
Download mbox | patch
Permalink /patch/169819/
State New
Headers show

Comments

Arnaud Charlet - July 9, 2012, 1:05 p.m.
This patch fixes an internal overflow when computing the alignment of a record
component whose size is improperly specified as larger than the largest integer
value.

Compiling the following must yield:

prob.adb:6:38: warning: 4294967168 bits of "Unsigned_Integer_4" unused
prob.adb:13:45: size for "Uint4" too small, minimum allowed is 16#1000_0000_0#

---
procedure prob is
   Int_Size : constant  := 4;
   Int_Size_Bit : constant  := 4 * Standard'Storage_Unit;

   type Unsigned_Integer_4 is mod 2 ** Int_Size_Bit;
   for Unsigned_Integer_4'Size use 2 ** Int_Size_Bit;

   type Rec is record
         Uint4 : Unsigned_Integer_4;
      end record;
   for Rec use
      record
         Uint4 at 0 range 0 .. Int_Size_Bit - 1;
      end record;
begin
   null;
end;

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

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

	* layout.adb (Set_Elem_Alignment): Protect against meaningless
	size clause, to prevent overflow in internal computation of
	alignment.

Patch

Index: layout.adb
===================================================================
--- layout.adb	(revision 189366)
+++ layout.adb	(working copy)
@@ -3103,11 +3103,22 @@ 
       --  the type, or the maximum allowed alignment.
 
       declare
-         S             : constant Int := UI_To_Int (Esize (E)) / SSU;
+         S             : Int;
+
          A             : Nat;
          Max_Alignment : Nat;
 
       begin
+         --  The given esize may be larger that int'last because of a previous
+         --  error, and the call to UI_To_Int will fail, so use default.
+
+         if Esize (E) / SSU > Ttypes.Maximum_Alignment then
+            S := Ttypes.Maximum_Alignment;
+
+         else
+            S := UI_To_Int (Esize (E)) / SSU;
+         end if;
+
          --  If the default alignment of "double" floating-point types is
          --  specifically capped, enforce the cap.