1
1
// Copyright 2007-2011 Baptiste Lepilleur
2
+ // Copyright (C) 2016 InfoTeCS JSC. All rights reserved.
2
3
// Distributed under MIT license, or public domain if desired and
3
4
// recognized in your jurisdiction.
4
5
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
44
45
#pragma warning(disable : 4996)
45
46
#endif
46
47
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
52
51
#endif
53
52
53
+ static size_t const stackLimit_g = JSONCPP_STACK_LIMIT; // see readValue()
54
+
54
55
namespace Json {
55
56
56
57
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
@@ -142,7 +143,6 @@ bool Reader::parse(const char* beginDoc,
142
143
nodes_.pop ();
143
144
nodes_.push (&root);
144
145
145
- stackDepth_g = 0 ; // Yes, this is bad coding, but options are limited.
146
146
bool successful = readValue ();
147
147
Token token;
148
148
skipCommentTokens (token);
@@ -165,12 +165,10 @@ bool Reader::parse(const char* beginDoc,
165
165
}
166
166
167
167
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()." );
174
172
175
173
Token token;
176
174
skipCommentTokens (token);
@@ -244,7 +242,6 @@ bool Reader::readValue() {
244
242
lastValue_ = ¤tValue ();
245
243
}
246
244
247
- --stackDepth_g;
248
245
return successful;
249
246
}
250
247
@@ -1032,7 +1029,6 @@ class OurReader {
1032
1029
Location lastValueEnd_;
1033
1030
Value* lastValue_;
1034
1031
JSONCPP_STRING commentsBefore_;
1035
- int stackDepth_;
1036
1032
1037
1033
OurFeatures const features_;
1038
1034
bool collectComments_;
@@ -1043,7 +1039,6 @@ class OurReader {
1043
1039
OurReader::OurReader (OurFeatures const & features)
1044
1040
: errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
1045
1041
lastValue_(), commentsBefore_(),
1046
- stackDepth_(0 ),
1047
1042
features_(features), collectComments_() {
1048
1043
}
1049
1044
@@ -1067,7 +1062,6 @@ bool OurReader::parse(const char* beginDoc,
1067
1062
nodes_.pop ();
1068
1063
nodes_.push (&root);
1069
1064
1070
- stackDepth_ = 0 ;
1071
1065
bool successful = readValue ();
1072
1066
Token token;
1073
1067
skipCommentTokens (token);
@@ -1096,8 +1090,8 @@ bool OurReader::parse(const char* beginDoc,
1096
1090
}
1097
1091
1098
1092
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(). " ) ;
1101
1095
Token token;
1102
1096
skipCommentTokens (token);
1103
1097
bool successful = true ;
@@ -1194,7 +1188,6 @@ bool OurReader::readValue() {
1194
1188
lastValue_ = ¤tValue ();
1195
1189
}
1196
1190
1197
- --stackDepth_;
1198
1191
return successful;
1199
1192
}
1200
1193
0 commit comments