[Ada] Avoid overflow in Table reallocation

Submitted by Arnaud Charlet on Jan. 3, 2013, 1:07 p.m.

Details

Message ID 20130103130720.GA4537@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Jan. 3, 2013, 1:07 p.m.
This patch avoids an overflow that occurs when tables get bigger than about 12
million elements. No change in functionality (except for enormous tables), so
no test available.

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

2013-01-03  Bob Duff  <duff@adacore.com>

	* table.adb (Reallocate): Calculate new Length in
	Long_Integer to avoid overflow.

Patch hide | download patch | download mbox

Index: table.adb
===================================================================
--- table.adb	(revision 194841)
+++ table.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2009, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -172,6 +172,7 @@ 
 
       procedure Reallocate is
          New_Size   : Memory.size_t;
+         New_Length : Long_Integer;
 
       begin
          if Max < Last_Val then
@@ -186,11 +187,15 @@ 
             --  the increment value or 10, which ever is larger (the reason
             --  for the use of 10 here is to ensure that the table does really
             --  increase in size (which would not be the case for a table of
-            --  length 10 increased by 3% for instance).
+            --  length 10 increased by 3% for instance). Do the intermediate
+            --  calculation in Long_Integer to avoid overflow.
 
             while Max < Last_Val loop
-               Length := Int'Max (Length * (100 + Table_Increment) / 100,
-                                  Length + 10);
+               New_Length :=
+                 Long_Integer (Length) *
+                 (100 + Long_Integer (Table_Increment))
+                 / 100;
+               Length := Int'Max (Int (New_Length), Length + 10);
                Max := Min + Length - 1;
             end loop;