Compare commits
1
Commits
main
...
f0a338f164
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0a338f164 |
@@ -140,6 +140,7 @@ struct Parser3 {
|
|||||||
std::ignore = push({N_VALUE, N_WHITESPACE, T_EOF});
|
std::ignore = push({N_VALUE, N_WHITESPACE, T_EOF});
|
||||||
inKey = false;
|
inKey = false;
|
||||||
rejected = false;
|
rejected = false;
|
||||||
|
overflowed = false;
|
||||||
utf8Codepoint = 0;
|
utf8Codepoint = 0;
|
||||||
utf16Surrogate = 0;
|
utf16Surrogate = 0;
|
||||||
minCodepoint = 0;
|
minCodepoint = 0;
|
||||||
@@ -163,6 +164,7 @@ struct Parser3 {
|
|||||||
Utf8Dfa strDfa;
|
Utf8Dfa strDfa;
|
||||||
bool inKey = false;
|
bool inKey = false;
|
||||||
bool rejected = false;
|
bool rejected = false;
|
||||||
|
bool overflowed = false;
|
||||||
|
|
||||||
#ifndef HAS_MUSTTAIL
|
#ifndef HAS_MUSTTAIL
|
||||||
char *stashBufForTrampoline;
|
char *stashBufForTrampoline;
|
||||||
@@ -1074,6 +1076,10 @@ inline WeaselJsonStatus Parser3::parse(char *buf, int len) {
|
|||||||
return WeaselJson_REJECT;
|
return WeaselJson_REJECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->overflowed) [[unlikely]] {
|
||||||
|
return WeaselJson_OVERFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
if (len < 0) [[unlikely]] {
|
if (len < 0) [[unlikely]] {
|
||||||
this->rejected = true;
|
this->rejected = true;
|
||||||
return WeaselJson_REJECT;
|
return WeaselJson_REJECT;
|
||||||
@@ -1087,6 +1093,8 @@ inline WeaselJsonStatus Parser3::parse(char *buf, int len) {
|
|||||||
symbolTables.continuations[top()](this, buf, buf + len);
|
symbolTables.continuations[top()](this, buf, buf + len);
|
||||||
if (status == WeaselJson_REJECT) {
|
if (status == WeaselJson_REJECT) {
|
||||||
this->rejected = true;
|
this->rejected = true;
|
||||||
|
} else if (status == WeaselJson_OVERFLOW) {
|
||||||
|
this->overflowed = true;
|
||||||
}
|
}
|
||||||
return WeaselJsonStatus(status);
|
return WeaselJsonStatus(status);
|
||||||
#else
|
#else
|
||||||
@@ -1097,6 +1105,8 @@ inline WeaselJsonStatus Parser3::parse(char *buf, int len) {
|
|||||||
;
|
;
|
||||||
if (result == WeaselJson_REJECT) {
|
if (result == WeaselJson_REJECT) {
|
||||||
this->rejected = true;
|
this->rejected = true;
|
||||||
|
} else if (result == WeaselJson_OVERFLOW) {
|
||||||
|
this->overflowed = true;
|
||||||
}
|
}
|
||||||
return WeaselJsonStatus(result);
|
return WeaselJsonStatus(result);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -202,6 +202,62 @@ TEST_CASE("parser3") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("overflow state is sticky") {
|
||||||
|
auto c = noopCallbacks();
|
||||||
|
// stackSize 3 is exactly big enough to hold reset()'s bootstrap, but too
|
||||||
|
// small for nested arrays. Overflows must be terminal like rejects: a later
|
||||||
|
// end-of-data call must never report OK for an incomplete document.
|
||||||
|
auto *parser = WeaselJsonParser_create(3, &c, nullptr, 0);
|
||||||
|
REQUIRE(parser != nullptr);
|
||||||
|
|
||||||
|
std::string doc = "[[";
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, doc.data(), doc.size()) ==
|
||||||
|
WeaselJson_OVERFLOW);
|
||||||
|
|
||||||
|
// After overflow, the end-of-data call must not return OK.
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, nullptr, 0) != WeaselJson_OK);
|
||||||
|
// It should keep reporting a terminal failure.
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, nullptr, 0) != WeaselJson_OK);
|
||||||
|
|
||||||
|
// Further data chunks must also stay terminal.
|
||||||
|
std::string more = "]]";
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, more.data(), more.size()) !=
|
||||||
|
WeaselJson_OK);
|
||||||
|
|
||||||
|
WeaselJsonParser_destroy(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("overflow is sticky for nested objects") {
|
||||||
|
auto c = noopCallbacks();
|
||||||
|
auto *parser = WeaselJsonParser_create(4, &c, nullptr, 0);
|
||||||
|
REQUIRE(parser != nullptr);
|
||||||
|
|
||||||
|
std::string doc = "{\"a\":{ \"a\":";
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, doc.data(), doc.size()) ==
|
||||||
|
WeaselJson_OVERFLOW);
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, nullptr, 0) != WeaselJson_OK);
|
||||||
|
|
||||||
|
WeaselJsonParser_destroy(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("reset clears overflow state") {
|
||||||
|
auto c = noopCallbacks();
|
||||||
|
auto *parser = WeaselJsonParser_create(3, &c, nullptr, 0);
|
||||||
|
REQUIRE(parser != nullptr);
|
||||||
|
|
||||||
|
std::string doc = "[[";
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, doc.data(), doc.size()) ==
|
||||||
|
WeaselJson_OVERFLOW);
|
||||||
|
// After reset the parser should accept a minimal document again.
|
||||||
|
WeaselJsonParser_reset(parser);
|
||||||
|
std::string copy = "1";
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, copy.data(), copy.size()) ==
|
||||||
|
WeaselJson_AGAIN);
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, nullptr, 0) == WeaselJson_OK);
|
||||||
|
|
||||||
|
WeaselJsonParser_destroy(parser);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("rejected state is sticky") {
|
TEST_CASE("rejected state is sticky") {
|
||||||
auto c = noopCallbacks();
|
auto c = noopCallbacks();
|
||||||
auto *parser = WeaselJsonParser_create(1024, &c, nullptr, 0);
|
auto *parser = WeaselJsonParser_create(1024, &c, nullptr, 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user