Commit c662e628 authored by Kamal Marhubi's avatar Kamal Marhubi

Reject trailing commas in JSON arrays and objects

Per spec.
parent 88ac1058
...@@ -415,10 +415,12 @@ KJ_TEST("basic json decoding") { ...@@ -415,10 +415,12 @@ KJ_TEST("basic json decoding") {
KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[}]", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[}]", root));
KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[1, , ]", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[1, , ]", root));
KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[,]", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[,]", root));
KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[true,]", root));
KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[, 1]", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[, 1]", root));
KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[1\"\"]", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[1\"\"]", root));
KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[1,, \"\"]", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[1,, \"\"]", root));
KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("{\"a\"1: 0}", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("{\"a\"1: 0}", root));
KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw(R"({"some": null,})", root));
KJ_EXPECT_THROW_MESSAGE("Input remains", json.decodeRaw("11a", root)); KJ_EXPECT_THROW_MESSAGE("Input remains", json.decodeRaw("11a", root));
KJ_EXPECT_THROW_MESSAGE("Invalid escape", json.decodeRaw(R"("\z")", root)); KJ_EXPECT_THROW_MESSAGE("Invalid escape", json.decodeRaw(R"("\z")", root));
KJ_EXPECT_THROW_MESSAGE("Invalid escape", json.decodeRaw(R"("\z")", root)); KJ_EXPECT_THROW_MESSAGE("Invalid escape", json.decodeRaw(R"("\z")", root));
......
...@@ -432,6 +432,7 @@ public: ...@@ -432,6 +432,7 @@ public:
// Cap'n Proto message. This also applies to parseObject below. // Cap'n Proto message. This also applies to parseObject below.
kj::Vector<Orphan<JsonValue>> values; kj::Vector<Orphan<JsonValue>> values;
auto orphanage = Orphanage::getForMessageContaining(output); auto orphanage = Orphanage::getForMessageContaining(output);
bool expectComma = false;
consume('['); consume('[');
KJ_REQUIRE(++nestingDepth_ <= maxNestingDepth_, "JSON message nested too deeply."); KJ_REQUIRE(++nestingDepth_ <= maxNestingDepth_, "JSON message nested too deeply.");
...@@ -440,13 +441,17 @@ public: ...@@ -440,13 +441,17 @@ public:
while (consumeWhitespace(), nextChar() != ']') { while (consumeWhitespace(), nextChar() != ']') {
auto orphan = orphanage.newOrphan<JsonValue>(); auto orphan = orphanage.newOrphan<JsonValue>();
auto builder = orphan.get(); auto builder = orphan.get();
parseValue(builder);
values.add(kj::mv(orphan));
if (consumeWhitespace(), nextChar() != ']') { if (expectComma) {
// TODO(someday): The JSON spec forbids a trailing comma, but we allow it. consumeWhitespace();
consume(','); consume(',');
consumeWhitespace();
} }
parseValue(builder);
values.add(kj::mv(orphan));
expectComma = true;
} }
output.initArray(values.size()); output.initArray(values.size());
...@@ -462,6 +467,7 @@ public: ...@@ -462,6 +467,7 @@ public:
void parseObject(JsonValue::Builder& output) { void parseObject(JsonValue::Builder& output) {
kj::Vector<Orphan<JsonValue::Field>> fields; kj::Vector<Orphan<JsonValue::Field>> fields;
auto orphanage = Orphanage::getForMessageContaining(output); auto orphanage = Orphanage::getForMessageContaining(output);
bool expectComma = false;
consume('{'); consume('{');
KJ_REQUIRE(++nestingDepth_ <= maxNestingDepth_, "JSON message nested too deeply."); KJ_REQUIRE(++nestingDepth_ <= maxNestingDepth_, "JSON message nested too deeply.");
...@@ -471,6 +477,12 @@ public: ...@@ -471,6 +477,12 @@ public:
auto orphan = orphanage.newOrphan<JsonValue::Field>(); auto orphan = orphanage.newOrphan<JsonValue::Field>();
auto builder = orphan.get(); auto builder = orphan.get();
if (expectComma) {
consumeWhitespace();
consume(',');
consumeWhitespace();
}
builder.setName(consumeQuotedString()); builder.setName(consumeQuotedString());
consumeWhitespace(); consumeWhitespace();
...@@ -482,10 +494,7 @@ public: ...@@ -482,10 +494,7 @@ public:
fields.add(kj::mv(orphan)); fields.add(kj::mv(orphan));
if (consumeWhitespace(), nextChar() != '}') { expectComma = true;
// TODO(someday): The JSON spec forbids a trailing comma, but we allow it.
consume(',');
}
} }
output.initObject(fields.size()); output.initObject(fields.size());
......
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