diff --git a/tests/parser/functions/test_ecrecover.py b/tests/parser/functions/test_ecrecover.py index 40c9a6a936..8571948c3d 100644 --- a/tests/parser/functions/test_ecrecover.py +++ b/tests/parser/functions/test_ecrecover.py @@ -58,3 +58,30 @@ def test_ecrecover(hash: bytes32, v: uint8, r: uint256) -> address: r = 0 # note web3.py decoding of 0x000..00 address is None. assert c.test_ecrecover(hash_, v, r) is None + + +# slightly more subtle example: get_v() stomps memory location 0, +# so this tests that the output buffer stays clean during ecrecover() +# builtin execution. +def test_invalid_signature2(get_contract): + code = """ + +owner: immutable(address) + +@external +def __init__(): + owner = 0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf + +@internal +def get_v() -> uint256: + assert owner == owner # force a dload to write at index 0 of memory + return 21 + +@payable +@external +def test_ecrecover() -> bool: + assert ecrecover(empty(bytes32), self.get_v(), 0, 0) == empty(address) + return True + """ + c = get_contract(code) + assert c.test_ecrecover() is True diff --git a/vyper/builtins/functions.py b/vyper/builtins/functions.py index e8e001306c..d152c7555d 100644 --- a/vyper/builtins/functions.py +++ b/vyper/builtins/functions.py @@ -765,7 +765,7 @@ def infer_arg_types(self, node): @process_inputs def build_IR(self, expr, args, kwargs, context): input_buf = context.new_internal_variable(get_type_for_exact_size(128)) - output_buf = MemoryPositions.FREE_VAR_SPACE + output_buf = context.new_internal_variable(get_type_for_exact_size(32)) return IRnode.from_list( [ "seq",