mirror of https://github.com/crytic/slither
fix: resolve state variable access in inherited internal functions from derived contracts, closes #1654
parent
1eaec647e5
commit
e11580f188
@ -0,0 +1,18 @@ |
||||
contract YYY { |
||||
mapping(address => uint256) private _counters; |
||||
function _getPackedBucketGlobalState(uint256 bucketId) internal view returns (uint256 packedGlobalState) { |
||||
assembly { |
||||
mstore(0x0, bucketId) |
||||
mstore(0x20, _counters.slot) |
||||
let slot := keccak256(0x0, 0x40) |
||||
packedGlobalState := sload(slot) |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
contract XXX is YYY { |
||||
function getPackedBucketGlobalState(uint256 bucketId) external { |
||||
_getPackedBucketGlobalState(bucketId); |
||||
} |
||||
} |
@ -0,0 +1,39 @@ |
||||
from pathlib import Path |
||||
from slither import Slither |
||||
|
||||
from slither.core.expressions import CallExpression |
||||
from slither.core.expressions.identifier import Identifier |
||||
from slither.core.expressions.literal import Literal |
||||
from slither.core.variables.state_variable import StateVariable |
||||
from slither.core.variables.local_variable import LocalVariable |
||||
|
||||
|
||||
TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" |
||||
|
||||
|
||||
def test_yul_parser_assembly_slot(solc_binary_path) -> None: |
||||
# mstore(0x0, bucketId) |
||||
# mstore(0x20, _counters.slot) |
||||
data = { |
||||
'0x0': 'bucketId', |
||||
'0x20': '_counters' |
||||
} |
||||
|
||||
solc_path = solc_binary_path("0.8.18") |
||||
slither = Slither(Path(TEST_DATA_DIR, "assembly_storage_slot.sol").as_posix(), solc=solc_path) |
||||
|
||||
contract = slither.get_contract_from_name('XXX')[0] |
||||
func = contract.get_function_from_full_name('getPackedBucketGlobalState(uint256)') |
||||
calls = [node.expression for node in func.all_nodes() if node.expression and 'mstore' in str(node.expression)] |
||||
|
||||
for call in calls: |
||||
assert isinstance(call, CallExpression) |
||||
memory_location = call.arguments[0] |
||||
value = call.arguments[1] |
||||
assert isinstance(memory_location, Literal) |
||||
assert isinstance(value, Identifier) |
||||
assert value.value.name == data[memory_location.value] |
||||
if value.value.name == '_counters': |
||||
assert isinstance(value.value, StateVariable) |
||||
elif value.value.name == 'bucketId': |
||||
assert isinstance(value.value, LocalVariable) |
Loading…
Reference in new issue