Hash values must be folded by the length of the buckets array. The length of
the buckets array is a discriminant of the container type, which means that it
is possible for the user to specify 0 as the length value. Insert must
therefore check for this case specifically, in order to prevent divide-by-zero
errors that would otherwise occur during computation of the bucket index for a
given key.

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

2011-08-31  Matthew Heaney  <hea...@adacore.com>

        * a-cbhama.adb, a-cbhase.adb (Insert): Check for zero-length buckets
        array.

Index: a-cbhama.adb
===================================================================
--- a-cbhama.adb        (revision 178358)
+++ a-cbhama.adb        (working copy)
@@ -513,6 +513,11 @@
       procedure Assign_Key (Node : in out Node_Type) is
       begin
          Node.Key := Key;
+
+         --  Note that we do not also assign the element component of the node
+         --  here, because this version of Insert does not accept an element
+         --  parameter.
+
          --  Node.Element := New_Item;
       end Assign_Key;
 
@@ -530,20 +535,17 @@
    --  Start of processing for Insert
 
    begin
-      --  ???
-      --  if HT_Ops.Capacity (HT) = 0 then
-      --     HT_Ops.Reserve_Capacity (HT, 1);
-      --  end if;
+      --  The buckets array length is specified by the user as a discriminant
+      --  of the container type, so it is possible for the buckets array to
+      --  have a length of zero. We must check for this case specifically, in
+      --  order to prevent divide-by-zero errors later, when we compute the
+      --  buckets array index value for a key, given its hash value.
 
-      Local_Insert (Container, Key, Position.Node, Inserted);
+      if Container.Buckets'Length = 0 then
+         raise Capacity_Error with "No capacity for insertion";
+      end if;
 
-      --  ???
-      --  if Inserted
-      --    and then HT.Length > HT_Ops.Capacity (HT)
-      --  then
-      --     HT_Ops.Reserve_Capacity (HT, HT.Length);
-      --  end if;
-
+      Local_Insert (Container, Key, Position.Node, Inserted);
       Position.Container := Container'Unchecked_Access;
    end Insert;
 
@@ -590,20 +592,17 @@
    --  Start of processing for Insert
 
    begin
-      --  ??
-      --  if HT_Ops.Capacity (HT) = 0 then
-      --     HT_Ops.Reserve_Capacity (HT, 1);
-      --  end if;
+      --  The buckets array length is specified by the user as a discriminant
+      --  of the container type, so it is possible for the buckets array to
+      --  have a length of zero. We must check for this case specifically, in
+      --  order to prevent divide-by-zero errors later, when we compute the
+      --  buckets array index value for a key, given its hash value.
 
-      Local_Insert (Container, Key, Position.Node, Inserted);
+      if Container.Buckets'Length = 0 then
+         raise Capacity_Error with "No capacity for insertion";
+      end if;
 
-      --  ???
-      --  if Inserted
-      --    and then HT.Length > HT_Ops.Capacity (HT)
-      --  then
-      --     HT_Ops.Reserve_Capacity (HT, HT.Length);
-      --  end if;
-
+      Local_Insert (Container, Key, Position.Node, Inserted);
       Position.Container := Container'Unchecked_Access;
    end Insert;
 
Index: a-cbhase.adb
===================================================================
--- a-cbhase.adb        (revision 178358)
+++ a-cbhase.adb        (working copy)
@@ -710,19 +710,17 @@
    --  Start of processing for Insert
 
    begin
-      --  ???
-      --  if HT_Ops.Capacity (HT) = 0 then
-      --     HT_Ops.Reserve_Capacity (HT, 1);
-      --  end if;
+      --  The buckets array length is specified by the user as a discriminant
+      --  of the container type, so it is possible for the buckets array to
+      --  have a length of zero. We must check for this case specifically, in
+      --  order to prevent divide-by-zero errors later, when we compute the
+      --  buckets array index value for an element, given its hash value.
 
-      Local_Insert (Container, New_Item, Node, Inserted);
+      if Container.Buckets'Length = 0 then
+         raise Capacity_Error with "No capacity for insertion";
+      end if;
 
-      --  ???
-      --  if Inserted
-      --    and then HT.Length > HT_Ops.Capacity (HT)
-      --  then
-      --     HT_Ops.Reserve_Capacity (HT, HT.Length);
-      --  end if;
+      Local_Insert (Container, New_Item, Node, Inserted);
    end Insert;
 
    ------------------

Reply via email to