From 5ac63523d76c429cb853fbb3ec5c6614773613b3 Mon Sep 17 00:00:00 2001 From: qining Date: Tue, 13 Sep 2016 11:57:02 -0400 Subject: [PATCH] Guard against nullptr in number parsing utilities ParseNumber(): Returns false if the given string is a nullptr. ParseAndEncodeXXXX(): Returns kInvalidText and populate error message: "The given text is a nullptr", if the givne string is a nullptr. --- source/util/parse_number.cpp | 15 +++++++++++++++ source/util/parse_number.h | 3 ++- test/ParseNumber.cpp | 27 +++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/source/util/parse_number.cpp b/source/util/parse_number.cpp index bba7545..c71b311 100644 --- a/source/util/parse_number.cpp +++ b/source/util/parse_number.cpp @@ -55,6 +55,11 @@ class ErrorMsgStream { EncodeNumberStatus ParseAndEncodeIntegerNumber( const char* text, const NumberType& type, std::function emit, std::string* error_msg) { + if (!text) { + ErrorMsgStream(error_msg) << "The given text is a nullptr"; + return EncodeNumberStatus::kInvalidText; + } + if (!IsIntegral(type)) { ErrorMsgStream(error_msg) << "The expected type is not a integer type"; return EncodeNumberStatus::kInvalidUsage; @@ -127,6 +132,11 @@ EncodeNumberStatus ParseAndEncodeIntegerNumber( EncodeNumberStatus ParseAndEncodeFloatingPointNumber( const char* text, const NumberType& type, std::function emit, std::string* error_msg) { + if (!text) { + ErrorMsgStream(error_msg) << "The given text is a nullptr"; + return EncodeNumberStatus::kInvalidText; + } + if (!IsFloating(type)) { ErrorMsgStream(error_msg) << "The expected type is not a float type"; return EncodeNumberStatus::kInvalidUsage; @@ -181,6 +191,11 @@ EncodeNumberStatus ParseAndEncodeNumber(const char* text, const NumberType& type, std::function emit, std::string* error_msg) { + if (!text) { + ErrorMsgStream(error_msg) << "The given text is a nullptr"; + return EncodeNumberStatus::kInvalidText; + } + if (IsUnknown(type)) { ErrorMsgStream(error_msg) << "The expected type is not a integer or float type"; diff --git a/source/util/parse_number.h b/source/util/parse_number.h index 6b9903a..5b7922b 100644 --- a/source/util/parse_number.h +++ b/source/util/parse_number.h @@ -169,8 +169,9 @@ bool ParseNumber(const char* text, T* value_pointer) { // with a single-byte type leads to implementation-defined behaviour. // Similarly for uint8_t. static_assert(sizeof(T) > 1, - "Don't use a single-byte type this parse method"); + "Single-byte types are not supported in this parse method"); + if (!text) return false; std::istringstream text_stream(text); // Allow both decimal and hex input for integers. // It also allows octal input, but we don't care about that case. diff --git a/test/ParseNumber.cpp b/test/ParseNumber.cpp index 42f3b2a..9c8850b 100644 --- a/test/ParseNumber.cpp +++ b/test/ParseNumber.cpp @@ -33,6 +33,7 @@ using testing::NotNull; TEST(ParseNarrowSignedIntegers, Sample) { int16_t i16; + EXPECT_FALSE(ParseNumber(nullptr, &i16)); EXPECT_FALSE(ParseNumber("", &i16)); EXPECT_FALSE(ParseNumber("0=", &i16)); @@ -60,6 +61,7 @@ TEST(ParseNarrowSignedIntegers, Sample) { TEST(ParseNarrowUnsignedIntegers, Sample) { uint16_t u16; + EXPECT_FALSE(ParseNumber(nullptr, &u16)); EXPECT_FALSE(ParseNumber("", &u16)); EXPECT_FALSE(ParseNumber("0=", &u16)); @@ -80,6 +82,7 @@ TEST(ParseSignedIntegers, Sample) { int32_t i32; // Invalid parse. + EXPECT_FALSE(ParseNumber(nullptr, &i32)); EXPECT_FALSE(ParseNumber("", &i32)); EXPECT_FALSE(ParseNumber("0=", &i32)); @@ -112,6 +115,7 @@ TEST(ParseUnsignedIntegers, Sample) { uint32_t u32; // Invalid parse. + EXPECT_FALSE(ParseNumber(nullptr, &u32)); EXPECT_FALSE(ParseNumber("", &u32)); EXPECT_FALSE(ParseNumber("0=", &u32)); @@ -132,6 +136,7 @@ TEST(ParseUnsignedIntegers, Sample) { TEST(ParseWideSignedIntegers, Sample) { int64_t i64; + EXPECT_FALSE(ParseNumber(nullptr, &i64)); EXPECT_FALSE(ParseNumber("", &i64)); EXPECT_FALSE(ParseNumber("0=", &i64)); EXPECT_TRUE(ParseNumber("0", &i64)); @@ -146,6 +151,7 @@ TEST(ParseWideSignedIntegers, Sample) { TEST(ParseWideUnsignedIntegers, Sample) { uint64_t u64; + EXPECT_FALSE(ParseNumber(nullptr, &u64)); EXPECT_FALSE(ParseNumber("", &u64)); EXPECT_FALSE(ParseNumber("0=", &u64)); EXPECT_TRUE(ParseNumber("0", &u64)); @@ -160,6 +166,7 @@ TEST(ParseWideUnsignedIntegers, Sample) { TEST(ParseFloat, Sample) { float f; + EXPECT_FALSE(ParseNumber(nullptr, &f)); EXPECT_FALSE(ParseNumber("", &f)); EXPECT_FALSE(ParseNumber("0=", &f)); @@ -199,6 +206,7 @@ TEST(ParseFloat, Overflow) { TEST(ParseDouble, Sample) { double f; + EXPECT_FALSE(ParseNumber(nullptr, &f)); EXPECT_FALSE(ParseNumber("", &f)); EXPECT_FALSE(ParseNumber("0=", &f)); @@ -250,6 +258,7 @@ TEST(ParseFloat16, Overflow) { // on floating point. spvutils::HexFloat> f(0); + EXPECT_FALSE(ParseNumber(nullptr, &f)); EXPECT_TRUE(ParseNumber("-0.0", &f)); EXPECT_EQ(uint16_t{0x8000}, f.value().getAsFloat().get_value()); EXPECT_TRUE(ParseNumber("1.0", &f)); @@ -280,6 +289,9 @@ TEST(ParseAndEncodeNarrowSignedIntegers, Invalid) { std::string err_msg; NumberType type = {16, SPV_NUMBER_SIGNED_INT}; + rc = ParseAndEncodeIntegerNumber(nullptr, type, AssertEmitFunc, &err_msg); + EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); + EXPECT_EQ("The given text is a nullptr", err_msg); rc = ParseAndEncodeIntegerNumber("", type, AssertEmitFunc, &err_msg); EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); EXPECT_EQ("Invalid unsigned integer literal: ", err_msg); @@ -346,6 +358,9 @@ TEST(ParseAndEncodeNarrowUnsignedIntegers, Invalid) { std::string err_msg; NumberType type = {16, SPV_NUMBER_UNSIGNED_INT}; + rc = ParseAndEncodeIntegerNumber(nullptr, type, AssertEmitFunc, &err_msg); + EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); + EXPECT_EQ("The given text is a nullptr", err_msg); rc = ParseAndEncodeIntegerNumber("", type, AssertEmitFunc, &err_msg); EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); EXPECT_EQ("Invalid unsigned integer literal: ", err_msg); @@ -405,6 +420,9 @@ TEST(ParseAndEncodeSignedIntegers, Invalid) { std::string err_msg; NumberType type = {32, SPV_NUMBER_SIGNED_INT}; + rc = ParseAndEncodeIntegerNumber(nullptr, type, AssertEmitFunc, &err_msg); + EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); + EXPECT_EQ("The given text is a nullptr", err_msg); rc = ParseAndEncodeIntegerNumber("", type, AssertEmitFunc, &err_msg); EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); EXPECT_EQ("Invalid unsigned integer literal: ", err_msg); @@ -475,6 +493,9 @@ TEST(ParseAndEncodeUnsignedIntegers, Invalid) { std::string err_msg; NumberType type = {32, SPV_NUMBER_UNSIGNED_INT}; + rc = ParseAndEncodeIntegerNumber(nullptr, type, AssertEmitFunc, &err_msg); + EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); + EXPECT_EQ("The given text is a nullptr", err_msg); rc = ParseAndEncodeIntegerNumber("", type, AssertEmitFunc, &err_msg); EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); EXPECT_EQ("Invalid unsigned integer literal: ", err_msg); @@ -536,6 +557,9 @@ TEST(ParseAndEncodeWideSignedIntegers, Invalid) { std::string err_msg; NumberType type = {64, SPV_NUMBER_SIGNED_INT}; + rc = ParseAndEncodeIntegerNumber(nullptr, type, AssertEmitFunc, &err_msg); + EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); + EXPECT_EQ("The given text is a nullptr", err_msg); rc = ParseAndEncodeIntegerNumber("", type, AssertEmitFunc, &err_msg); EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); EXPECT_EQ("Invalid unsigned integer literal: ", err_msg); @@ -611,6 +635,9 @@ TEST(ParseAndEncodeWideUnsignedIntegers, Invalid) { NumberType type = {64, SPV_NUMBER_UNSIGNED_INT}; // Invalid + rc = ParseAndEncodeIntegerNumber(nullptr, type, AssertEmitFunc, &err_msg); + EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); + EXPECT_EQ("The given text is a nullptr", err_msg); rc = ParseAndEncodeIntegerNumber("", type, AssertEmitFunc, &err_msg); EXPECT_EQ(EncodeNumberStatus::kInvalidText, rc); EXPECT_EQ("Invalid unsigned integer literal: ", err_msg); -- 2.7.4