diff mbox series

[Ada] Fix operations on Unbounded_String...

Message ID 20210617143311.GA10815@adacore.com
State New
Headers show
Series [Ada] Fix operations on Unbounded_String... | expand

Commit Message

Pierre-Marie de Rodat June 17, 2021, 2:33 p.m. UTC
... when its length is close to Natural'Last.

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

gcc/ada/

	* libgnat/a-strunb__shared.ads (Allocate): Additional parameter
	to provide additional amount of space to be allocated.
	* libgnat/a-strunb__shared.adb (Aligned_Max_Length): Limit
	length to Natural'Last when requested length is larger than it.
	(Allocate): Merge two slightly different implementations into
	one.
diff mbox series

Patch

diff --git a/gcc/ada/libgnat/a-strunb__shared.adb b/gcc/ada/libgnat/a-strunb__shared.adb
--- a/gcc/ada/libgnat/a-strunb__shared.adb
+++ b/gcc/ada/libgnat/a-strunb__shared.adb
@@ -50,11 +50,13 @@  package body Ada.Strings.Unbounded is
    --  align the returned memory on the maximum alignment as malloc does not
    --  know the target alignment.
 
-   function Aligned_Max_Length (Max_Length : Natural) return Natural;
+   function Aligned_Max_Length
+     (Required_Length : Natural;
+      Reserved_Length : Natural) return Natural;
    --  Returns recommended length of the shared string which is greater or
-   --  equal to specified length. Calculation take in sense alignment of the
-   --  allocated memory segments to use memory effectively by Append/Insert/etc
-   --  operations.
+   --  equal to specified required length and desired reserved length.
+   --  Calculation takes into account alignment of the allocated memory
+   --  segments to use memory effectively by Append/Insert/etc operations.
 
    function Sum (Left : Natural; Right : Integer) return Natural with Inline;
    --  Returns summary of Left and Right, raise Constraint_Error on overflow
@@ -63,11 +65,6 @@  package body Ada.Strings.Unbounded is
    --  Returns multiplication of Left and Right, raise Constraint_Error on
    --  overflow
 
-   function Allocate
-     (Length, Growth : Natural) return not null Shared_String_Access;
-   --  Allocates new Shared_String with at least specified Length plus optional
-   --  Growth.
-
    ---------
    -- "&" --
    ---------
@@ -490,17 +487,24 @@  package body Ada.Strings.Unbounded is
    -- Aligned_Max_Length --
    ------------------------
 
-   function Aligned_Max_Length (Max_Length : Natural) return Natural is
+   function Aligned_Max_Length
+     (Required_Length : Natural;
+      Reserved_Length : Natural) return Natural
+   is
       Static_Size : constant Natural :=
                       Empty_Shared_String'Size / Standard'Storage_Unit;
       --  Total size of all Shared_String static components
    begin
-      if Max_Length > Natural'Last - Static_Size then
+      if Required_Length > Natural'Last - Static_Size - Reserved_Length then
+         --  Total requested length is larger than maximum possible length.
+         --  Use of Static_Size needed to avoid overflows in expression to
+         --  compute aligned length.
          return Natural'Last;
+
       else
          return
-           ((Static_Size + Max_Length - 1) / Min_Mul_Alloc + 2) * Min_Mul_Alloc
-             - Static_Size;
+           ((Static_Size + Required_Length + Reserved_Length - 1)
+              / Min_Mul_Alloc + 2) * Min_Mul_Alloc - Static_Size;
       end if;
    end Aligned_Max_Length;
 
@@ -509,35 +513,21 @@  package body Ada.Strings.Unbounded is
    --------------
 
    function Allocate
-     (Max_Length : Natural) return not null Shared_String_Access
+     (Required_Length : Natural;
+      Reserved_Length : Natural := 0) return not null Shared_String_Access
    is
    begin
       --  Empty string requested, return shared empty string
 
-      if Max_Length = 0 then
+      if Required_Length = 0 then
          return Empty_Shared_String'Access;
 
       --  Otherwise, allocate requested space (and probably some more room)
 
       else
-         return new Shared_String (Aligned_Max_Length (Max_Length));
-      end if;
-   end Allocate;
-
-   --------------
-   -- Allocate --
-   --------------
-
-   function Allocate
-     (Length, Growth : Natural) return not null Shared_String_Access is
-   begin
-      if Natural'Last - Growth < Length then
-         --  Then Length + Growth would be more than Natural'Last
-
-         return new Shared_String (Integer'Last);
-
-      else
-         return Allocate (Length + Growth);
+         return
+           new Shared_String
+                 (Aligned_Max_Length (Required_Length, Reserved_Length));
       end if;
    end Allocate;
 
@@ -657,7 +647,7 @@  package body Ada.Strings.Unbounded is
         System.Atomic_Counters.Is_One (Item.Counter)
           and then Item.Max_Length >= Length
           and then Item.Max_Length <=
-                     Aligned_Max_Length (Length + Length / Growth_Factor);
+                     Aligned_Max_Length (Length, Length / Growth_Factor);
    end Can_Be_Reused;
 
    -----------


diff --git a/gcc/ada/libgnat/a-strunb__shared.ads b/gcc/ada/libgnat/a-strunb__shared.ads
--- a/gcc/ada/libgnat/a-strunb__shared.ads
+++ b/gcc/ada/libgnat/a-strunb__shared.ads
@@ -725,10 +725,12 @@  private
    --  store string with specified length effectively.
 
    function Allocate
-     (Max_Length : Natural) return not null Shared_String_Access;
-   --  Allocates new Shared_String with at least specified maximum length.
-   --  Actual maximum length of the allocated Shared_String can be slightly
-   --  greater. Returns reference to Empty_Shared_String when requested length
+     (Required_Length : Natural;
+      Reserved_Length : Natural := 0) return not null Shared_String_Access;
+   --  Allocates new Shared_String. Actual maximum length of allocated object
+   --  is at least the specified required length. Additional storage is
+   --  allocated to allow to store up to the specified reserved length when
+   --  possible. Returns reference to Empty_Shared_String when requested length
    --  is zero.
 
    Empty_Shared_String : aliased Shared_String (0);