Commit 32179932 authored by Chris Davis (EDGE)'s avatar Chris Davis (EDGE) Committed by Commit Bot

JSONWriter should support adding non containers at max depth

The JSON fuzzing tests failed to write JSON via JSONWriter::Write that
was successfully read with JSONReader.  This was due to an edge case
where we are writing the JSON and have reached max depth (200) but have
non-container leaf entries at that level and nothing deeper.  This case
should be supported by the JSONWriter to match the JSONReader and
JSONParser. Also added a unit test for this case.

Bug: 1138450, 1013934
Change-Id: I98fcd63c957ab4e85a322d923bef18b981220383
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2477239Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Commit-Queue: Chris Davis <chrdavis@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#818212}
parent f529523f
...@@ -61,8 +61,6 @@ JSONWriter::JSONWriter(int options, std::string* json, size_t max_depth) ...@@ -61,8 +61,6 @@ JSONWriter::JSONWriter(int options, std::string* json, size_t max_depth)
bool JSONWriter::BuildJSONString(const Value& node, size_t depth) { bool JSONWriter::BuildJSONString(const Value& node, size_t depth) {
internal::StackMarker depth_check(max_depth_, &stack_depth_); internal::StackMarker depth_check(max_depth_, &stack_depth_);
if (depth_check.IsTooDeep())
return false;
switch (node.type()) { switch (node.type()) {
case Value::Type::NONE: case Value::Type::NONE:
...@@ -113,6 +111,9 @@ bool JSONWriter::BuildJSONString(const Value& node, size_t depth) { ...@@ -113,6 +111,9 @@ bool JSONWriter::BuildJSONString(const Value& node, size_t depth) {
return true; return true;
case Value::Type::LIST: { case Value::Type::LIST: {
if (depth_check.IsTooDeep())
return false;
json_string_->push_back('['); json_string_->push_back('[');
if (pretty_print_) if (pretty_print_)
json_string_->push_back(' '); json_string_->push_back(' ');
...@@ -142,6 +143,9 @@ bool JSONWriter::BuildJSONString(const Value& node, size_t depth) { ...@@ -142,6 +143,9 @@ bool JSONWriter::BuildJSONString(const Value& node, size_t depth) {
} }
case Value::Type::DICTIONARY: { case Value::Type::DICTIONARY: {
if (depth_check.IsTooDeep())
return false;
json_string_->push_back('{'); json_string_->push_back('{');
if (pretty_print_) if (pretty_print_)
json_string_->append(kPrettyPrintLineEnding); json_string_->append(kPrettyPrintLineEnding);
......
...@@ -3,9 +3,11 @@ ...@@ -3,9 +3,11 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "base/json/json_writer.h" #include "base/json/json_writer.h"
#include "base/json/json_reader.h"
#include "base/containers/span.h" #include "base/containers/span.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h"
#include "base/values.h" #include "base/values.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -186,4 +188,26 @@ TEST(JSONWriterTest, StackOverflow) { ...@@ -186,4 +188,26 @@ TEST(JSONWriterTest, StackOverflow) {
} }
} }
TEST(JSONWriterTest, TestMaxDepthWithValidNodes) {
// Create JSON to the max depth - 1. Nodes at that depth are still valid
// for writing which matches the JSONParser logic.
std::string nested_json;
for (int i = 0; i < 199; ++i) {
std::string node = "[";
for (int j = 0; j < 5; j++) {
node.append(StringPrintf("%d,", j));
}
nested_json.insert(0, node);
nested_json.append("]");
}
// Ensure we can read and write the JSON
JSONReader::ValueWithError json_val = JSONReader::ReadAndReturnValueWithError(
nested_json, JSON_ALLOW_TRAILING_COMMAS);
EXPECT_TRUE(json_val.value);
const Value& value = json_val.value.value();
std::string serialized;
EXPECT_TRUE(JSONWriter::Write(value, &serialized));
}
} // namespace base } // namespace base
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment