Summary
tensorflow/lite/micro/memory_helpers.cc computes the byte length of tensors using a 32-bit signed int running product before assigning the result to a size_t. Because tensor shape dimensions and element type sizes come from the (untrusted) flatbuffer model, a model with a shape such as [65536, 65536] over a 4-byte element type produces an element-count product of 2^32, which wraps to 0 in the existing code and causes *bytes = 0.
The same pattern appears in three places:
BytesRequiredForTensor (called during initial allocation from the flatbuffer model)
TfLiteEvalTensorByteLength
AllocateOutputDimensionsFromInput
A downstream allocator that trusts *bytes then operates on a tensor whose advertised size is 0 while its dimensions imply ~17 GiB of storage, which is a memory corruption surface when models are loaded from an untrusted source.
Reproducer
The arithmetic from BytesRequiredForTensor extracted into a self-contained C++ program:
size_t VulnerableBytesRequiredForTensor(const int32_t* shape, size_t rank,
size_t type_size) {
int element_count = 1;
for (size_t n = 0; n < rank; ++n) {
element_count *= shape[n];
}
return element_count * type_size;
}
int main() {
const int32_t shape[] = {65536, 65536};
const size_t type_size = 4; // float32
// Mathematically: 17,179,869,184 bytes.
// Observed: 0 (signed 32-bit wraparound).
std::cout << VulnerableBytesRequiredForTensor(shape, 2, type_size) << "\n";
}
Proposed fix
See PR — running product moved to size_t, every multiplication guarded against size_t overflow, negative dimensions rejected, and three regression tests added in memory_helpers_test.cc.
Summary
tensorflow/lite/micro/memory_helpers.cccomputes the byte length of tensors using a 32-bit signedintrunning product before assigning the result to asize_t. Because tensor shape dimensions and element type sizes come from the (untrusted) flatbuffer model, a model with a shape such as[65536, 65536]over a 4-byte element type produces an element-count product of 2^32, which wraps to0in the existing code and causes*bytes = 0.The same pattern appears in three places:
BytesRequiredForTensor(called during initial allocation from the flatbuffer model)TfLiteEvalTensorByteLengthAllocateOutputDimensionsFromInputA downstream allocator that trusts
*bytesthen operates on a tensor whose advertised size is0while its dimensions imply ~17 GiB of storage, which is a memory corruption surface when models are loaded from an untrusted source.Reproducer
The arithmetic from
BytesRequiredForTensorextracted into a self-contained C++ program:Proposed fix
See PR — running product moved to
size_t, every multiplication guarded againstsize_toverflow, negative dimensions rejected, and three regression tests added inmemory_helpers_test.cc.