Core ML (apple/coremltools) Span::Slice integer-overflow bounds-check bypass PoC
Proof-of-concept material for a huntr Model Format Vulnerability report
against apple/coremltools (MILBlob::Util::Span<T>::Slice,
mlmodel/src/MILBlob/Util/Span.hpp:322-327).
repro.cpp reproduces, in isolation, the exact bounds-check used by the real
code (verified against the live source, quoted directly below) and shows it
passes for an attacker-controlled size near SIZE_MAX:
// Real check, Span.hpp:325 (quoted, not paraphrased):
// MILVerifyIsTrue(size > 0 && index < Size() && index + size <= Size(), ...)
Verified live on this host:
index=10 size=18446744073709551611 total_size=4096
index+size (wrapped) = 5
bounds check passes (bug present if true): YES - BYPASSED
index + size overflows size_t and wraps to 5, which is <= 4096 -
the check passes despite size being enormous, and the returned Span
still carries the original, attacker-controlled size.
metadata.offset/metadata.sizeInBytes are read directly from a
weight.bin file (blob_metadata, StorageFormat.hpp:50-64) and validated
only by a magic sentinel 0xDEADBEEF (StorageReader.cpp:39-44), not by
range. MMapFileReader::ReadData() (MMapFileReader.cpp:54-57) calls
m_dataSpan.Slice(offset, length) directly on the real memory-mapped file -
so a crafted weight.bin with a sizeInBytes near SIZE_MAX reaches this
exact bypassed check.
Honest limits (not swept under the rug)
This report is source-level, not a run exploit. libmilstoragepython (the
native extension that would let this be triggered end-to-end from a crafted
.mlpackage via Python) is Apple/macOS-specific - it does not ship on Linux
at all (confirmed directly: pip install coremltools on this host loads
without any of the native extensions - ModuleNotFoundError: coremltools.libmilstoragepython), so no live .mlpackage-level
reproduction was possible on this server. Confidence rests on the arithmetic
being verified byte-for-byte against the live source and reproduced in
isolation with the exact real types (size_t), not on a live memory-
corruption crash.
Impact: an attacker who can supply or influence a Core ML weight.bin file
can bypass this bounds check via an oversized declared size, causing
MMapFileReader::ReadData() to return a Span that extends far past the
real mapped buffer - a potential out-of-bounds read, escalating from the
DoS-class findings elsewhere in this portfolio to memory corruption.