[Runtime][VM] Bounds-check per-parameter byteOffset/nbytes in tensor-cache loader - #348
[Runtime][VM] Bounds-check per-parameter byteOffset/nbytes in tensor-cache loader#348professor-moody wants to merge 6 commits into
Conversation
MLC local ci setup. Also CI for Windows and macOS building, which may take 90-100 mins. Co-authored-by: Siyuan Feng <Hzfengsy@sjtu.edu.cn>
- Revert "[CMake][MSVC] Disable permissive mode for MSVC builds (#16343)" - Skip MSC tests - Disable NNPack and TFLite - Tweak CMAKE_CUDA_ARCHITECTURES
Draft message; will be rewritten via commit-amend guidance.
…cache loader ParamRecord::Load copies each parameter from the shard buffer using byte_offset and nbytes taken from tensor-cache.json. FileRecord::Load validates only the shard total, not each parameter's range, so an inconsistent cache reads out of bounds of the shard buffer. The f32-to-bf16 path additionally allocates buffer(nbytes/2), which is one byte short of the memcpy for odd nbytes. Add a null check, an overflow-safe range check, and an even-nbytes check on the f32-to-bf16 path so malformed input fails with a clear ValueError. Mirrors the same hardening upstream in apache/tvm#19997.
There was a problem hiding this comment.
Code Review
This pull request adds bounds checking for parameter byte ranges against the shard buffer in TensorCacheMetadata::FileRecord::ParamRecord::Load to prevent out-of-bounds reads, and validates that nbytes is even for the f32-to-bf16 format. The review feedback identifies two potential undefined behavior issues: a signed integer overflow risk in the error message's addition of byte_offset + nbytes, and a null pointer passing to std::memcpy if nbytes is zero. Both comments are valid and should be addressed.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| << "Parameter byte range [" << byte_offset << ", " << (byte_offset + nbytes) | ||
| << ") is out of bounds of the " << shard_len << "-byte shard buffer."; |
There was a problem hiding this comment.
Although the bounds check is written to avoid signed overflow on byte_offset + nbytes, the error message itself evaluates byte_offset + nbytes. If a malformed or malicious tensor-cache.json contains extremely large values (e.g., byte_offset = INT64_MAX), this addition will trigger signed integer overflow, which is undefined behavior in C++. To prevent this, avoid performing the addition in the error message stream and print the offset and length separately.
<< "Parameter byte range starting at " << byte_offset << " with length " << nbytes
<< " is out of bounds of the " << shard_len << "-byte shard buffer.";| << "Parameter nbytes must be even for the f32-to-bf16 format, but got " << nbytes << "."; | ||
| std::vector<uint16_t> buffer(nbytes / 2); | ||
| std::vector<uint32_t> decoded(nbytes / 2); | ||
| std::memcpy(buffer.data(), raw_data->data() + byte_offset, nbytes); |
There was a problem hiding this comment.
If nbytes is 0, buffer will be empty and buffer.data() will return nullptr. Passing a null pointer to std::memcpy even with a size of 0 is undefined behavior in C++. Guard the std::memcpy call with a check for nbytes > 0 to prevent this.
if (nbytes > 0) {
std::memcpy(buffer.data(), raw_data->data() + byte_offset, nbytes);
}
Mirrors the same tensor-cache hardening as upstream apache/tvm#19997.
ParamRecord::Loadcopies each parameter from the shard buffer usingbyte_offsetandnbytesfromtensor-cache.json.FileRecord::Loadvalidates only the shard total, not each parameter's range, so an inconsistent cache directory reads out of bounds of the shard buffer. Thef32-to-bf16path additionally allocatesbuffer(nbytes / 2), which is one byte short of thememcpywhennbytesis odd.This adds, in
ParamRecord::Load: a null check on the shard buffer, an overflow-safe range check (byte_offset/nbyteswithin the shard), and an even-nbytescheck on thef32-to-bf16path. Malformed/inconsistent cache input now fails with a clearValueErrorinstead of reading or writing out of bounds.