summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2012-07-11 23:20:20 +0900
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2012-07-11 23:20:20 +0900
commitcd67e27ca4f610758835b951ac725fb188cb79b5 (patch)
tree826bdf990318d6dd7034b2cdf362b2a8a977b127
parent57b46d5123084a42a2936e9014a43115d0dc070f (diff)
Check structure depth when parsing JSON
-rw-r--r--src/JsonParser.cc22
-rw-r--r--src/JsonParser.h5
-rw-r--r--test/ValueBaseJsonParserTest.cc3
3 files changed, 23 insertions, 7 deletions
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