Skip to content

Commit 2ecd2a5

Browse files
authored
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.
1 parent 77632b2 commit 2ecd2a5

File tree

1 file changed

+12
-19
lines changed

1 file changed

+12
-19
lines changed

src/lib_json/json_reader.cpp

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// Copyright 2007-2011 Baptiste Lepilleur
2+
// Copyright (C) 2016 InfoTeCS JSC. All rights reserved.
23
// Distributed under MIT license, or public domain if desired and
34
// recognized in your jurisdiction.
45
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -44,13 +45,13 @@
4445
#pragma warning(disable : 4996)
4546
#endif
4647

47-
static int const stackLimit_g = 1000;
48-
#if __cplusplus >= 201103L
49-
thread_local static int stackDepth_g = 0; // see readValue()
50-
#else
51-
static int stackDepth_g = 0; // see readValue()
48+
// Define JSONCPP_STACK_LIMIT as an appropriate integer at compile time to change the stack limit
49+
#if !defined(JSONCPP_STACK_LIMIT)
50+
#define JSONCPP_STACK_LIMIT 1000
5251
#endif
5352

53+
static size_t const stackLimit_g = JSONCPP_STACK_LIMIT; // see readValue()
54+
5455
namespace Json {
5556

5657
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
@@ -142,7 +143,6 @@ bool Reader::parse(const char* beginDoc,
142143
nodes_.pop();
143144
nodes_.push(&root);
144145

145-
stackDepth_g = 0; // Yes, this is bad coding, but options are limited.
146146
bool successful = readValue();
147147
Token token;
148148
skipCommentTokens(token);
@@ -165,12 +165,10 @@ bool Reader::parse(const char* beginDoc,
165165
}
166166

167167
bool Reader::readValue() {
168-
// This is a non-reentrant way to support a stackLimit. Terrible!
169-
// But this deprecated class has a security problem: Bad input can
170-
// cause a seg-fault. This seems like a fair, binary-compatible way
171-
// to prevent the problem.
172-
if (stackDepth_g >= stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
173-
++stackDepth_g;
168+
// readValue() may call itself only if it calls readObject() or ReadArray().
169+
// These methods execute nodes_.push() just before and nodes_.pop)() just after calling readValue().
170+
// parse() executes one nodes_.push(), so > instead of >=.
171+
if (nodes_.size() > stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
174172

175173
Token token;
176174
skipCommentTokens(token);
@@ -244,7 +242,6 @@ bool Reader::readValue() {
244242
lastValue_ = &currentValue();
245243
}
246244

247-
--stackDepth_g;
248245
return successful;
249246
}
250247

@@ -1032,7 +1029,6 @@ class OurReader {
10321029
Location lastValueEnd_;
10331030
Value* lastValue_;
10341031
JSONCPP_STRING commentsBefore_;
1035-
int stackDepth_;
10361032

10371033
OurFeatures const features_;
10381034
bool collectComments_;
@@ -1043,7 +1039,6 @@ class OurReader {
10431039
OurReader::OurReader(OurFeatures const& features)
10441040
: errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
10451041
lastValue_(), commentsBefore_(),
1046-
stackDepth_(0),
10471042
features_(features), collectComments_() {
10481043
}
10491044

@@ -1067,7 +1062,6 @@ bool OurReader::parse(const char* beginDoc,
10671062
nodes_.pop();
10681063
nodes_.push(&root);
10691064

1070-
stackDepth_ = 0;
10711065
bool successful = readValue();
10721066
Token token;
10731067
skipCommentTokens(token);
@@ -1096,8 +1090,8 @@ bool OurReader::parse(const char* beginDoc,
10961090
}
10971091

10981092
bool OurReader::readValue() {
1099-
if (stackDepth_ >= features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
1100-
++stackDepth_;
1093+
// To preserve the old behaviour we cast size_t to int.
1094+
if (static_cast<int>(nodes_.size()) > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
11011095
Token token;
11021096
skipCommentTokens(token);
11031097
bool successful = true;
@@ -1194,7 +1188,6 @@ bool OurReader::readValue() {
11941188
lastValue_ = &currentValue();
11951189
}
11961190

1197-
--stackDepth_;
11981191
return successful;
11991192
}
12001193

0 commit comments

Comments
 (0)