diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/fxcrt/fx_basic_util.cpp | 41 | ||||
-rw-r--r-- | core/fxcrt/fx_basic_util_unittest.cpp | 47 |
2 files changed, 84 insertions, 4 deletions
diff --git a/core/fxcrt/fx_basic_util.cpp b/core/fxcrt/fx_basic_util.cpp index abd84a864f..663ca93e9c 100644 --- a/core/fxcrt/fx_basic_util.cpp +++ b/core/fxcrt/fx_basic_util.cpp @@ -16,8 +16,15 @@ #include <algorithm> #include <cctype> +#include <limits> #include <memory> +namespace { + +const int kDefaultIntValue = 0; + +} // namespace + bool FX_atonum(const CFX_ByteStringC& strc, void* pData) { if (strc.Find('.') != -1) { FX_FLOAT* pFloat = static_cast<FX_FLOAT*>(pData); @@ -25,26 +32,52 @@ bool FX_atonum(const CFX_ByteStringC& strc, void* pData) { return false; } - int cc = 0; - pdfium::base::CheckedNumeric<int> integer = 0; + // Note, numbers in PDF are typically of the form 123, -123, etc. But, + // for things like the Permissions on the encryption hash the number is + // actually an unsigned value. We use a uint32_t so we can deal with the + // unsigned and then check for overflow if the user actually signed the value. + // The Permissions flag is listed in Table 3.20 PDF 1.7 spec. + pdfium::base::CheckedNumeric<uint32_t> integer = 0; bool bNegative = false; + bool bSigned = false; + int cc = 0; if (strc[0] == '+') { cc++; + bSigned = true; } else if (strc[0] == '-') { bNegative = true; + bSigned = true; cc++; } + while (cc < strc.GetLength() && std::isdigit(strc[cc])) { integer = integer * 10 + FXSYS_toDecimalDigit(strc.CharAt(cc)); if (!integer.IsValid()) break; cc++; } + + // We have a sign, and the value was greater then a regular integer + // we've overflowed, reset to the default value. + if (bSigned) { + if (bNegative) { + if (integer.ValueOrDefault(kDefaultIntValue) > + static_cast<uint32_t>(std::numeric_limits<int>::max()) + 1) { + integer = kDefaultIntValue; + } + } else if (integer.ValueOrDefault(kDefaultIntValue) > + static_cast<uint32_t>(std::numeric_limits<int>::max())) { + integer = kDefaultIntValue; + } + } + + // Switch back to the int space so we can flip to a negative if we need. + int value = static_cast<int>(integer.ValueOrDefault(kDefaultIntValue)); if (bNegative) - integer = -integer; + value = -value; int* pInt = static_cast<int*>(pData); - *pInt = integer.ValueOrDefault(0); + *pInt = value; return true; } diff --git a/core/fxcrt/fx_basic_util_unittest.cpp b/core/fxcrt/fx_basic_util_unittest.cpp index 3272eab70c..6eae6696ad 100644 --- a/core/fxcrt/fx_basic_util_unittest.cpp +++ b/core/fxcrt/fx_basic_util_unittest.cpp @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <limits> + #include "core/fxcrt/include/fx_basic.h" #include "testing/fx_string_testhelpers.h" #include "testing/gtest/include/gtest/gtest.h" @@ -28,3 +30,48 @@ TEST(fxge, GetBits32) { } } } + +TEST(fxcrt, FX_atonum) { + int i; + EXPECT_TRUE(FX_atonum("10", &i)); + EXPECT_EQ(10, i); + + EXPECT_TRUE(FX_atonum("-10", &i)); + EXPECT_EQ(-10, i); + + EXPECT_TRUE(FX_atonum("+10", &i)); + EXPECT_EQ(10, i); + + EXPECT_TRUE(FX_atonum("-2147483648", &i)); + EXPECT_EQ(std::numeric_limits<int>::min(), i); + + EXPECT_TRUE(FX_atonum("2147483647", &i)); + EXPECT_EQ(2147483647, i); + + // Value overflows. + EXPECT_TRUE(FX_atonum("-2147483649", &i)); + EXPECT_EQ(0, i); + + // Value overflows. + EXPECT_TRUE(FX_atonum("+2147483648", &i)); + EXPECT_EQ(0, i); + + // Value overflows. + EXPECT_TRUE(FX_atonum("4223423494965252", &i)); + EXPECT_EQ(0, i); + + // No explicit sign will allow the number to go negative. This is for things + // like the encryption Permissions flag (Table 3.20 PDF 1.7 spec) + EXPECT_TRUE(FX_atonum("4294965252", &i)); + EXPECT_EQ(-2044, i); + + EXPECT_TRUE(FX_atonum("-4294965252", &i)); + EXPECT_EQ(0, i); + + EXPECT_TRUE(FX_atonum("+4294965252", &i)); + EXPECT_EQ(0, i); + + float f; + EXPECT_FALSE(FX_atonum("3.24", &f)); + EXPECT_FLOAT_EQ(3.24f, f); +} |