Skip to main content
Sigvex

Assembly Analysis Remediation

Make inline assembly memory-safe, bound returndata copies, and add overflow guards that Solidity would otherwise provide.

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

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 unchecked region is provably safe.

Common Mistakes

  • Declaring a block memory-safe while 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.

References