Skip to content

Commit 0d25d9a

Browse files
authored
Merge pull request open-source-parsers#556 from Infotecs/nnkur-rec-fix
Removed a static variable used to contain the current recursion depth in json_reader.cpp
2 parents 762ad0f + 5021e79 commit 0d25d9a

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_DEPRECATED_STACK_LIMIT as an appropriate integer at compile time to change the stack limit
49+
#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT)
50+
#define JSONCPP_DEPRECATED_STACK_LIMIT 1000
5251
#endif
5352

53+
static size_t const stackLimit_g = JSONCPP_DEPRECATED_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)