Skip to content

Commit a52ec64

Browse files
committed
pysimlin: clean up FFI error allocations
pysimlin: clean up FFI error allocations Ensure JSON patch paths always free collected error objects and release any allocated C strings when name or link counts mismatch. This prevents leaks on error paths and keeps ownership rules consistent. Assumes libsimlin may partially populate result arrays before reporting a mismatch, so we now free any non-null entries in the allocated range.
1 parent fe34678 commit a52ec64

3 files changed

Lines changed: 15 additions & 7 deletions

File tree

src/pysimlin/simlin/_ffi.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,14 +180,16 @@ def apply_patch_json(
180180
out_collected_errors_ptr,
181181
err_ptr,
182182
)
183-
check_out_error(err_ptr, "Apply JSON patch")
184-
185183
errors: List[ErrorDetail] = []
186-
if out_collected_errors_ptr[0] != ffi.NULL:
187-
errors = extract_error_details(out_collected_errors_ptr[0])
188-
lib.simlin_error_free(out_collected_errors_ptr[0])
189-
190-
return errors
184+
errors_ptr = out_collected_errors_ptr[0]
185+
try:
186+
check_out_error(err_ptr, "Apply JSON patch")
187+
if errors_ptr != ffi.NULL:
188+
errors = extract_error_details(errors_ptr)
189+
return errors
190+
finally:
191+
if errors_ptr != ffi.NULL:
192+
lib.simlin_error_free(errors_ptr)
191193

192194

193195
def serialize_json(project_ptr: Any) -> bytes:

src/pysimlin/simlin/model.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ def get_incoming_links(self, var_name: str) -> List[str]:
251251

252252
actual_count = int(out_written_ptr[0])
253253
if actual_count != count:
254+
for i in range(count):
255+
if c_deps[i] != ffi.NULL:
256+
free_c_string(c_deps[i])
254257
raise SimlinRuntimeError(
255258
f"Failed to get incoming links for '{var_name}': count mismatch (expected {count}, got {actual_count})"
256259
)

src/pysimlin/simlin/project.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ def get_model_names(self) -> List[str]:
135135

136136
written = int(out_written_ptr[0])
137137
if written != count:
138+
for i in range(count):
139+
if c_names[i] != ffi.NULL:
140+
free_c_string(c_names[i])
138141
raise SimlinImportError(f"Failed to get model names: got {written}, expected {count}")
139142

140143
# Convert to Python strings and free C memory

0 commit comments

Comments
 (0)