Allow JSON empty exponent as trailing junk

Revert #251, and instead allow an invalid trailing empty exponent to be
treated as junk data in JSON parsing. Expand the test suite to test this
case, including testing the trailing junk.
This commit is contained in:
Leszek Swirski 2024-07-23 14:56:42 +02:00
parent 129f0e807e
commit e6777f2eef
2 changed files with 38 additions and 15 deletions

View File

@ -349,7 +349,7 @@ parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, par
++p; ++p;
} }
if ((p == pend) || !is_integer(*p)) { if ((p == pend) || !is_integer(*p)) {
if(!(fmt & chars_format::fixed) || (fmt & FASTFLOAT_JSONFMT)) { if(!(fmt & chars_format::fixed)) {
// We are in error. // We are in error.
return answer; return answer;
} }

View File

@ -36,32 +36,55 @@ int main_readme3() {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
int main() struct ExpectedResult {
{ double value;
const std::vector<double> expected{ -0.2, 0.02, 0.002, 1., 0., std::numeric_limits<double>::infinity() }; std::string junk_chars;
const std::vector<std::string> accept{ "-0.2", "0.02", "0.002", "1e+0000", "0e-2", "inf" }; };
struct AcceptedValue {
std::string input;
ExpectedResult expected;
};
int main() {
const std::vector<AcceptedValue> accept{
{"-0.2", {-0.2, ""}},
{"0.02", {0.02, ""}},
{"0.002", {0.002, ""}},
{"1e+0000", {1., ""}},
{"0e-2", {0., ""}},
{"1e", {1., "e"}},
{"1e+", {1., "e+"}},
{"inf", {std::numeric_limits<double>::infinity(), ""}}};
const std::vector<std::string> reject{"-.2", "00.02", "0.e+1", "00.e+1", const std::vector<std::string> reject{"-.2", "00.02", "0.e+1", "00.e+1",
"1e", "1e+", ".25", "+0.25", ".25", "+0.25", "inf", "nan(snan)"};
"inf", "nan(snan)"};
for (std::size_t i = 0; i < accept.size(); ++i) for (std::size_t i = 0; i < accept.size(); ++i)
{ {
const auto& f = accept[i]; const auto& s = accept[i].input;
const auto& expected = accept[i].expected;
double result; double result;
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, fast_float::chars_format::json_or_infnan); auto answer = fast_float::from_chars(s.data(), s.data() + s.size(), result, fast_float::chars_format::json_or_infnan);
if (answer.ec != std::errc() || result != expected[i]) { if (answer.ec != std::errc()) {
std::cerr << "json fmt rejected valid json " << f << std::endl; std::cerr << "json fmt rejected valid json " << s << std::endl;
return EXIT_FAILURE;
}
if (result != expected.value) {
std::cerr << "json fmt gave wrong result " << s << " (expected " << expected.value << " got " << result << ")" << std::endl;
return EXIT_FAILURE;
}
if (std::string(answer.ptr) != expected.junk_chars) {
std::cerr << "json fmt has wrong trailing characters " << s << " (expected " << expected.junk_chars << " got " << answer.ptr << ")" << std::endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
for (std::size_t i = 0; i < reject.size(); ++i) for (std::size_t i = 0; i < reject.size(); ++i)
{ {
const auto& f = reject[i]; const auto& s = reject[i];
double result; double result;
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, fast_float::chars_format::json); auto answer = fast_float::from_chars(s.data(), s.data() + s.size(), result, fast_float::chars_format::json);
if (answer.ec == std::errc()) { if (answer.ec == std::errc()) {
std::cerr << "json fmt accepted invalid json " << f << std::endl; std::cerr << "json fmt accepted invalid json " << s << std::endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }