Generated RootBuilder dereferences null when WeaselJsonParser_create fails #36

Closed
opened 2026-06-28 15:42:57 +00:00 by weaselbot · 0 comments
Member

The generated RootBuilder constructor calls WeaselJsonParser_create and stores the result in parser_, but it never checks whether the call returned nullptr. WeaselJsonParser_create can return nullptr when stackSize is negative (or too small) or when memory allocation fails. When that happens, every later feed() call dereferences the null pointer and the process crashes.

Relevant code

File: contrib/schemagen/weaseljson_schemagen.py

  • Lines 892-894: the generated constructor template.
explicit RootBuilder(int stackSize = 1024) {{
    cb_ = makeCallbacks();
    parser_ = WeaselJsonParser_create(stackSize, &cb_, this, 0);
}}

There is no check for parser_ == nullptr, and feed() calls WeaselJsonParser_parse(parser_, ...) unconditionally.

Reproduction

Generate any schema, e.g.:

python3 contrib/schemagen/weaseljson_schemagen.py     contrib/schemagen/nullable_string.schema.json     -o /tmp/gen.h --namespace ns

Then compile and run:

#include "/tmp/gen.h"
#include <cstdio>
int main() {
    ns::RootBuilder b(-1);  // invalid stack size
    char buf[] = "null";
    WeaselJsonStatus s = b.feed(buf, sizeof(buf) - 1);
    std::printf("status %d
", s);
    return 0;
}
c++ -std=c++20 -Iinclude -Lbuild -lweaseljson -Wl,-rpath,'$PWD'/build repro.cpp -o repro
./repro

Result:

Segmentation fault (core dumped)

Expected behavior

If WeaselJsonParser_create fails, the generated builder should either throw an exception (e.g. std::runtime_error), set an internal error flag so that feed() returns WeaselJson_REJECT, or both. It must not dereference a null pointer.

Actual behavior

RootBuilder stores nullptr in parser_ and later feed() passes it to the C parser, causing a segfault.

Impact

Any caller that instantiates a generated builder with an invalid stackSize (including a negative value or a value too small for the bootstrap symbols) or under memory pressure will crash at the first feed() call. This is an easy-to-hit failure mode because the constructor exposes stackSize as a public parameter and the C API already defines the failure path.

The generated `RootBuilder` constructor calls `WeaselJsonParser_create` and stores the result in `parser_`, but it never checks whether the call returned `nullptr`. `WeaselJsonParser_create` can return `nullptr` when `stackSize` is negative (or too small) or when memory allocation fails. When that happens, every later `feed()` call dereferences the null pointer and the process crashes. **Relevant code** File: `contrib/schemagen/weaseljson_schemagen.py` - Lines 892-894: the generated constructor template. ```cpp explicit RootBuilder(int stackSize = 1024) {{ cb_ = makeCallbacks(); parser_ = WeaselJsonParser_create(stackSize, &cb_, this, 0); }} ``` There is no check for `parser_ == nullptr`, and `feed()` calls `WeaselJsonParser_parse(parser_, ...)` unconditionally. **Reproduction** Generate any schema, e.g.: ```sh python3 contrib/schemagen/weaseljson_schemagen.py contrib/schemagen/nullable_string.schema.json -o /tmp/gen.h --namespace ns ``` Then compile and run: ```cpp #include "/tmp/gen.h" #include <cstdio> int main() { ns::RootBuilder b(-1); // invalid stack size char buf[] = "null"; WeaselJsonStatus s = b.feed(buf, sizeof(buf) - 1); std::printf("status %d ", s); return 0; } ``` ```sh c++ -std=c++20 -Iinclude -Lbuild -lweaseljson -Wl,-rpath,'$PWD'/build repro.cpp -o repro ./repro ``` Result: ``` Segmentation fault (core dumped) ``` **Expected behavior** If `WeaselJsonParser_create` fails, the generated builder should either throw an exception (e.g. `std::runtime_error`), set an internal error flag so that `feed()` returns `WeaselJson_REJECT`, or both. It must not dereference a null pointer. **Actual behavior** `RootBuilder` stores `nullptr` in `parser_` and later `feed()` passes it to the C parser, causing a segfault. **Impact** Any caller that instantiates a generated builder with an invalid `stackSize` (including a negative value or a value too small for the bootstrap symbols) or under memory pressure will crash at the first `feed()` call. This is an easy-to-hit failure mode because the constructor exposes `stackSize` as a public parameter and the C API already defines the failure path.
weaselbot was assigned by andrew 2026-06-30 14:57:14 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: weaselab/weaseljson#36