[libc-commits] [libc] 548789b - [libc] Fix HPD on extremely long numbers

Michael Jones via libc-commits libc-commits at lists.llvm.org
Fri Aug 18 11:04:05 PDT 2023


Author: Michael Jones
Date: 2023-08-18T11:03:45-07:00
New Revision: 548789b071a79e3f275a059871110eb8e828f6c0

URL: https://github.com/llvm/llvm-project/commit/548789b071a79e3f275a059871110eb8e828f6c0
DIFF: https://github.com/llvm/llvm-project/commit/548789b071a79e3f275a059871110eb8e828f6c0.diff

LOG: [libc] Fix HPD on extremely long numbers

The fuzzer found that a 100,000 digit number could possibly return an
incorrect result. This patch fixes the issue.

Reviewed By: lntue

Differential Revision: https://reviews.llvm.org/D158118

Added: 
    

Modified: 
    libc/src/__support/high_precision_decimal.h
    libc/test/src/__support/high_precision_decimal_test.cpp

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/high_precision_decimal.h b/libc/src/__support/high_precision_decimal.h
index cb0a78b900b19c..486e289f4ce614 100644
--- a/libc/src/__support/high_precision_decimal.h
+++ b/libc/src/__support/high_precision_decimal.h
@@ -334,13 +334,24 @@ class HighPrecisionDecimal {
     if ((*numString | 32) == 'e') {
       ++numString;
       if (isdigit(*numString) || *numString == '+' || *numString == '-') {
-        int32_t add_to_exp = strtointeger<int32_t>(numString, 10);
-        if (add_to_exp > 100000) {
-          add_to_exp = 100000;
-        } else if (add_to_exp < -100000) {
-          add_to_exp = -100000;
+        auto result = strtointeger<int32_t>(numString, 10);
+        if (result.has_error()) {
+          // TODO: handle error
         }
-        this->decimal_point += add_to_exp;
+        int32_t add_to_exponent = result.value;
+
+        // Here we do this operation as int64 to avoid overflow.
+        int64_t temp_exponent = static_cast<int64_t>(this->decimal_point) +
+                                static_cast<int64_t>(add_to_exponent);
+
+        // Theoretically these numbers should be MAX_EXPONENT for long double,
+        // but that should be ~16,000 which is much less than 1 << 30.
+        if (temp_exponent > (1 << 30)) {
+          temp_exponent = (1 << 30);
+        } else if (temp_exponent < -(1 << 30)) {
+          temp_exponent = -(1 << 30);
+        }
+        this->decimal_point = static_cast<int32_t>(temp_exponent);
       }
     }
 

diff  --git a/libc/test/src/__support/high_precision_decimal_test.cpp b/libc/test/src/__support/high_precision_decimal_test.cpp
index 004bc1c82f861e..abe4a604b4a390 100644
--- a/libc/test/src/__support/high_precision_decimal_test.cpp
+++ b/libc/test/src/__support/high_precision_decimal_test.cpp
@@ -391,3 +391,18 @@ TEST(LlvmLibcHighPrecisionDecimalTest, RoundingTest) {
 
   EXPECT_EQ(hpd.round_to_integer_type<UInt128>(), result);
 }
+
+TEST(LlvmLibcHighPrecisionDecimalTest, BigExpTest) {
+  __llvm_libc::internal::HighPrecisionDecimal big_hpd =
+      __llvm_libc::internal::HighPrecisionDecimal("1e123456789");
+
+  // We need to add one to handle the digit before the decimal point in our
+  // number.
+  EXPECT_EQ(big_hpd.get_decimal_point(), 123456789 + 1);
+
+  __llvm_libc::internal::HighPrecisionDecimal big_negative_hpd =
+      __llvm_libc::internal::HighPrecisionDecimal("1e-123456789");
+
+  // Same, but since the number is negative the net result is -123456788
+  EXPECT_EQ(big_negative_hpd.get_decimal_point(), -123456789 + 1);
+}


        


More information about the libc-commits mailing list