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.
This commit is contained in:
nnkur 2016-11-30 18:30:12 +03:00 committed by GitHub
parent 77632b2611
commit 2ecd2a59de

View File

@ -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_ = &currentValue();
}
--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<int>(nodes_.size()) > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
Token token;
skipCommentTokens(token);
bool successful = true;
@ -1194,7 +1188,6 @@ bool OurReader::readValue() {
lastValue_ = &currentValue();
}
--stackDepth_;
return successful;
}