Assembly Analysis Remediation
Overview
Inline assembly bypasses Solidity’s safety features: bounds checks, overflow checks, and the free memory pointer discipline are all your responsibility. The detector flags assembly that writes into reserved memory without declaring memory-safe, copies returndata without bounds, or does arithmetic without guards. The fix is to respect the memory model and re-add the checks the compiler would have inserted.
Related Detector: Assembly Analysis
Recommended Fix
Before (Vulnerable)
function getReturn(address target, bytes calldata data) external returns (bytes memory out) {
assembly {
let ok := call(gas(), target, 0, data.offset, data.length, 0, 0)
// Writes to scratch space and ignores returndatasize bounds
returndatacopy(0x00, 0, 0x40)
out := mload(0x00)
}
}
After (Fixed)
function getReturn(address target, bytes calldata data) external returns (bytes memory out) {
assembly ("memory-safe") {
let ptr := mload(0x40) // use the free memory pointer
let ok := call(gas(), target, 0, data.offset, data.length, 0, 0)
let size := returndatasize() // bound the copy by actual size
returndatacopy(ptr, 0, size)
mstore(0x40, add(ptr, size)) // advance the free memory pointer
if iszero(ok) { revert(ptr, size) }
out := ptr
}
}
Allocating from the free memory pointer and advancing it keeps later Solidity code from reading corrupted memory, and copying exactly returndatasize() bytes prevents both truncation and reads past the returned data. The memory-safe annotation is only safe to use once these rules hold.
Alternative Mitigations
- Prefer high-level Solidity when no measurable gas benefit justifies assembly; the compiler inserts the checks for you.
- For external calls, use the standard high-level call syntax or a vetted library rather than hand-written
call/returndatacopy. - Wrap arithmetic that can overflow in checked operations, or document why an
uncheckedregion is provably safe.
Common Mistakes
- Declaring a block
memory-safewhile still writing below the free memory pointer. - Copying a fixed number of returndata bytes instead of
returndatasize(). - Adding, subtracting, or multiplying in assembly without considering wraparound.