diff --git a/include/jsoncons/staj_event.hpp b/include/jsoncons/staj_event.hpp index 885cd85df..f483c41b8 100644 --- a/include/jsoncons/staj_event.hpp +++ b/include/jsoncons/staj_event.hpp @@ -493,7 +493,16 @@ class basic_staj_event case staj_events::string_value: { double val{0}; - jsoncons::decstr_to_double(value_.string_data_, length_, val); + if (length_ == 0) + { + ec = conv_errc::not_double; + return val; + } + auto result = jsoncons::decstr_to_double(value_.string_data_, length_, val); + if (!result) + { + ec = conv_errc::not_double; + } return val; } case staj_events::double_value: diff --git a/test/csv/src/encode_decode_csv_tests.cpp b/test/csv/src/encode_decode_csv_tests.cpp index 17fcdc601..6b0838313 100644 --- a/test/csv/src/encode_decode_csv_tests.cpp +++ b/test/csv/src/encode_decode_csv_tests.cpp @@ -152,6 +152,35 @@ TEST_CASE("encode decode csv source") } } +TEST_CASE("decode_csv non-numeric string into double reports error") +{ + // Regression test for staj_event::as_double silently returning 0.0 + // when a string_value event is decoded into a floating-point type. + // Introduced in caacd258a ("Remove chars_to, replace with to_double"): + // the new to_double API's return code was not propagated to ec, so + // non-numeric and empty cells were coerced to 0.0 without error. + using cpp_type = std::vector>; + auto options = csv::csv_options{} + .mapping_kind(csv::csv_mapping_kind::n_rows) + .assume_header(false); + + SECTION("non-numeric token") + { + std::string s = "hey\n"; + auto result = csv::try_decode_csv(s, options); + REQUIRE(!result); //-V521 + REQUIRE_THROWS(csv::decode_csv(s, options)); + } + + SECTION("empty trailing field") + { + std::string s = "0,\n"; + auto result = csv::try_decode_csv(s, options); + REQUIRE(!result); //-V521 + REQUIRE_THROWS(csv::decode_csv(s, options)); + } +} + namespace {