From 4e49829851e536bd82220872e5ea733221eaf10d Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 11 Mar 2017 19:26:12 +0100 Subject: [PATCH] :ambulance: fix for #493 Added a test to check if the input stream is good() before executing getline on it. Also added two test cases that set the failbit and badbit before calling file_line_buffer. --- src/json.hpp | 7 +++++++ src/json.hpp.re2c | 7 +++++++ test/src/unit-regression.cpp | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/src/json.hpp b/src/json.hpp index 33456a51..1ed8cca2 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -10988,6 +10988,13 @@ basic_json_parser_74: m_line_buffer.erase(0, num_processed_chars); // read next line from input stream m_line_buffer_tmp.clear(); + + // check if stream is still good + if (not m_stream->good()) + { + JSON_THROW(std::invalid_argument("stream error")); + } + std::getline(*m_stream, m_line_buffer_tmp, '\n'); // add line with newline symbol to the line buffer diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 180f5d3b..c58b29a8 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -10022,6 +10022,13 @@ class basic_json m_line_buffer.erase(0, num_processed_chars); // read next line from input stream m_line_buffer_tmp.clear(); + + // check if stream is still good + if (not m_stream->good()) + { + JSON_THROW(std::invalid_argument("stream error")); + } + std::getline(*m_stream, m_line_buffer_tmp, '\n'); // add line with newline symbol to the line buffer diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index bfd2c954..368c1470 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -28,6 +28,7 @@ SOFTWARE. #include "catch.hpp" +#define private public #include "json.hpp" using nlohmann::json; @@ -804,4 +805,35 @@ TEST_CASE("regression tests") CHECK(j["bool_vector"].dump() == "[false,true,false,false]"); } + + SECTION("issue #495 - fill_line_buffer incorrectly tests m_stream for eof but not fail or bad bits") + { + SECTION("setting failbit") + { + std::stringstream ss; + ss << "[1,2,3\n,4,5]"; + + json::lexer l(ss); + + CHECK(l.m_line_buffer == "[1,2,3\n"); + + l.m_stream->setstate(std::ios_base::failbit); + + CHECK_THROWS_AS(l.fill_line_buffer(), std::invalid_argument); + } + + SECTION("setting badbit") + { + std::stringstream ss; + ss << "[1,2,3\n,4,5]"; + + json::lexer l(ss); + + CHECK(l.m_line_buffer == "[1,2,3\n"); + + l.m_stream->setstate(std::ios_base::badbit); + + CHECK_THROWS_AS(l.fill_line_buffer(), std::invalid_argument); + } + } }