security: fix integer overflow in safeAddToBufferSize on MSVC
The MSVC fallback path in safeAddToBufferSize() performed unchecked arithmetic (type_size*nr*nc) on attacker-controlled values read from .mjb binary model files. This could cause integer overflow, leading to an undersized heap allocation followed by a heap buffer overflow when data is copied into the buffer. The fix adds manual overflow detection using SIZE_MAX/INTPTR_MAX comparisons, matching the behavior of the existing __builtin_*_overflow path used on GCC/Clang. Also adds a regression test that crafts a binary model buffer with overflow-inducing size fields and asserts safe rejection.
This commit is contained in:
+26
-3
@@ -184,9 +184,32 @@ static mjtSize safeAddToBufferSize(intptr_t* offset, mjtSize* nbuffer,
|
||||
if (__builtin_add_overflow(*nbuffer, to_add, nbuffer)) return 0;
|
||||
if (__builtin_add_overflow(*offset, to_add, offset)) return 0;
|
||||
#else
|
||||
// TODO: offer a safe implementation for MSVC or other compilers that don't have the builtins
|
||||
*nbuffer += SKIP(*offset) + type_size*nr*nc;
|
||||
*offset += SKIP(*offset) + type_size*nr*nc;
|
||||
// safe overflow checks for MSVC and other compilers without __builtin_*_overflow
|
||||
{
|
||||
size_t product;
|
||||
size_t to_add;
|
||||
size_t skip = SKIP(*offset);
|
||||
|
||||
// nc * nr
|
||||
if (nr > 0 && (size_t)nc > SIZE_MAX / (size_t)nr) return 0;
|
||||
product = (size_t)nc * (size_t)nr;
|
||||
|
||||
// product * type_size
|
||||
if (type_size > 0 && product > SIZE_MAX / type_size) return 0;
|
||||
product *= type_size;
|
||||
|
||||
// product + SKIP(*offset)
|
||||
if (product > SIZE_MAX - skip) return 0;
|
||||
to_add = product + skip;
|
||||
|
||||
// *nbuffer + to_add
|
||||
if ((size_t)*nbuffer > SIZE_MAX - to_add) return 0;
|
||||
*nbuffer += to_add;
|
||||
|
||||
// *offset + to_add
|
||||
if (*offset > 0 && to_add > (size_t)(INTPTR_MAX - *offset)) return 0;
|
||||
*offset += to_add;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
|
||||
Reference in New Issue
Block a user