diff --git a/src/parser3.h b/src/parser3.h index 639a05f..053ed33 100644 --- a/src/parser3.h +++ b/src/parser3.h @@ -83,26 +83,28 @@ struct Parser3 { [[nodiscard]] WeaselJsonStatus parse(char *buf, int len); void flushNumber(bool done, char *buf) { - int len = buf - dataBegin; + int len = (intptr_t)buf - (intptr_t)dataBegin; assert(len >= 0); if (done || len > 0) { - callbacks->on_number_data(userdata, dataBegin, len, done); + callbacks->on_number_data(userdata, dataBegin ? dataBegin : "", len, + done); } } void flushString(bool done, char *buf) { int len; if (!(flags & WeaselJsonRaw)) { - len = writeBuf - dataBegin; + len = (intptr_t)writeBuf - (intptr_t)dataBegin; } else { - len = buf - dataBegin; + len = (intptr_t)buf - (intptr_t)dataBegin; } assert(len >= 0); if (done || len > 0) { + const char *data = dataBegin ? dataBegin : ""; if (inKey) { - callbacks->on_key_data(userdata, dataBegin, len, done); + callbacks->on_key_data(userdata, data, len, done); } else { - callbacks->on_string_data(userdata, dataBegin, len, done); + callbacks->on_string_data(userdata, data, len, done); } } } diff --git a/src/test.cpp b/src/test.cpp index eec6669..792cafa 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -303,6 +303,24 @@ TEST_CASE("reset clears inKey and transient state") { WeaselJsonParser_destroy(parser); } +TEST_CASE("scalar ending at chunk boundary is finalized at EOF") { + // A number whose digits exactly fill the first chunk must not invoke + // undefined behaviour on the EOF call, and must still signal completion. + auto c = serializeCallbacks(); + SerializeState state; + auto *parser = WeaselJsonParser_create(1024, &c, &state, 0); + REQUIRE(parser != nullptr); + + std::string chunk = "123"; + REQUIRE(WeaselJsonParser_parse(parser, chunk.data(), chunk.size()) == + WeaselJson_AGAIN); + REQUIRE(WeaselJsonParser_parse(parser, nullptr, 0) == WeaselJson_OK); + + CHECK(state.result == "(123)"); + + WeaselJsonParser_destroy(parser); +} + void doTestUnescapingUtf8(std::string const &escaped, std::string const &expected, int stride, int flags) { CAPTURE(escaped);