diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index d5ff46d..6de6a31 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -1,4 +1,5 @@ // Copyright 2007-2011 Baptiste Lepilleur +// Copyright (C) 2016 InfoTeCS JSC. All rights reserved. // Distributed under MIT license, or public domain if desired and // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE @@ -44,13 +45,13 @@ #pragma warning(disable : 4996) #endif -static int const stackLimit_g = 1000; -#if __cplusplus >= 201103L -thread_local static int stackDepth_g = 0; // see readValue() -#else -static int stackDepth_g = 0; // see readValue() +// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile time to change the stack limit +#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT) +#define JSONCPP_DEPRECATED_STACK_LIMIT 1000 #endif +static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue() + namespace Json { #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) @@ -142,7 +143,6 @@ bool Reader::parse(const char* beginDoc, nodes_.pop(); nodes_.push(&root); - stackDepth_g = 0; // Yes, this is bad coding, but options are limited. bool successful = readValue(); Token token; skipCommentTokens(token); @@ -165,12 +165,10 @@ bool Reader::parse(const char* beginDoc, } bool Reader::readValue() { - // This is a non-reentrant way to support a stackLimit. Terrible! - // But this deprecated class has a security problem: Bad input can - // cause a seg-fault. This seems like a fair, binary-compatible way - // to prevent the problem. - if (stackDepth_g >= stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue()."); - ++stackDepth_g; + // readValue() may call itself only if it calls readObject() or ReadArray(). + // These methods execute nodes_.push() just before and nodes_.pop)() just after calling readValue(). + // parse() executes one nodes_.push(), so > instead of >=. + if (nodes_.size() > stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue()."); Token token; skipCommentTokens(token); @@ -244,7 +242,6 @@ bool Reader::readValue() { lastValue_ = ¤tValue(); } - --stackDepth_g; return successful; } @@ -1032,7 +1029,6 @@ private: Location lastValueEnd_; Value* lastValue_; JSONCPP_STRING commentsBefore_; - int stackDepth_; OurFeatures const features_; bool collectComments_; @@ -1043,7 +1039,6 @@ private: OurReader::OurReader(OurFeatures const& features) : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), lastValue_(), commentsBefore_(), - stackDepth_(0), features_(features), collectComments_() { } @@ -1067,7 +1062,6 @@ bool OurReader::parse(const char* beginDoc, nodes_.pop(); nodes_.push(&root); - stackDepth_ = 0; bool successful = readValue(); Token token; skipCommentTokens(token); @@ -1096,8 +1090,8 @@ bool OurReader::parse(const char* beginDoc, } bool OurReader::readValue() { - if (stackDepth_ >= features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue()."); - ++stackDepth_; + // To preserve the old behaviour we cast size_t to int. + if (static_cast(nodes_.size()) > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue()."); Token token; skipCommentTokens(token); bool successful = true; @@ -1194,7 +1188,6 @@ bool OurReader::readValue() { lastValue_ = ¤tValue(); } - --stackDepth_; return successful; }