Skip to content

Commit 548789b

Browse files
[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
1 parent 40bf363 commit 548789b

File tree

2 files changed

+32
-6
lines changed

2 files changed

+32
-6
lines changed

libc/src/__support/high_precision_decimal.h

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -334,13 +334,24 @@ class HighPrecisionDecimal {
334334
if ((*numString | 32) == 'e') {
335335
++numString;
336336
if (isdigit(*numString) || *numString == '+' || *numString == '-') {
337-
int32_t add_to_exp = strtointeger<int32_t>(numString, 10);
338-
if (add_to_exp > 100000) {
339-
add_to_exp = 100000;
340-
} else if (add_to_exp < -100000) {
341-
add_to_exp = -100000;
337+
auto result = strtointeger<int32_t>(numString, 10);
338+
if (result.has_error()) {
339+
// TODO: handle error
342340
}
343-
this->decimal_point += add_to_exp;
341+
int32_t add_to_exponent = result.value;
342+
343+
// Here we do this operation as int64 to avoid overflow.
344+
int64_t temp_exponent = static_cast<int64_t>(this->decimal_point) +
345+
static_cast<int64_t>(add_to_exponent);
346+
347+
// Theoretically these numbers should be MAX_EXPONENT for long double,
348+
// but that should be ~16,000 which is much less than 1 << 30.
349+
if (temp_exponent > (1 << 30)) {
350+
temp_exponent = (1 << 30);
351+
} else if (temp_exponent < -(1 << 30)) {
352+
temp_exponent = -(1 << 30);
353+
}
354+
this->decimal_point = static_cast<int32_t>(temp_exponent);
344355
}
345356
}
346357

libc/test/src/__support/high_precision_decimal_test.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,3 +391,18 @@ TEST(LlvmLibcHighPrecisionDecimalTest, RoundingTest) {
391391

392392
EXPECT_EQ(hpd.round_to_integer_type<UInt128>(), result);
393393
}
394+
395+
TEST(LlvmLibcHighPrecisionDecimalTest, BigExpTest) {
396+
__llvm_libc::internal::HighPrecisionDecimal big_hpd =
397+
__llvm_libc::internal::HighPrecisionDecimal("1e123456789");
398+
399+
// We need to add one to handle the digit before the decimal point in our
400+
// number.
401+
EXPECT_EQ(big_hpd.get_decimal_point(), 123456789 + 1);
402+
403+
__llvm_libc::internal::HighPrecisionDecimal big_negative_hpd =
404+
__llvm_libc::internal::HighPrecisionDecimal("1e-123456789");
405+
406+
// Same, but since the number is negative the net result is -123456788
407+
EXPECT_EQ(big_negative_hpd.get_decimal_point(), -123456789 + 1);
408+
}

0 commit comments

Comments
 (0)