]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ada: Add guard to System.Val_Real.Large_Powfive against pathological input
authorEric Botcazou <ebotcazou@adacore.com>
Tue, 17 Dec 2024 19:00:38 +0000 (20:00 +0100)
committerMarc Poulhiès <dkm@gcc.gnu.org>
Tue, 7 Jan 2025 12:33:33 +0000 (13:33 +0100)
There is no need to keep multiplying the result once it saturates to +Inf.

gcc/ada/ChangeLog:

* libgnat/s-powflt.ads (Maxpow_Exact): Minor comment fix.
* libgnat/s-powlfl.ads (Maxpow_Exact): Likewise.
* libgnat/s-powllf.ads (Maxpow_Exact): Likewise.
* libgnat/s-valrea.adb (Large_Powfive) [1 parameter]: Exit the loop
as soon as the result saturates to +Inf.
(Large_Powfive) [2 parameters]: Likewise.

gcc/ada/libgnat/s-powflt.ads
gcc/ada/libgnat/s-powlfl.ads
gcc/ada/libgnat/s-powllf.ads
gcc/ada/libgnat/s-valrea.adb

index eadea7f914dbf8c4e5b187c14fe9e47160270738..ae904f056173fb70d2cbd8c9f09942da276aab11 100644 (file)
@@ -36,7 +36,7 @@ package System.Powten_Flt is
 
    Maxpow_Exact : constant := 10;
    --  Largest power of five exactly representable with Float. It is equal to
-   --  floor (M * log 2 / log 5), when M is the size of the mantissa (24).
+   --  floor (M * log 2 / log 5), where M is the size of the mantissa (24).
    --  It also works for any number of the form 5*(2**N) and in particular 10.
 
    Maxpow : constant := Maxpow_Exact * 2;
index 13630fcad40a03872e079bcddefef5bdd231460c..2bf72d9c17d3162a615f4db302d371308eb72f38 100644 (file)
@@ -36,7 +36,7 @@ package System.Powten_LFlt is
 
    Maxpow_Exact : constant := 22;
    --  Largest power of five exactly representable with Long_Float. It is equal
-   --  to floor (M * log 2 / log 5), when M is the size of the mantissa (53).
+   --  to floor (M * log 2 / log 5), where M is the size of the mantissa (53).
    --  It also works for any number of the form 5*(2**N) and in particular 10.
 
    Maxpow : constant := Maxpow_Exact * 2;
index b470ae044de851073913eb52503d672ad653ec9a..b184b31ea9c037a631497c9ae64778c484c04ea2 100644 (file)
@@ -37,8 +37,8 @@ package System.Powten_LLF is
    Maxpow_Exact : constant :=
      (if Long_Long_Float'Machine_Mantissa = 64 then 27 else 22);
    --  Largest power of five exactly representable with Long_Long_Float. It is
-   --  equal to floor (M * log 2 / log 5), when M is the size of the mantissa
-   --  assumed to be either 64 for IEEE Extended or 53 for IEEE Double.
+   --  equal to floor (M * log 2 / log 5), where M is the size of the mantissa
+   --  (assumed to be either 64 for IEEE Extended or 53 for IEEE Double).
    --  It also works for any number of the form 5*(2**N) and in particular 10.
 
    Maxpow : constant := Maxpow_Exact * 2;
index f554280c0ead0d600e34d20cd612e0791203aaf9..3b0f0a99a638179f4edca5993e8df093da54c6be 100644 (file)
@@ -336,6 +336,7 @@ package body System.Val_Real is
       pragma Import (Ada, Powfive_300);
       for Powfive_300'Address use Powfive_300_Address;
 
+      H : Double_T;
       R : Double_T;
       E : Natural;
 
@@ -359,8 +360,15 @@ package body System.Val_Real is
          E := Exp - Maxpow;
       end if;
 
+      --  Accumulate 5**Maxpow into R until E <= Maxpow or R saturates to +Inf
+
       while E > Maxpow loop
+         H := R;
          R := R * Powfive (Maxpow);
+         if R = H then
+            E := Maxpow;
+            exit;
+         end if;
          E := E - Maxpow;
       end loop;
 
@@ -381,6 +389,7 @@ package body System.Val_Real is
       pragma Import (Ada, Powfive);
       for Powfive'Address use Powfive_Address;
 
+      H : Double_T;
       R : Double_T;
       E : Natural;
 
@@ -407,8 +416,15 @@ package body System.Val_Real is
          S := 0;
       end if;
 
+      --  Accumulate 5**Maxpow into R until E <= Maxpow or R saturates to +Inf
+
       while E > Maxpow loop
+         H := R;
          R := R * Powfive (Maxpow);
+         if R = H then
+            E := Maxpow;
+            exit;
+         end if;
          E := E - Maxpow;
       end loop;