Bug
The file and tuple input paths allocate data with malloc and never free it, including after successful icsneoScriptLoad calls. The load_readbin wrapper repeats the same pattern.
Reviewed commit: 45167e09de6b886cd451a4245f842c8221349711 (current master on 2026-09-15).
Source: src/methods.cpp:1533
Reproduction
This reproducer uses a hardware-free DLL. Save this as mock.c:
#define API __declspec(dllexport)
typedef unsigned long long size_t;
API int icsneoScriptLoad(void* h, const unsigned char* data, unsigned long len, int location) { return 1; }
Build with LLVM on Windows x64:
clang-cl /nologo /c /GS- /Zl mock.c /Fomock.obj
lld-link /dll /noentry /nodefaultlib /out:mock.dll mock.obj
Then run:
import ics
import ctypes
from pathlib import Path
ics.override_library_name(str(Path('mock.dll').resolve()))
d = ics.PyNeoDeviceEx()
d._auto_handle_close = False
payload = Path('payload.bin')
payload.write_bytes(bytes(1024 * 1024))
for _ in range(20):
ics.coremini_load(d, str(payload), 0)
# Observe process private bytes with a process memory profiler.
Observed / expected
After one warmup load, 20 additional 1 MiB loads increased process private memory by 21,094,400 bytes. The mock does not allocate or retain the input. Expected transient script storage to be freed when the synchronous call returns. Source inspection confirms no free(data) on any path.
Suggested fix and regression coverage
Own script data with RAII (for example a vector) or free it on every exit. Check allocation and conversion errors. Cover repeated file/tuple loads and native failure paths; apply the same ownership fix to load_readbin.
Validation environment
Windows x64, CPython 3.14.5, extension rebuilt from the commit above. Hardware-dependent entry points below were exercised with a mock DLL, not a connected device. The existing 30 tests pass despite these findings.
Bug
The file and tuple input paths allocate
datawith malloc and never free it, including after successful icsneoScriptLoad calls. The load_readbin wrapper repeats the same pattern.Reviewed commit:
45167e09de6b886cd451a4245f842c8221349711(current master on 2026-09-15).Source: src/methods.cpp:1533
Reproduction
This reproducer uses a hardware-free DLL. Save this as
mock.c:Build with LLVM on Windows x64:
Then run:
Observed / expected
After one warmup load, 20 additional 1 MiB loads increased process private memory by 21,094,400 bytes. The mock does not allocate or retain the input. Expected transient script storage to be freed when the synchronous call returns. Source inspection confirms no free(data) on any path.
Suggested fix and regression coverage
Own script data with RAII (for example a vector) or free it on every exit. Check allocation and conversion errors. Cover repeated file/tuple loads and native failure paths; apply the same ownership fix to load_readbin.
Validation environment
Windows x64, CPython 3.14.5, extension rebuilt from the commit above. Hardware-dependent entry points below were exercised with a mock DLL, not a connected device. The existing 30 tests pass despite these findings.