From b5f0a87686b299e9fc6f683be258101b54383d54 Mon Sep 17 00:00:00 2001 From: Michael Jones Date: Mon, 17 Apr 2023 10:30:28 -0700 Subject: [PATCH] [libc] Fix strtod hex exponent overflow bug Same issue as was fixed in commit 3d95323, but for hexadecimal floats. Reviewed By: sivachandra Differential Revision: https://reviews.llvm.org/D148545 --- libc/src/__support/str_to_float.h | 9 ++++----- libc/test/src/stdlib/strtod_test.cpp | 3 +++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h index 6c298d47ff87f..0697cf0a68c32 100644 --- a/libc/src/__support/str_to_float.h +++ b/libc/src/__support/str_to_float.h @@ -1052,13 +1052,12 @@ hexadecimal_string_to_float(const char *__restrict src, // If the result is in the valid range, then we use it. The valid range is // also within the int32 range, so this prevents overflow issues. - if (temp_exponent < fputil::FPBits::MAX_EXPONENT && - temp_exponent > -fputil::FPBits::MAX_EXPONENT) { - exponent = static_cast(temp_exponent); - } else if (temp_exponent > fputil::FPBits::MAX_EXPONENT) { + if (temp_exponent > fputil::FPBits::MAX_EXPONENT) { exponent = fputil::FPBits::MAX_EXPONENT; - } else { + } else if (temp_exponent < -fputil::FPBits::MAX_EXPONENT) { exponent = -fputil::FPBits::MAX_EXPONENT; + } else { + exponent = static_cast(temp_exponent); } } } diff --git a/libc/test/src/stdlib/strtod_test.cpp b/libc/test/src/stdlib/strtod_test.cpp index aa81eca7a04aa..fee32cd5fab34 100644 --- a/libc/test/src/stdlib/strtod_test.cpp +++ b/libc/test/src/stdlib/strtod_test.cpp @@ -220,6 +220,9 @@ TEST_F(LlvmLibcStrToDTest, FuzzFailures) { "200000000000000000E608", 1462, uint64_t(0x7ff0000000000000), ERANGE); + // Same as above but for hex. + run_test("0x0164810157p2047", 17, uint64_t(0x7ff0000000000000), ERANGE); + // This bug was in the handling of very large exponents in the exponent // marker. Previously anything greater than 10,000 would be set to 10,000. // This caused incorrect behavior if there were more than 10,000 '0's in the