diff --git a/src/JsonParser.cc b/src/JsonParser.cc index 59d98aec..5f83ec7a 100644 --- a/src/JsonParser.cc +++ b/src/JsonParser.cc @@ -117,7 +117,10 @@ ssize_t JsonParser::parseUpdate(const char* data, size_t size) } else if(isSpace(c)) { break; } else { - pushState(currentState_); + int rv = pushState(currentState_); + if(rv < 0) { + return rv; + } currentState_ = JSON_VALUE; runBeginCallback(STRUCT_ARRAY_DATA_T); } @@ -208,11 +211,15 @@ ssize_t JsonParser::parseUpdate(const char* data, size_t size) break; case JSON_OBJECT_KEY: switch(c) { - case '"': - pushState(currentState_); + case '"': { + int rv = pushState(currentState_); + if(rv < 0) { + return rv; + } currentState_ = JSON_STRING; runBeginCallback(STRUCT_DICT_KEY_T); break; + } case '}': onObjectEnd(); break; @@ -584,9 +591,14 @@ void JsonParser::onValueEnd() } } -void JsonParser::pushState(int state) +int JsonParser::pushState(int state) { - stateStack_.push(state); + if(stateStack_.size() >= 50) { + return ERR_STRUCTURE_TOO_DEEP; + } else { + stateStack_.push(state); + return 0; + } } int JsonParser::stateTop() const diff --git a/src/JsonParser.h b/src/JsonParser.h index f08546ee..821d6416 100644 --- a/src/JsonParser.h +++ b/src/JsonParser.h @@ -55,7 +55,8 @@ enum JsonError { ERR_NUMBER_OUT_OF_RANGE = -7, ERR_UNEXPECTED_CHAR_BEFORE_ARRAY_SEP = -8, ERR_UNEXPECTED_LITERAL = -9, - ERR_PREMATURE_DATA = -10 + ERR_PREMATURE_DATA = -10, + ERR_STRUCTURE_TOO_DEEP = -11 }; class JsonParser { @@ -76,7 +77,7 @@ public: // reuse. void reset(); private: - void pushState(int state); + int pushState(int state); int stateTop() const; int popState(); void runBeginCallback(int elementType); diff --git a/test/ValueBaseJsonParserTest.cc b/test/ValueBaseJsonParserTest.cc index 6fddb6fd..97443d2b 100644 --- a/test/ValueBaseJsonParserTest.cc +++ b/test/ValueBaseJsonParserTest.cc @@ -288,6 +288,9 @@ void ValueBaseJsonParserTest::testParseUpdate_error() checkDecodeError("[1.1e]"); // bool checkDecodeError("[t"); + // too deep structure + checkDecodeError(std::string(51, '[')+std::string(51,']')); + checkDecodeError(std::string(50, '[')+"{\"foo\":100}"+std::string(50,']')); } } // namespace aria2