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
This commit is contained in:
2026-06-22 02:29:13 -04:00
parent 5e18347e35
commit a26e101191
2 changed files with 24 additions and 0 deletions
+12
View File
@@ -84,7 +84,19 @@ def test_mixed_values():
assert recorder.events.count("null") == 1 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__": if __name__ == "__main__":
test_object_keys_routed_correctly() test_object_keys_routed_correctly()
test_mixed_values() test_mixed_values()
test_create_rejects_too_small_stack()
print("python bindings ok") print("python bindings ok")
+12
View File
@@ -117,12 +117,24 @@ class WeaselJsonParser:
self.voidp_callbacks, self.voidp_callbacks,
0, 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: def parse(self, data: bytes) -> WeaselJsonStatus:
self._check_open()
buf = (ctypes.c_ubyte * len(data)).from_buffer(bytearray(data)) buf = (ctypes.c_ubyte * len(data)).from_buffer(bytearray(data))
return self._lib.WeaselJsonParser_parse(self.p, buf, len(data)) return self._lib.WeaselJsonParser_parse(self.p, buf, len(data))
def reset(self): def reset(self):
self._check_open()
self._lib.WeaselJsonParser_reset(self.p) self._lib.WeaselJsonParser_reset(self.p)
def __enter__(self): def __enter__(self):