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; ------------------