Patchwork [Ada] Avoid overflow in Table reallocation

login
register
mail settings
Submitter Arnaud Charlet
Date Jan. 3, 2013, 1:07 p.m.
Message ID <20130103130720.GA4537@adacore.com>
Download mbox | patch
Permalink /patch/209248/
State New
Headers show

Comments

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

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;