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
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+
5455namespace 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
167167bool 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_ = ¤tValue ();
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 {
10431039OurReader::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
10981092bool 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_ = ¤tValue ();
11951189 }
11961190
1197- --stackDepth_;
11981191 return successful;
11991192}
12001193
0 commit comments