diff --git a/tests/test_parse_floating.cpp b/tests/test_parse_floating.cpp index 8ddcb90..15f433d 100644 --- a/tests/test_parse_floating.cpp +++ b/tests/test_parse_floating.cpp @@ -176,3 +176,10 @@ BOOST_AUTO_TEST_CASE(test_nan) BOOST_CHECK(std::isnan(r.unwrap().first)); } } + +BOOST_AUTO_TEST_CASE(test_overflow) +{ + std::istringstream float_overflow (std::string("float-overflow = 1.0e+1024")); + BOOST_CHECK_THROW(toml::parse(float_overflow ), toml::syntax_error); + // istringstream >> float does not set failbit in case of underflow. +} diff --git a/tests/test_parse_integer.cpp b/tests/test_parse_integer.cpp index f6547bb..8e73686 100644 --- a/tests/test_parse_integer.cpp +++ b/tests/test_parse_integer.cpp @@ -90,3 +90,15 @@ BOOST_AUTO_TEST_CASE(test_bin_value) TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b01_00_00", value(16)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b111111", value(63)); } + +BOOST_AUTO_TEST_CASE(test_integer_overflow) +{ + std::istringstream dec_overflow(std::string("dec-overflow = 9223372036854775808")); + std::istringstream hex_overflow(std::string("hex-overflow = 0x1_00000000_00000000")); + std::istringstream oct_overflow(std::string("oct-overflow = 0o1_000_000_000_000_000_000_000")); + std::istringstream bin_overflow(std::string("bin-overflow = 0b1_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000")); + BOOST_CHECK_THROW(toml::parse(dec_overflow), toml::syntax_error); + BOOST_CHECK_THROW(toml::parse(hex_overflow), toml::syntax_error); + BOOST_CHECK_THROW(toml::parse(oct_overflow), toml::syntax_error); + BOOST_CHECK_THROW(toml::parse(bin_overflow), toml::syntax_error); +} diff --git a/toml/parser.hpp b/toml/parser.hpp index 6784181..80f6250 100644 --- a/toml/parser.hpp +++ b/toml/parser.hpp @@ -57,6 +57,12 @@ parse_binary_integer(location& loc) { auto str = token.unwrap().str(); assert(str.size() > 2); // minimum -> 0b1 + if(64 <= str.size()) + { + // since toml11 uses int64_t, 64bit (unsigned) input cannot be read. + return err(format_underline("toml::parse_binary_integer:", + {{source_location(loc), "too large input (> int64_t)"}})); + } integer retval(0), base(1); for(auto i(str.rbegin()), e(str.rend() - 2); i!=e; ++i) { @@ -91,6 +97,20 @@ parse_octal_integer(location& loc) std::istringstream iss(str); integer retval(0); iss >> std::oct >> retval; + if(iss.fail()) + { + // `istream` sets `failbit` if internally-called `std::num_get::get` + // fails. + // `std::num_get::get` calls `std::strtoll` if the argument type is + // signed. + // `std::strtoll` fails if + // - the value is out_of_range or + // - no conversion is possible. + // since we already checked that the string is valid octal integer, + // so the error reason is out_of_range. + return err(format_underline("toml::parse_octal_integer:", + {{source_location(loc), "out of range"}})); + } return ok(std::make_pair(retval, token.unwrap())); } loc.reset(first); @@ -111,6 +131,12 @@ parse_hexadecimal_integer(location& loc) std::istringstream iss(str); integer retval(0); iss >> std::hex >> retval; + if(iss.fail()) + { + // see parse_octal_integer for detail of this error message. + return err(format_underline("toml::parse_hexadecimal_integer:", + {{source_location(loc), "out of range"}})); + } return ok(std::make_pair(retval, token.unwrap())); } loc.reset(first); @@ -157,6 +183,12 @@ parse_integer(location& loc) std::istringstream iss(str); integer retval(0); iss >> retval; + if(iss.fail()) + { + // see parse_octal_integer for detail of this error message. + return err(format_underline("toml::parse_integer:", + {{source_location(loc), "out of range"}})); + } return ok(std::make_pair(retval, token.unwrap())); } loc.reset(first); @@ -245,6 +277,12 @@ parse_floating(location& loc) std::istringstream iss(str); floating v(0.0); iss >> v; + if(iss.fail()) + { + // see parse_octal_integer for detail of this error message. + return err(format_underline("toml::parse_floating:", + {{source_location(loc), "out of range"}})); + } return ok(std::make_pair(v, token.unwrap())); } loc.reset(first);