[libc-commits] [libc] bf7f01d - [libc] fix strtofloatingpoint on rare edge case

Michael Jones via libc-commits libc-commits at lists.llvm.org
Mon Jul 18 14:23:37 PDT 2022


Author: Michael Jones
Date: 2022-07-18T14:23:33-07:00
New Revision: bf7f01d857eda2ea0753e92149c2941c7ad84bbc

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

LOG: [libc] fix strtofloatingpoint on rare edge case

Currently, there are two string parsers that can be used in a call to
strtofloatingpoint. There is the main parser used by Clinger's fast path
and Eisel-Lemire, and the backup parser used by Simple Decimal
Conversion. There was a bug in the backup parser where if the number had
more than 800 digits (the size of the SDC buffer) before the decimal
point, it would just ignore the digits after the 800th and not count
them into the exponent. This patch fixes that issue and adds regression
tests.

Reviewed By: lntue

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

Added: 
    

Modified: 
    libc/src/__support/high_precision_decimal.h
    libc/test/src/stdlib/strtod_test.cpp

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/high_precision_decimal.h b/libc/src/__support/high_precision_decimal.h
index 94bc51a0cfa11..d3f3f02da9606 100644
--- a/libc/src/__support/high_precision_decimal.h
+++ b/libc/src/__support/high_precision_decimal.h
@@ -285,12 +285,15 @@ class HighPrecisionDecimal {
   // handle leading spaces.
   HighPrecisionDecimal(const char *__restrict numString) {
     bool saw_dot = false;
+    // This counts the digits in the number, even if there isn't space to store
+    // them all.
+    uint32_t total_digits = 0;
     while (isdigit(*numString) || *numString == '.') {
       if (*numString == '.') {
         if (saw_dot) {
           break;
         }
-        this->decimal_point = this->num_digits;
+        this->decimal_point = total_digits;
         saw_dot = true;
       } else {
         if (*numString == '0' && this->num_digits == 0) {
@@ -298,6 +301,7 @@ class HighPrecisionDecimal {
           ++numString;
           continue;
         }
+        ++total_digits;
         if (this->num_digits < MAX_NUM_DIGITS) {
           this->digits[this->num_digits] =
               static_cast<uint8_t>(*numString - '0');
@@ -309,9 +313,8 @@ class HighPrecisionDecimal {
       ++numString;
     }
 
-    if (!saw_dot) {
-      this->decimal_point = this->num_digits;
-    }
+    if (!saw_dot)
+      this->decimal_point = total_digits;
 
     if ((*numString | 32) == 'e') {
       ++numString;

diff  --git a/libc/test/src/stdlib/strtod_test.cpp b/libc/test/src/stdlib/strtod_test.cpp
index 1a778fe05002a..e82547825c064 100644
--- a/libc/test/src/stdlib/strtod_test.cpp
+++ b/libc/test/src/stdlib/strtod_test.cpp
@@ -80,6 +80,104 @@ TEST_F(LlvmLibcStrToDTest, SpecificFailures) {
   run_test("2.16656806400000023841857910156251e9", 36,
            uint64_t(0x41e0246690000001));
   run_test("27949676547093071875", 20, uint64_t(0x43f83e132bc608c9));
+  run_test(
+      "100000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000e-800",
+      806, 0x3ff0000000000000);
+  run_test(
+      "100000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000e-799",
+      806, 0x4024000000000000);
+  run_test(
+      "100000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "0000000000e-800",
+      807, 0x4024000000000000);
+  run_test(
+      "10000000000000000000000000000000000000000000000000000000000000000e-64",
+      69, 0x3ff0000000000000);
+  run_test(
+      "100000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000e-128",
+      134, 0x3ff0000000000000);
+  run_test("1000000000000000000000000000000000000000000000000000000000000000000"
+           "0000000000000000000000000000000000000000000000000000000000000000000"
+           "0000000000000000000000000000000000000000000000000000000000000000000"
+           "00000000000000000000000000000000000000000000000000000000e-256",
+           262, 0x3ff0000000000000);
+  run_test("1000000000000000000000000000000000000000000000000000000000000000000"
+           "0000000000000000000000000000000000000000000000000000000000000000000"
+           "0000000000000000000000000000000000000000000000000000000000000000000"
+           "0000000000000000000000000000000000000000000000000000000000000000000"
+           "0000000000000000000000000000000000000000000000000000000000000000000"
+           "0000000000000000000000000000000000000000000000000000000000000000000"
+           "0000000000000000000000000000000000000000000000000000000000000000000"
+           "00000000000000000000000000000000000000000000e-512",
+           518, 0x3ff0000000000000);
+  run_test(
+      "100000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "00000000000000000e-1024",
+      1031, 0x3ff0000000000000);
+  run_test(
+      "0"
+      "100000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "000000000000000000000000000000000000000000000000000000000000000000000000"
+      "00000000000000000e-1024",
+      1032, 0x3ff0000000000000);
 }
 
 TEST_F(LlvmLibcStrToDTest, FuzzFailures) {


        


More information about the libc-commits mailing list