From 2ecd2a59de8faef1a6bd2ed7e53cf78b72d6c680 Mon Sep 17 00:00:00 2001 From: nnkur Date: Wed, 30 Nov 2016 18:30:12 +0300 Subject: [PATCH 1/2] Add files via upload Removed a static variable used to contain the current recursion depth of Reader::readValue(). The number of elements in an internal container Reader::nodes_ is used instead. It is correct because any recursive call of Reader::readValue() is executed with adjacent nodes_.push() and nodes_.pop() calls. Added the option to change the allowed recursion depth at compile time by defining a macro JSONCPP_STACK_LIMIT as the required integer value. --- src/lib_json/json_reader.cpp | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index d5ff46d..ae248e7 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_STACK_LIMIT as an appropriate integer at compile time to change the stack limit +#if !defined(JSONCPP_STACK_LIMIT) +#define JSONCPP_STACK_LIMIT 1000 #endif +static size_t const stackLimit_g = JSONCPP_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; } From 5021e799dc8b8a5c47d4d62d1760096ac2329143 Mon Sep 17 00:00:00 2001 From: nnkur Date: Wed, 7 Dec 2016 15:47:08 +0300 Subject: [PATCH 2/2] Renamed JSONCPP_STACK_LIMIT to JSONCPP_DEPRECATED_STACK_LIMIT Renamed JSONCPP_STACK_LIMIT to JSONCPP_DEPRECATED_STACK_LIMIT to stress that usage of this macros assumes old interface. --- src/lib_json/json_reader.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index ae248e7..6de6a31 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -45,12 +45,12 @@ #pragma warning(disable : 4996) #endif -// Define JSONCPP_STACK_LIMIT as an appropriate integer at compile time to change the stack limit -#if !defined(JSONCPP_STACK_LIMIT) -#define JSONCPP_STACK_LIMIT 1000 +// 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_STACK_LIMIT; // see readValue() +static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue() namespace Json {