Merge pull request #12861 from ethereum/disallow-returndatacopy-in-pure-functions

Disallow RETURNDATACOPY and RETURNDATASIZE in inline assembly in pure functions
This commit is contained in:
chriseth 2022-04-28 13:15:04 +02:00 committed by GitHub
commit d55b84ff63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 431 additions and 5 deletions

View File

@ -13,6 +13,7 @@ Compiler Features:
Bugfixes: Bugfixes:
* Assembly-Json: Fix assembly json export to store jump types of operations in `jumpType` field instead of `value`. * Assembly-Json: Fix assembly json export to store jump types of operations in `jumpType` field instead of `value`.
* TypeChecker: Convert parameters of function type to how they would be called for ``abi.encodeCall``. * TypeChecker: Convert parameters of function type to how they would be called for ``abi.encodeCall``.
* View Pure Checker: Mark ``returndatasize`` and ``returndatacopy`` as view to disallow them in inline assembly blocks in pure functions.

View File

@ -479,6 +479,8 @@ bool SemanticInformation::invalidInPureFunctions(Instruction _instruction)
case Instruction::EXTCODESIZE: case Instruction::EXTCODESIZE:
case Instruction::EXTCODECOPY: case Instruction::EXTCODECOPY:
case Instruction::EXTCODEHASH: case Instruction::EXTCODEHASH:
case Instruction::RETURNDATASIZE:
case Instruction::RETURNDATACOPY:
case Instruction::BLOCKHASH: case Instruction::BLOCKHASH:
case Instruction::COINBASE: case Instruction::COINBASE:
case Instruction::TIMESTAMP: case Instruction::TIMESTAMP:

View File

@ -1,5 +1,5 @@
contract C { contract C {
function f() pure external { function f() view external {
assembly { assembly {
let s := returndatasize() let s := returndatasize()
returndatacopy(0, 0, s) returndatacopy(0, 0, s)

View File

@ -1,5 +1,5 @@
contract C { contract C {
function f() pure external { function f() view external {
assembly { assembly {
let s := returndatasize() let s := returndatasize()
returndatacopy(0, 0, s) returndatacopy(0, 0, s)

View File

@ -1,5 +1,5 @@
contract C { contract C {
function f() public pure { function f() public view {
uint returndatasize; uint returndatasize;
returndatasize; returndatasize;
assembly { assembly {

View File

@ -1,5 +1,5 @@
contract C { contract C {
function f() public pure { function f() public view {
uint returndatasize; uint returndatasize;
returndatasize; returndatasize;
assembly { assembly {

View File

@ -1,4 +1,4 @@
contract C { function f() public pure { uint returndatasize; returndatasize; assembly { pop(returndatasize()) }}} contract C { function f() public view { uint returndatasize; returndatasize; assembly { pop(returndatasize()) }}}
// ==== // ====
// EVMVersion: =homestead // EVMVersion: =homestead
// ---- // ----

View File

@ -0,0 +1,92 @@
contract C {
function f() public {
assembly {
stop()
pop(add(0, 1))
pop(sub(0, 1))
pop(mul(0, 1))
pop(div(0, 1))
pop(sdiv(0, 1))
pop(mod(0, 1))
pop(smod(0, 1))
pop(exp(0, 1))
pop(not(0))
pop(lt(0, 1))
pop(gt(0, 1))
pop(slt(0, 1))
pop(sgt(0, 1))
pop(eq(0, 1))
pop(iszero(0))
pop(and(0, 1))
pop(or(0, 1))
pop(xor(0, 1))
pop(byte(0, 1))
pop(shl(0, 1))
pop(shr(0, 1))
pop(sar(0, 1))
pop(addmod(0, 1, 2))
pop(mulmod(0, 1, 2))
pop(signextend(0, 1))
pop(keccak256(0, 1))
pop(0)
pop(mload(0))
mstore(0, 1)
mstore8(0, 1)
pop(sload(0))
sstore(0, 1)
pop(gas())
pop(address())
pop(balance(0))
pop(selfbalance())
pop(caller())
pop(callvalue())
pop(calldataload(0))
pop(calldatasize())
calldatacopy(0, 1, 2)
pop(codesize())
codecopy(0, 1, 2)
pop(extcodesize(0))
extcodecopy(0, 1, 2, 3)
pop(returndatasize())
returndatacopy(0, 1, 2)
pop(extcodehash(0))
pop(create(0, 1, 2))
pop(create2(0, 1, 2, 3))
pop(call(0, 1, 2, 3, 4, 5, 6))
pop(callcode(0, 1, 2, 3, 4, 5, 6))
pop(delegatecall(0, 1, 2, 3, 4, 5))
pop(staticcall(0, 1, 2, 3, 4, 5))
return(0, 1)
revert(0, 1)
selfdestruct(0)
invalid()
log0(0, 1)
log1(0, 1, 2)
log2(0, 1, 2, 3)
log3(0, 1, 2, 3, 4)
log4(0, 1, 2, 3, 4, 5)
pop(chainid())
pop(basefee())
pop(origin())
pop(gasprice())
pop(blockhash(0))
pop(coinbase())
pop(timestamp())
pop(number())
pop(difficulty())
pop(gaslimit())
// NOTE: msize() is allowed only with optimizer disabled
//pop(msize())
//pop(pc())
}
}
}
// ====
// EVMVersion: >=london
// ----
// Warning 5740: (89-1716): Unreachable code.
// Warning 5740: (1729-1741): Unreachable code.
// Warning 5740: (1754-1769): Unreachable code.
// Warning 5740: (1782-1791): Unreachable code.
// Warning 5740: (1804-2215): Unreachable code.

View File

@ -0,0 +1,90 @@
contract C {
function f() public pure {
assembly {
stop()
pop(add(0, 1))
pop(sub(0, 1))
pop(mul(0, 1))
pop(div(0, 1))
pop(sdiv(0, 1))
pop(mod(0, 1))
pop(smod(0, 1))
pop(exp(0, 1))
pop(not(0))
pop(lt(0, 1))
pop(gt(0, 1))
pop(slt(0, 1))
pop(sgt(0, 1))
pop(eq(0, 1))
pop(iszero(0))
pop(and(0, 1))
pop(or(0, 1))
pop(xor(0, 1))
pop(byte(0, 1))
pop(shl(0, 1))
pop(shr(0, 1))
pop(sar(0, 1))
pop(addmod(0, 1, 2))
pop(mulmod(0, 1, 2))
pop(signextend(0, 1))
pop(keccak256(0, 1))
pop(0)
pop(mload(0))
mstore(0, 1)
mstore8(0, 1)
//pop(sload(0))
//sstore(0, 1)
//pop(gas())
//pop(address())
//pop(balance(0))
//pop(selfbalance())
//pop(caller())
//pop(callvalue())
pop(calldataload(0))
pop(calldatasize())
calldatacopy(0, 1, 2)
pop(codesize())
codecopy(0, 1, 2)
//pop(extcodesize(0))
//extcodecopy(0, 1, 2, 3)
//pop(returndatasize())
//returndatacopy(0, 1, 2)
//pop(extcodehash(0))
//pop(create(0, 1, 2))
//pop(create2(0, 1, 2, 3))
//pop(call(0, 1, 2, 3, 4, 5, 6))
//pop(callcode(0, 1, 2, 3, 4, 5, 6))
//pop(delegatecall(0, 1, 2, 3, 4, 5))
//pop(staticcall(0, 1, 2, 3, 4, 5))
return(0, 1)
revert(0, 1)
//selfdestruct(0)
invalid()
//log0(0, 1)
//log1(0, 1, 2)
//log2(0, 1, 2, 3)
//log3(0, 1, 2, 3, 4)
//log4(0, 1, 2, 3, 4, 5)
//pop(chainid())
//pop(basefee())
//pop(origin())
//pop(gasprice())
//pop(blockhash(0))
//pop(coinbase())
//pop(timestamp())
//pop(number())
//pop(difficulty())
//pop(gaslimit())
// NOTE: msize() is allowed only with optimizer disabled
//pop(msize())
//pop(pc())
}
}
}
// ====
// EVMVersion: >=london
// ----
// Warning 5740: (94-1759): Unreachable code.
// Warning 5740: (1772-1784): Unreachable code.
// Warning 5740: (1827-1836): Unreachable code.

View File

@ -0,0 +1,91 @@
contract C {
function f() public view {
assembly {
stop()
pop(add(0, 1))
pop(sub(0, 1))
pop(mul(0, 1))
pop(div(0, 1))
pop(sdiv(0, 1))
pop(mod(0, 1))
pop(smod(0, 1))
pop(exp(0, 1))
pop(not(0))
pop(lt(0, 1))
pop(gt(0, 1))
pop(slt(0, 1))
pop(sgt(0, 1))
pop(eq(0, 1))
pop(iszero(0))
pop(and(0, 1))
pop(or(0, 1))
pop(xor(0, 1))
pop(byte(0, 1))
pop(shl(0, 1))
pop(shr(0, 1))
pop(sar(0, 1))
pop(addmod(0, 1, 2))
pop(mulmod(0, 1, 2))
pop(signextend(0, 1))
pop(keccak256(0, 1))
pop(0)
pop(mload(0))
mstore(0, 1)
mstore8(0, 1)
pop(sload(0))
//sstore(0, 1)
pop(gas())
pop(address())
pop(balance(0))
pop(selfbalance())
pop(caller())
pop(callvalue())
pop(calldataload(0))
pop(calldatasize())
calldatacopy(0, 1, 2)
pop(codesize())
codecopy(0, 1, 2)
pop(extcodesize(0))
extcodecopy(0, 1, 2, 3)
pop(returndatasize())
returndatacopy(0, 1, 2)
pop(extcodehash(0))
//pop(create(0, 1, 2))
//pop(create2(0, 1, 2, 3))
//pop(call(0, 1, 2, 3, 4, 5, 6))
//pop(callcode(0, 1, 2, 3, 4, 5, 6))
//pop(delegatecall(0, 1, 2, 3, 4, 5))
pop(staticcall(0, 1, 2, 3, 4, 5))
return(0, 1)
revert(0, 1)
//selfdestruct(0)
invalid()
//log0(0, 1)
//log1(0, 1, 2)
//log2(0, 1, 2, 3)
//log3(0, 1, 2, 3, 4)
//log4(0, 1, 2, 3, 4, 5)
pop(chainid())
pop(basefee())
pop(origin())
pop(gasprice())
pop(blockhash(0))
pop(coinbase())
pop(timestamp())
pop(number())
pop(difficulty())
pop(gaslimit())
// NOTE: msize() is allowed only with optimizer disabled
//pop(msize())
//pop(pc())
}
}
}
// ====
// EVMVersion: >=london
// ----
// Warning 5740: (94-1733): Unreachable code.
// Warning 5740: (1746-1758): Unreachable code.
// Warning 5740: (1801-1810): Unreachable code.
// Warning 5740: (1978-2244): Unreachable code.

View File

@ -0,0 +1,28 @@
contract C {
function f() public {
assembly {
datasize(0)
dataoffset(0)
datacopy(0, 1, 2)
setimmutable(0, "x", 1)
loadimmutable("x")
linkersymbol("x")
memoryguard(0)
verbatim_1i_1o(hex"600202", 0)
pop(msize())
pop(pc())
}
}
}
// ----
// SyntaxError 6553: (47-362): The msize instruction cannot be used when the Yul optimizer is activated because it can change its semantics. Either disable the Yul optimizer or do not use the instruction.
// DeclarationError 4619: (70-78): Function "datasize" not found.
// DeclarationError 4619: (94-104): Function "dataoffset" not found.
// DeclarationError 4619: (120-128): Function "datacopy" not found.
// DeclarationError 4619: (150-162): Function "setimmutable" not found.
// DeclarationError 4619: (186-199): Function "loadimmutable" not found.
// DeclarationError 4619: (217-229): Function "linkersymbol" not found.
// DeclarationError 4619: (247-258): Function "memoryguard" not found.
// DeclarationError 4619: (274-288): Function "verbatim_1i_1o" not found.
// SyntaxError 2450: (347-349): PC instruction is a low-level EVM feature. Because of that PC is disallowed in strict assembly.

View File

@ -0,0 +1,84 @@
contract C {
function f() public pure {
assembly {
pop(sload(0))
sstore(0, 1)
pop(gas())
pop(address())
pop(balance(0))
pop(selfbalance())
pop(caller())
pop(callvalue())
pop(extcodesize(0))
extcodecopy(0, 1, 2, 3)
pop(returndatasize())
returndatacopy(0, 1, 2)
pop(extcodehash(0))
pop(create(0, 1, 2))
pop(create2(0, 1, 2, 3))
pop(call(0, 1, 2, 3, 4, 5, 6))
pop(callcode(0, 1, 2, 3, 4, 5, 6))
pop(delegatecall(0, 1, 2, 3, 4, 5))
pop(staticcall(0, 1, 2, 3, 4, 5))
selfdestruct(0)
log0(0, 1)
log1(0, 1, 2)
log2(0, 1, 2, 3)
log3(0, 1, 2, 3, 4)
log4(0, 1, 2, 3, 4, 5)
pop(chainid())
pop(basefee())
pop(origin())
pop(gasprice())
pop(blockhash(0))
pop(coinbase())
pop(timestamp())
pop(number())
pop(difficulty())
pop(gaslimit())
// These two are disallowed too but the error suppresses other errors.
//pop(msize())
//pop(pc())
}
}
}
// ====
// EVMVersion: >=london
// ----
// Warning 5740: (742-1153): Unreachable code.
// TypeError 2527: (79-87): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 8961: (101-113): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 2527: (130-135): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (153-162): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (180-190): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (208-221): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (239-247): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (265-276): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (294-308): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (322-345): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (362-378): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (392-415): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (432-446): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 8961: (464-479): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (497-516): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (534-559): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (577-606): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (624-654): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 2527: (672-700): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 8961: (714-729): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (742-752): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (765-778): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (791-807): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (820-839): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 8961: (852-874): Function cannot be declared as pure because this expression (potentially) modifies the state.
// TypeError 2527: (891-900): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (918-927): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (945-953): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (971-981): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (999-1011): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (1029-1039): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (1057-1068): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (1086-1094): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (1112-1124): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (1142-1152): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".

View File

@ -0,0 +1,38 @@
contract C {
function f() public view {
assembly {
sstore(0, 1)
pop(create(0, 1, 2))
pop(create2(0, 1, 2, 3))
pop(call(0, 1, 2, 3, 4, 5, 6))
pop(callcode(0, 1, 2, 3, 4, 5, 6))
pop(delegatecall(0, 1, 2, 3, 4, 5))
selfdestruct(0)
log0(0, 1)
log1(0, 1, 2)
log2(0, 1, 2, 3)
log3(0, 1, 2, 3, 4)
log4(0, 1, 2, 3, 4, 5)
// These two are disallowed too but the error suppresses other errors.
//pop(msize())
//pop(pc())
}
}
}
// ====
// EVMVersion: >=london
// ----
// Warning 5740: (336-468): Unreachable code.
// TypeError 8961: (75-87): Function cannot be declared as view because this expression (potentially) modifies the state.
// TypeError 8961: (104-119): Function cannot be declared as view because this expression (potentially) modifies the state.
// TypeError 8961: (137-156): Function cannot be declared as view because this expression (potentially) modifies the state.
// TypeError 8961: (174-199): Function cannot be declared as view because this expression (potentially) modifies the state.
// TypeError 8961: (217-246): Function cannot be declared as view because this expression (potentially) modifies the state.
// TypeError 8961: (264-294): Function cannot be declared as view because this expression (potentially) modifies the state.
// TypeError 8961: (308-323): Function cannot be declared as view because this expression (potentially) modifies the state.
// TypeError 8961: (336-346): Function cannot be declared as view because this expression (potentially) modifies the state.
// TypeError 8961: (359-372): Function cannot be declared as view because this expression (potentially) modifies the state.
// TypeError 8961: (385-401): Function cannot be declared as view because this expression (potentially) modifies the state.
// TypeError 8961: (414-433): Function cannot be declared as view because this expression (potentially) modifies the state.
// TypeError 8961: (446-468): Function cannot be declared as view because this expression (potentially) modifies the state.