From a26e10119120c299cb87feed1f694234d05258fb Mon Sep 17 00:00:00 2001 From: Weaselbot Date: Mon, 22 Jun 2026 02:29:13 -0400 Subject: [PATCH] check WeaselJsonParser_create return value in Python bindings Raise ValueError from __init__ when the C constructor returns NULL, instead of storing a NULL pointer that segfaults on parse()/reset(). Add defensive RuntimeError checks in parse() and reset() for closed or failed parsers. Add a test covering stackSize values that the C API rejects (-1, 0, 1, 2). Fixes #23 --- test_python_bindings.py | 12 ++++++++++++ weaseljson.py | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/test_python_bindings.py b/test_python_bindings.py index 5d955a9..48f01e0 100644 --- a/test_python_bindings.py +++ b/test_python_bindings.py @@ -84,7 +84,19 @@ def test_mixed_values(): assert recorder.events.count("null") == 1 +def test_create_rejects_too_small_stack(): + for stack_size in (-1, 0, 1, 2): + try: + parser = weaseljson.WeaselJsonParser(Recorder(), stackSize=stack_size) + except ValueError: + continue + # If creation unexpectedly succeeds, close it cleanly and fail the test. + parser.close() + raise AssertionError(f"expected ValueError for stackSize={stack_size}") + + if __name__ == "__main__": test_object_keys_routed_correctly() test_mixed_values() + test_create_rejects_too_small_stack() print("python bindings ok") diff --git a/weaseljson.py b/weaseljson.py index f1ece45..b6c20d6 100644 --- a/weaseljson.py +++ b/weaseljson.py @@ -117,12 +117,24 @@ class WeaselJsonParser: self.voidp_callbacks, 0, ) + if self.p is None: + raise ValueError( + "WeaselJsonParser_create returned NULL; " + "check stackSize (must be positive and large enough) " + "and available memory" + ) + + def _check_open(self): + if self.p is None: + raise RuntimeError("parser has been closed or creation failed") def parse(self, data: bytes) -> WeaselJsonStatus: + self._check_open() buf = (ctypes.c_ubyte * len(data)).from_buffer(bytearray(data)) return self._lib.WeaselJsonParser_parse(self.p, buf, len(data)) def reset(self): + self._check_open() self._lib.WeaselJsonParser_reset(self.p) def __enter__(self):