mirror of
https://github.com/open-source-parsers/jsoncpp.git
synced 2025-06-07 01:04:55 +02:00
commit
acbf4eb2ef
@ -310,6 +310,9 @@ public:
|
|||||||
- true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
|
- true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
|
||||||
- "allowNumericKeys": false or true
|
- "allowNumericKeys": false or true
|
||||||
- true if numeric object keys are allowed.
|
- true if numeric object keys are allowed.
|
||||||
|
- "stackLimit": integer
|
||||||
|
- This is a security issue (seg-faults caused by deeply nested JSON),
|
||||||
|
so the default is low.
|
||||||
|
|
||||||
You can examine 'settings_` yourself
|
You can examine 'settings_` yourself
|
||||||
to see the defaults. You can also write and read them just like any
|
to see the defaults. You can also write and read them just like any
|
||||||
|
@ -28,6 +28,9 @@
|
|||||||
#pragma warning(disable : 4996)
|
#pragma warning(disable : 4996)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int const stackLimit_g = 1000;
|
||||||
|
static int stackDepth_g = 0; // see readValue()
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L
|
||||||
@ -118,6 +121,7 @@ bool Reader::parse(const char* beginDoc,
|
|||||||
nodes_.pop();
|
nodes_.pop();
|
||||||
nodes_.push(&root);
|
nodes_.push(&root);
|
||||||
|
|
||||||
|
stackDepth_g = 0; // Yes, this is bad coding, but options are limited.
|
||||||
bool successful = readValue();
|
bool successful = readValue();
|
||||||
Token token;
|
Token token;
|
||||||
skipCommentTokens(token);
|
skipCommentTokens(token);
|
||||||
@ -140,6 +144,13 @@ bool Reader::parse(const char* beginDoc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Reader::readValue() {
|
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) throw std::runtime_error("Exceeded stackLimit in readValue().");
|
||||||
|
++stackDepth_g;
|
||||||
|
|
||||||
Token token;
|
Token token;
|
||||||
skipCommentTokens(token);
|
skipCommentTokens(token);
|
||||||
bool successful = true;
|
bool successful = true;
|
||||||
@ -211,6 +222,7 @@ bool Reader::readValue() {
|
|||||||
lastValue_ = ¤tValue();
|
lastValue_ = ¤tValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--stackDepth_g;
|
||||||
return successful;
|
return successful;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -902,7 +914,8 @@ public:
|
|||||||
bool strictRoot_;
|
bool strictRoot_;
|
||||||
bool allowDroppedNullPlaceholders_;
|
bool allowDroppedNullPlaceholders_;
|
||||||
bool allowNumericKeys_;
|
bool allowNumericKeys_;
|
||||||
}; // OldFeatures
|
int stackLimit_;
|
||||||
|
}; // OurFeatures
|
||||||
|
|
||||||
// exact copy of Implementation of class Features
|
// exact copy of Implementation of class Features
|
||||||
// ////////////////////////////////
|
// ////////////////////////////////
|
||||||
@ -1033,7 +1046,9 @@ private:
|
|||||||
Location lastValueEnd_;
|
Location lastValueEnd_;
|
||||||
Value* lastValue_;
|
Value* lastValue_;
|
||||||
std::string commentsBefore_;
|
std::string commentsBefore_;
|
||||||
OurFeatures features_;
|
int stackDepth_;
|
||||||
|
|
||||||
|
OurFeatures const features_;
|
||||||
bool collectComments_;
|
bool collectComments_;
|
||||||
}; // OurReader
|
}; // OurReader
|
||||||
|
|
||||||
@ -1064,6 +1079,7 @@ bool OurReader::parse(const char* beginDoc,
|
|||||||
nodes_.pop();
|
nodes_.pop();
|
||||||
nodes_.push(&root);
|
nodes_.push(&root);
|
||||||
|
|
||||||
|
stackDepth_ = 0;
|
||||||
bool successful = readValue();
|
bool successful = readValue();
|
||||||
Token token;
|
Token token;
|
||||||
skipCommentTokens(token);
|
skipCommentTokens(token);
|
||||||
@ -1086,6 +1102,8 @@ bool OurReader::parse(const char* beginDoc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool OurReader::readValue() {
|
bool OurReader::readValue() {
|
||||||
|
if (stackDepth_ >= features_.stackLimit_) throw std::runtime_error("Exceeded stackLimit in readValue().");
|
||||||
|
++stackDepth_;
|
||||||
Token token;
|
Token token;
|
||||||
skipCommentTokens(token);
|
skipCommentTokens(token);
|
||||||
bool successful = true;
|
bool successful = true;
|
||||||
@ -1157,6 +1175,7 @@ bool OurReader::readValue() {
|
|||||||
lastValue_ = ¤tValue();
|
lastValue_ = ¤tValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--stackDepth_;
|
||||||
return successful;
|
return successful;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1853,6 +1872,7 @@ CharReader* CharReaderBuilder::newCharReader() const
|
|||||||
features.strictRoot_ = settings_["strictRoot"].asBool();
|
features.strictRoot_ = settings_["strictRoot"].asBool();
|
||||||
features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
|
features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
|
||||||
features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
|
features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
|
||||||
|
features.stackLimit_ = settings_["stackLimit"].asInt();
|
||||||
return new OurCharReader(collectComments, features);
|
return new OurCharReader(collectComments, features);
|
||||||
}
|
}
|
||||||
static void getValidReaderKeys(std::set<std::string>* valid_keys)
|
static void getValidReaderKeys(std::set<std::string>* valid_keys)
|
||||||
@ -1863,6 +1883,7 @@ static void getValidReaderKeys(std::set<std::string>* valid_keys)
|
|||||||
valid_keys->insert("strictRoot");
|
valid_keys->insert("strictRoot");
|
||||||
valid_keys->insert("allowDroppedNullPlaceholders");
|
valid_keys->insert("allowDroppedNullPlaceholders");
|
||||||
valid_keys->insert("allowNumericKeys");
|
valid_keys->insert("allowNumericKeys");
|
||||||
|
valid_keys->insert("stackLimit");
|
||||||
}
|
}
|
||||||
bool CharReaderBuilder::validate(Json::Value* invalid) const
|
bool CharReaderBuilder::validate(Json::Value* invalid) const
|
||||||
{
|
{
|
||||||
@ -1901,6 +1922,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings)
|
|||||||
(*settings)["strictRoot"] = false;
|
(*settings)["strictRoot"] = false;
|
||||||
(*settings)["allowDroppedNullPlaceholders"] = false;
|
(*settings)["allowDroppedNullPlaceholders"] = false;
|
||||||
(*settings)["allowNumericKeys"] = false;
|
(*settings)["allowNumericKeys"] = false;
|
||||||
|
(*settings)["stackLimit"] = 1000;
|
||||||
//! [CharReaderBuilderDefaults]
|
//! [CharReaderBuilderDefaults]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1713,6 +1713,34 @@ JSONTEST_FIXTURE(CharReaderTest, parseWithDetailError) {
|
|||||||
delete reader;
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSONTEST_FIXTURE(CharReaderTest, parseWithStackLimit) {
|
||||||
|
Json::CharReaderBuilder b;
|
||||||
|
Json::Value root;
|
||||||
|
char const doc[] =
|
||||||
|
"{ \"property\" : \"value\" }";
|
||||||
|
{
|
||||||
|
b.settings_["stackLimit"] = 2;
|
||||||
|
Json::CharReader* reader(b.newCharReader());
|
||||||
|
std::string errs;
|
||||||
|
bool ok = reader->parse(
|
||||||
|
doc, doc + std::strlen(doc),
|
||||||
|
&root, &errs);
|
||||||
|
JSONTEST_ASSERT(ok);
|
||||||
|
JSONTEST_ASSERT(errs == "");
|
||||||
|
JSONTEST_ASSERT_EQUAL("value", root["property"]);
|
||||||
|
delete reader;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
b.settings_["stackLimit"] = 1;
|
||||||
|
Json::CharReader* reader(b.newCharReader());
|
||||||
|
std::string errs;
|
||||||
|
JSONTEST_ASSERT_THROWS(reader->parse(
|
||||||
|
doc, doc + std::strlen(doc),
|
||||||
|
&root, &errs));
|
||||||
|
delete reader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
JsonTest::Runner runner;
|
JsonTest::Runner runner;
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, checkNormalizeFloatingPointStr);
|
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, checkNormalizeFloatingPointStr);
|
||||||
@ -1749,6 +1777,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithOneError);
|
JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithOneError);
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseChineseWithOneError);
|
JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseChineseWithOneError);
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithDetailError);
|
JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithDetailError);
|
||||||
|
JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithStackLimit);
|
||||||
|
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, WriterTest, dropNullPlaceholders);
|
JSONTEST_REGISTER_FIXTURE(runner, WriterTest, dropNullPlaceholders);
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, dropNullPlaceholders);
|
JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, dropNullPlaceholders);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user