Skip to content

Commit 1b9ed64

Browse files
committed
Fix #12282 (Internal error: fail to parse 1.0e4931L)
A float literal out of the range of double, such as 1.0e4931L or glibc's HUGE_VAL for compilers other than GCC (1e10000), stopped the analysis of the whole file with Internal Error. MathLib::toDoubleNumber: conversion failed: 1e10000 The stream stores the largest finite value and fails on such a literal; compilers make it infinity, so do the same.
1 parent e5f9f00 commit 1b9ed64

2 files changed

Lines changed: 16 additions & 2 deletions

File tree

‎lib/mathlib.cpp‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -532,8 +532,15 @@ double MathLib::toDoubleNumber(const std::string &str, const Token * const tok)
532532
std::istringstream istr(str);
533533
istr.imbue(std::locale::classic());
534534
double ret;
535-
if (!(istr >> ret))
536-
throw InternalError(tok, "Internal Error. MathLib::toDoubleNumber: conversion failed: " + str);
535+
if (!(istr >> ret)) {
536+
// Out of the range of double, such as 1e10000 (glibc's HUGE_VAL for
537+
// compilers other than GCC): the stream stores the largest finite
538+
// value and fails, a compiler makes it infinity.
539+
if (!isFloat(str) || std::fabs(ret) != std::numeric_limits<double>::max())
540+
throw InternalError(tok, "Internal Error. MathLib::toDoubleNumber: conversion failed: " + str);
541+
ret = std::copysign(std::numeric_limits<double>::infinity(), ret);
542+
istr.clear();
543+
}
537544
std::string s;
538545
if (istr >> s) {
539546
if (isDecimalFloat(str))

‎test/testmathlib.cpp‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,13 @@ class TestMathLib : public TestFixture {
677677
ASSERT_EQUALS_DOUBLE(static_cast<double>('\200'), MathLib::toDoubleNumber("'\\200'"), 0.000001);
678678
ASSERT_EQUALS_DOUBLE(static_cast<double>(L'A'), MathLib::toDoubleNumber("L'A'"), 0.000001);
679679

680+
// out of the range of double, like glibc's HUGE_VAL for compilers other than GCC
681+
ASSERT_EQUALS(std::numeric_limits<double>::infinity(), MathLib::toDoubleNumber("1e10000"));
682+
ASSERT_EQUALS(std::numeric_limits<double>::infinity(), MathLib::toDoubleNumber("1e10000f"));
683+
ASSERT_EQUALS(std::numeric_limits<double>::infinity(), MathLib::toDoubleNumber("1e10000L"));
684+
ASSERT_EQUALS(std::numeric_limits<double>::infinity(), MathLib::toDoubleNumber("1.5E+400"));
685+
ASSERT_EQUALS(std::numeric_limits<double>::infinity(), MathLib::toDoubleNumber("1.0e4931L")); // #12282
686+
680687
ASSERT_THROW_INTERNAL_EQUALS(MathLib::toDoubleNumber("invalid"), INTERNAL, "Internal Error. MathLib::toDoubleNumber: conversion failed: invalid");
681688

682689
// AppleClang before 18 reports a different error

0 commit comments

Comments
 (0)