forked from weaselab/weaseljson
Parser3::reset: clear inKey and other per-parse transient state
WeaselJsonParser_reset is documented to restore the parser to its newly-created state, but reset() only rewound the symbol stack. The inKey flag and transient DFA/codepoint state from the previous parse leaked into the next parse, so a top-level string after a mid-key reset was delivered via on_key_data instead of on_string_data. Reset inKey to false and clear utf8Codepoint, utf16Surrogate, minCodepoint, numDfa, and strDfa so the next document starts fresh. Add a test that reproduces the reported misrouting.
This commit is contained in:
@@ -138,6 +138,12 @@ struct Parser3 {
|
|||||||
void reset() {
|
void reset() {
|
||||||
stackPtr = stack();
|
stackPtr = stack();
|
||||||
std::ignore = push({N_VALUE, N_WHITESPACE, T_EOF});
|
std::ignore = push({N_VALUE, N_WHITESPACE, T_EOF});
|
||||||
|
inKey = false;
|
||||||
|
utf8Codepoint = 0;
|
||||||
|
utf16Surrogate = 0;
|
||||||
|
minCodepoint = 0;
|
||||||
|
numDfa.reset();
|
||||||
|
strDfa.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used for flushing pending data with on_*_data callbacks
|
// Used for flushing pending data with on_*_data callbacks
|
||||||
|
|||||||
@@ -223,6 +223,47 @@ TEST_CASE("create rejects too-small stack") {
|
|||||||
|
|
||||||
TEST_CASE("streaming") { testStreaming(json); }
|
TEST_CASE("streaming") { testStreaming(json); }
|
||||||
|
|
||||||
|
TEST_CASE("reset clears inKey and transient state") {
|
||||||
|
struct State {
|
||||||
|
std::string stringData;
|
||||||
|
std::string keyData;
|
||||||
|
} state;
|
||||||
|
auto c = noopCallbacks();
|
||||||
|
c.on_string_data = +[](void *p, const char *buf, int len, int /*done*/) {
|
||||||
|
((State *)p)->stringData.append(buf, len);
|
||||||
|
};
|
||||||
|
c.on_key_data = +[](void *p, const char *buf, int len, int /*done*/) {
|
||||||
|
((State *)p)->keyData.append(buf, len);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto *parser = WeaselJsonParser_create(1024, &c, &state, 0);
|
||||||
|
REQUIRE(parser != nullptr);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::string chunk = "{\"ab";
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, chunk.data(), chunk.size()) ==
|
||||||
|
WeaselJson_AGAIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset mid-key: the next top-level string must be delivered as a string,
|
||||||
|
// not appended to the aborted key.
|
||||||
|
WeaselJsonParser_reset(parser);
|
||||||
|
state.stringData.clear();
|
||||||
|
state.keyData.clear();
|
||||||
|
|
||||||
|
{
|
||||||
|
std::string chunk = "\"hello\"";
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, chunk.data(), chunk.size()) ==
|
||||||
|
WeaselJson_AGAIN);
|
||||||
|
}
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, nullptr, 0) == WeaselJson_OK);
|
||||||
|
|
||||||
|
CHECK(state.stringData == "hello");
|
||||||
|
CHECK(state.keyData.empty());
|
||||||
|
|
||||||
|
WeaselJsonParser_destroy(parser);
|
||||||
|
}
|
||||||
|
|
||||||
void doTestUnescapingUtf8(std::string const &escaped,
|
void doTestUnescapingUtf8(std::string const &escaped,
|
||||||
std::string const &expected, int stride, int flags) {
|
std::string const &expected, int stride, int flags) {
|
||||||
CAPTURE(escaped);
|
CAPTURE(escaped);
|
||||||
|
|||||||
Reference in New Issue
Block a user