This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Ada] Fix memory corruption on assignment to global mutable


The storage allocated for a mutable variable must be large enough to hold
any possible value assigned to the variable over its lifetime. The storage
for library level variables of this kind is dynamically allocated via
build_allocator, which is also passed an initializer expression when need
be. Unless told not to by an argument, build_allocator uses the size of the
initializer as the amount to allocate if this size is simpler to compute.

The bug here is that there was nothing to prevent the use of the
initializer's size in build_allocator for a mutable variable. This causes
trouble when the initializer is not as large as any possible value the
variable may be assigned with later on, since an assignment with a larger
value overruns the allocated storage.

The fix is to note that we are processing a mutable object at a point
prior to the build_allocator call, and to tell build_allocator to ignore
the initializer's size in this case.

Testcase should output:
M0.Has_Data is FALSE
M1.Has_Data is TRUE
M2.Has_Data is FALSE

with Ada.Text_IO; use Ada.Text_IO;
with MSGS; use MSGS;
procedure P is
begin
   Prepare (M1);
   Put_Line ("M0.Has_Data is " & Boolean'Image (M0.Has_Data));
   Put_Line ("M1.Has_Data is " & Boolean'Image (M1.Has_Data));
   Put_Line ("M2.Has_Data is " & Boolean'Image (M2.Has_Data));
   if M2.Has_Data or M0.Has_Data then
      raise Program_Error;
   end if;
end;
with MSG_Data; use MSG_Data;
package MSGS is
   type Message_T (Has_Data : Boolean := False) is record
      case Has_Data is
         when True => Data  : Message_Data_T;
         when False => null;
      end case;
   end record;
   procedure Prepare (M : in out Message_T);
   M0, M1, M2 : Message_T := (Has_Data => False);
end;
with Ada.Text_IO; use Ada.Text_IO;
package body MSGS is
   Default_Message_Data : Message_Data_T := (others => 16#7FFF_FFFF#);
   procedure Prepare (M : in out Message_T) is
   begin M := (Has_Data => True, Data => Default_Message_Data); end;
end;
with Sizes;
package MSG_Data is
   Msize : constant Sizes.Message_Data_Range := Sizes.Message_Data_Size;
   type Message_Data_T is array (1 .. Msize) of Natural;
end;
package Sizes is
   pragma Elaborate_Body;
   subtype Message_Data_Range is Natural range 1 .. 5000;
   function Message_Data_Size return Message_Data_Range;
end Sizes;
package body Sizes is
   function Message_Data_Size return Message_Data_Range is
   begin return Message_Data_Range'Last; end;
end;

2005-08-29  Olivier Hainque  <hainque@adacore.com>

	* decl.c (gnat_to_gnu_entity) <E_Variable>: When allocating storage for
	a library level mutable variable with an initializer, tell
	build_allocator to ignore the initializer's size. It may not be large
	enough for all the values that might be assigned to the variable later
	on.

Attachment: difs.2
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]