Skip to content

Assembly clearing local variable #13494

Closed
@wighawag

Description

@wighawag

Description

It seems in some conditions, assembly code is messing up with local variable even when it should not

What is even weirder, is that adding some extra code remove the issue.

Reproduction repo here :
https://github.com/bug-reproduction/solidity-assembly-variable-reset

Environment

  • Compiler version: 0.8.16 (tested also on 0.8.13)
  • Target EVM version (as per compiler settings): default settings with optimizer (runs: 2000)
  • Framework/IDE (e.g. Truffle or Remix): hardhat
  • EVM execution environment / backend / blockchain client: geth
  • Operating system: linux

Steps to Reproduce

// SPDX-License-Identifier: AGPL-1.0
pragma solidity 0.8.16;

contract Test {
	event Debug(address deployedContract);

	function deployData(bytes calldata) external {
		address newContract;
		assembly {
			let len := calldataload(36)
			let p := mload(0x40)
			mstore(p, 0x61FFFF600E60003961FFFF6000F3000000000000000000000000000000000000)
			let lenByte1 := shr(8, len)
			let lenByte2 := and(len, 0xFF)
			mstore8(add(p, 1), lenByte1)
			mstore8(add(p, 2), lenByte2)
			mstore8(add(p, 9), lenByte1)
			mstore8(add(p, 10), lenByte2)
			calldatacopy(add(p, 14), 68, len)

			newContract := create(0, p, add(len, 14))
			// log1(p, add(len, 14), newContract) // need this line, no idea why, looks like some memory management issues
		}
		emit Debug(newContract);
	}

	function deployDataWithLog1(bytes calldata) external {
		address newContract;
		assembly {
			let len := calldataload(36)
			let p := mload(0x40)
			mstore(p, 0x61FFFF600E60003961FFFF6000F3000000000000000000000000000000000000)
			let lenByte1 := shr(8, len)
			let lenByte2 := and(len, 0xFF)
			mstore8(add(p, 1), lenByte1)
			mstore8(add(p, 2), lenByte2)
			mstore8(add(p, 9), lenByte1)
			mstore8(add(p, 10), lenByte2)
			calldatacopy(add(p, 14), 68, len)

			newContract := create(0, p, add(len, 14))
			log1(p, add(len, 14), newContract) // need this line, no idea why, looks like some memory management issues
		}
		emit Debug(newContract);
	}

	function deployData2(bytes calldata data) external {
		bytes memory deployCode = bytes.concat(hex"61FFFF600E60003961FFFF6000F3", data);
		bytes1 lenByte1 = bytes1(uint8(data.length >> 8));
		bytes1 lenByte2 = bytes1(uint8(data.length & 0xFF));
		deployCode[1] = lenByte1;
		deployCode[9] = lenByte1;
		deployCode[2] = lenByte2;
		deployCode[10] = lenByte2;

		address newContract;
		assembly {
			newContract := create(0, add(deployCode, 32), mload(deployCode))
			// log1(add(deployCode, 32), mload(deployCode), newContract) // need this line, no idea why, looks like some memory management issues
		}
		emit Debug(newContract);
	}

	function deployData2WithLog1(bytes calldata data) external {
		bytes memory deployCode = bytes.concat(hex"61FFFF600E60003961FFFF6000F3", data);
		bytes1 lenByte1 = bytes1(uint8(data.length >> 8));
		bytes1 lenByte2 = bytes1(uint8(data.length & 0xFF));
		deployCode[1] = lenByte1;
		deployCode[9] = lenByte1;
		deployCode[2] = lenByte2;
		deployCode[10] = lenByte2;

		address newContract;
		assembly {
			newContract := create(0, add(deployCode, 32), mload(deployCode))
			log1(add(deployCode, 32), mload(deployCode), newContract) // need this line, no idea why, looks like some memory management issues
		}
		emit Debug(newContract);
	}
}

The issue only arise when the input data is big enough, tested with 24000 bytes

see repo for reproducing the bug : https://github.com/bug-reproduction/solidity-assembly-variable-reset

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions