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 alloc/free mishap for super-aligned fat or thin ptr


Hello,

 Super alignment for a type/object refers to requests for an alignment
 stricter than what the underlying memory allocation engine offers, the
 stack for local objects or malloc for a default allocator.

 gigi has the 'make_aligning_type' circuitry to deal with this.

 The bug fixed here is a misynchronization between build_allocator and the
 processing for a N_Free_Statement when dealing with a fat or thin pointer.

 build_allocator never makes an aligning type in such cases:

     /* If RESULT_TYPE is a fat or thin pointer, set SIZE to be the sum of the
        sizes of the object and its template.  Allocate the whole thing and
        fill in the parts that are known.  */
     else if (TYPE_FAT_OR_THIN_POINTER_P (result_type))
       { ...
         return ...;
       }
     ...
     /* If this is in the default storage pool and the type alignment is larger
        than what the default allocator supports, make an "aligning" record type

 But N_Free_Statement, via build_call_alloc_dealloc, expects an
 aligning type for super alignments whatever the kind of pointer:

     else if (gnu_obj)
        {
          /* If the required alignement was greater than what malloc guarantees,
             what we have in gnu_obj here is an address dynamically adjusted to
             match the requirement (see build_allocator).  What we need to pass
             to free is the initial underlying allocator's return value, which
             has been stored just in front of the block we have.  */
         ...
         if (align > (int) default_allocator_alignment)
         ...

 This shows up as SEGVs from the Release call in the testcase below on
 some targets:

     with Ada.Unchecked_Deallocation;
     procedure unc_release is

        type List is array (Natural range <>) of Integer;
        for List'Alignment use Standard'Maximum_Alignment;

        type List_Access is access all List;

        procedure Release is new Ada.Unchecked_Deallocation
          (Object => List, Name => List_Access);

        My_List : List_Access;
     begin
        My_List := new List (1 .. 3);
        Release (My_List);
     end;

 Short of messing with the allocators for fat pointers at this stage, the
 fix applied here synchronizes on the Free_Statement side.

 Bootstrapped and regression tested on x86_64-pc-linux-gnu. Applying to mainline.

 2007-11-16  Olivier Hainque  <hainque@adacore.com>

	ada/
	* utils2.c (build_call_alloc_dealloc) <if gnu_obj>: Move the code
	retrieving an allocator return value from a super-aligned address from
	here to ...
	* trans.c (gnat_to_gnu) <case N_Free_Statement>: ... here, and don't
	expect a super-aligned address for a fat or thin pointer.

	testsuite/
	* gnat.dg/release_unc_maxalign.adb: New test.

Attachment: release-unc-maxalign.dif
Description: Text document


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