forked from weaselab/weaseljson
Reject negative lengths in WeaselJsonParser_parse
`Parser3::parse` previously formed `buf + len` immediately, so passing a negative `len` from the C API caused undefined pointer arithmetic. Add an explicit `len < 0` check that returns `WeaselJson_REJECT` (and makes the rejected state sticky) before any `buf + len` computation. Also document the non-negative length precondition in the public header and add a regression test. Closes #24
This commit is contained in:
@@ -64,7 +64,8 @@ void WeaselJsonParser_destroy(WeaselJsonParser *parser);
|
|||||||
|
|
||||||
/** Incrementally parse `len` more bytes starting at `buf`. `buf` may be
|
/** Incrementally parse `len` more bytes starting at `buf`. `buf` may be
|
||||||
* modified. Call with `len` 0 to indicate end of data. `buf` may be null if
|
* modified. Call with `len` 0 to indicate end of data. `buf` may be null if
|
||||||
* `len` is 0 */
|
* `len` is 0. `len` must not be negative; a negative length is treated as a
|
||||||
|
* rejected input. */
|
||||||
WeaselJsonStatus WeaselJsonParser_parse(WeaselJsonParser *parser, char *buf,
|
WeaselJsonStatus WeaselJsonParser_parse(WeaselJsonParser *parser, char *buf,
|
||||||
int len);
|
int len);
|
||||||
|
|
||||||
|
|||||||
@@ -1068,6 +1068,11 @@ inline WeaselJsonStatus Parser3::parse(char *buf, int len) {
|
|||||||
return WeaselJson_REJECT;
|
return WeaselJson_REJECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (len < 0) [[unlikely]] {
|
||||||
|
this->rejected = true;
|
||||||
|
return WeaselJson_REJECT;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAS_MUSTTAIL
|
#ifdef HAS_MUSTTAIL
|
||||||
// The continuation returns a value in 0..3 here (kBounce is only used by the
|
// The continuation returns a value in 0..3 here (kBounce is only used by the
|
||||||
// no-musttail trampoline below), so the conversion back to the enum is in
|
// no-musttail trampoline below), so the conversion back to the enum is in
|
||||||
|
|||||||
@@ -246,6 +246,20 @@ TEST_CASE("create rejects too-small stack") {
|
|||||||
WeaselJsonParser_destroy(parser);
|
WeaselJsonParser_destroy(parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("parse rejects negative length") {
|
||||||
|
auto c = noopCallbacks();
|
||||||
|
auto *parser = WeaselJsonParser_create(1024, &c, nullptr, 0);
|
||||||
|
REQUIRE(parser != nullptr);
|
||||||
|
|
||||||
|
// A negative length must not cause pointer arithmetic UB. It should be
|
||||||
|
// rejected, and the rejected state should remain sticky.
|
||||||
|
char buf[10] = "hello";
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, buf, -1) == WeaselJson_REJECT);
|
||||||
|
REQUIRE(WeaselJsonParser_parse(parser, nullptr, 0) == WeaselJson_REJECT);
|
||||||
|
|
||||||
|
WeaselJsonParser_destroy(parser);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("streaming") { testStreaming(json); }
|
TEST_CASE("streaming") { testStreaming(json); }
|
||||||
|
|
||||||
TEST_CASE("reset clears inKey and transient state") {
|
TEST_CASE("reset clears inKey and transient state") {
|
||||||
|
|||||||
Reference in New Issue
Block a user