Repository navigation
Harden Mat_VarCreate/VarCreateStruct against integer overflow and NULL deref - #380
bg0d-droid wants to merge 1 commit into
Conversation
cc8f531 to
9f18851
Compare
dfb69ad to
f1a9a69
Compare
|
Note on the Everything before it passed: If you want fork PRs to stay green, guarding that step (e.g. |
…L deref The public constructors computed allocation sizes and element counts with unchecked arithmetic on caller-supplied dimensions: - nelems *= dims[j] could wrap silently, so a tiny allocation was made for a "large" array (heap overflow when data is later written). - malloc(rank * sizeof(*dims)) was unchecked, and a negative rank was accepted (huge size_t allocation / OOB write). - The sparse copy path multiplied nir/njc/ndata by element size unchecked for both allocation and memcpy. - Struct creation with a NULL field name crashed in strdup(NULL). - malloc/strdup return values were not checked. Replace all of these with the existing checked Mul() helper and proper NULL/error handling, matching the convention already used by the file parsing paths. Mat_VarCreate and Mat_VarCreateStruct now fail cleanly with NULL on malformed input. Add var_api tests covering overflowing dimensions, negative rank and NULL struct field names. The NULL-fieldname case segfaults on unpatched code, so these are true regression tests.
f1a9a69 to
0025b35
Compare
|
After rebasing a new test error appeared. Can you please have a look. |
Summary
This PR systematically hardens the two public variable constructors,
Mat_VarCreate(src/mat.c) andVarCreateStruct(src/matvar_struct.c), against integer-overflow and NULL-deref bugs arising from untrustedrank/dims/field metadata. All size arithmetic now goes through the project's existing checkedMul()helper — the same convention the file-parsing paths (e.g.Mat_VarGetSize, the mat5 readers) already follow.Issues fixed
1. Silent wrap of the element count (
nelems *= dims[j]) — both constructors multiplied caller-supplied dimensions without checks. A wrappednelemsmakesMat_VarGetSize/data allocation undersized relative torank/dims, so any later per-element write throughdims-shaped iteration overflows the heap buffer. Now each multiply is checked and creation fails cleanly withNULL.2. Unchecked
malloc(rank * sizeof(*dims))+ negativerank—rankis a signedint. A negative rank passed straight into the allocation size produced a hugesize_t, and the copy loopj < ranksemantics diverged from the allocation. Both constructors now rejectrank < 0up front and use a checked size for the allocation.3. Unchecked sparse-copy arithmetic —
Mat_VarCreate's sparse path computednir * sizeof(*ir),njc * sizeof(*jc)andndata * data_sizeinline for bothmallocandmemcpy. On 32-bitsize_tplatforms these wrap. All three products are now computed once withMul()and reused for allocation and copy.4.
strdup(NULL)crash on struct creation —Mat_VarCreatewithMAT_C_STRUCTcopiedfields[i]->namewithstrdupunconditionally. A field withname == NULLsegfaults (reproduced against unpatched master in the regression run below). Field names are now validated before use.5. Unchecked
malloc/strdup/callocreturns — allocation failures previously fell through to NULL writes. All results are now checked, withMat_VarFree(matvar)cleanup on every error path (no leaks; verified by the error-path tests).Testing
New
var_apitests (registered in both the CMake glob and the autotoolstestsuite.at/Makefile.am):var_api_create_overflow_dims— dims ofSIZE_MAXmust be rejected, not silently wrapped (covers both constructors).var_api_create_negative_rank—rank = -1must be rejected (covers both constructors).var_api_create_null_fieldname— struct creation with a NULL field name must fail cleanly.Full suite on this branch (Ubuntu, GCC + HDF5 enabled): 8725/8725 tests pass.
Regression proof — the new tests were run against unpatched
mastersources:var_api_create_overflow_dims/var_api_create_negative_rank: fail as expected (creation succeeds where it must not).var_api_create_null_fieldname: segfaults (strdup(NULL)) on unpatched code.Formatting verified with the project's pinned clang-format 23.1.2 (clean on all touched C files).
Security impact
These constructors are the entry point for building variables from application-supplied (and, in downstream applications, file-derived) shapes and field metadata. The wrap bugs are the classic undersized-allocation → heap-overflow primitive; the NULL-field crash is a straightforward NULL deref. Beyond the specific cases, the patch eliminates the error-prone unchecked size arithmetic in these paths entirely, matching the codebase's established
Mul()-based convention so future edits don't regress.