diff options
author | John McCall <rjmccall@apple.com> | 2010-02-26 22:20:41 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-02-26 22:20:41 +0000 |
commit | b42cc681ba56af1ef92ccd80a86714f634cd7d4c (patch) | |
tree | e40d3b5928da05eda17d31ed5ab22185924c57d9 | |
parent | c3a9376215ca0a215ede2913b41cd98abd069fbb (diff) | |
download | bcm5719-llvm-b42cc681ba56af1ef92ccd80a86714f634cd7d4c.tar.gz bcm5719-llvm-b42cc681ba56af1ef92ccd80a86714f634cd7d4c.zip |
Make APFloat's string-parsing routines a bit safer against very large exponents.
llvm-svn: 97278
-rw-r--r-- | llvm/lib/Support/APFloat.cpp | 18 | ||||
-rw-r--r-- | llvm/unittests/ADT/APFloatTest.cpp | 7 |
2 files changed, 23 insertions, 2 deletions
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp index 1e6d22f18ed..f90973feab8 100644 --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/lib/Support/APFloat.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include <limits.h> #include <cstring> using namespace llvm; @@ -2345,11 +2346,24 @@ APFloat::convertFromDecimalString(const StringRef &str, roundingMode rounding_mo if (decDigitValue(*D.firstSigDigit) >= 10U) { category = fcZero; fs = opOK; - } else if ((D.normalizedExponent + 1) * 28738 - <= 8651 * (semantics->minExponent - (int) semantics->precision)) { + + /* Check whether the normalized exponent is high enough to overflow + max during the log-rebasing in the max-exponent check below. */ + } else if (D.normalizedExponent - 1 > INT_MAX / 42039) { + fs = handleOverflow(rounding_mode); + + /* If it wasn't, then it also wasn't high enough to overflow max + during the log-rebasing in the min-exponent check. Check that it + won't overflow min in either check, then perform the min-exponent + check. */ + } else if (D.normalizedExponent - 1 < INT_MIN / 42039 || + (D.normalizedExponent + 1) * 28738 <= + 8651 * (semantics->minExponent - (int) semantics->precision)) { /* Underflow to zero and round. */ zeroSignificand(); fs = normalize(rounding_mode, lfLessThanHalf); + + /* We can finally safely perform the max-exponent check. */ } else if ((D.normalizedExponent - 1) * 42039 >= 12655 * semantics->maxExponent) { /* Overflow and round. */ diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp index b02cc3e3172..3277c836da2 100644 --- a/llvm/unittests/ADT/APFloatTest.cpp +++ b/llvm/unittests/ADT/APFloatTest.cpp @@ -236,6 +236,13 @@ TEST(APFloatTest, fromDecimalString) { EXPECT_EQ(2.05e12, APFloat(APFloat::IEEEdouble, "002.05000e12").convertToDouble()); EXPECT_EQ(2.05e+12, APFloat(APFloat::IEEEdouble, "002.05000e+12").convertToDouble()); EXPECT_EQ(2.05e-12, APFloat(APFloat::IEEEdouble, "002.05000e-12").convertToDouble()); + + // These are "carefully selected" to overflow the fast log-base + // calculations in APFloat.cpp + EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "99e99999").isInfinity()); + EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "-99e99999").isInfinity()); + EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "1e-99999").isPosZero()); + EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "-1e-99999").isNegZero()); } TEST(APFloatTest, fromHexadecimalString) { |