CVE-2023-42443: Vyper vulnerable to memory corruption in certain builtins utilizing `msize`

Published Sep 18, 2023
·
Updated

Impact In certain conditions, the memory used by the builtins rawcall, createfromblueprint and createcopyof can be corrupted.

- For rawcall, the argument buffer of the call can be corrupted, leading to incorrect calldata in the sub-context. - For createfromblueprint and createcopyof, the buffer for the to-be-deployed bytecode can be corrupted, leading to deploying incorrect bytecode.

Below are the conditions that must be fulfilled for the corruption to happen for each builtin:

rawcall - memory is not fully initialized, ex. all parameters to an external function live in calldata and - The data argument of the builtin is msg.data. and - The to, value or gas passed to the builtin is some complex expression that results in writing to uninitialized memory (e.g. calling an internal function)

createcopyof - memory is not fully initialized, ex. all parameters to an external function live in calldata and - The value or salt passed to the builtin is some complex expression that results in writing to uninitialized memory (e.g. calling an internal function)

createfromblueprint - memory is not fully initialized, ex. all parameters to an external function live in calldata and - Either no constructor parameters are passed to the builtin or rawargs is set to True. and - The value or salt passed to the builtin is some complex expression that results in writing to uninitialized memory (e.g. calling an internal function)

Note: When the builtin is being called from an internal function f from a function g, the issue is not present provided that g has written to memory before calling f. Examples

rawcall

In the following contract, calling bar(1,1) will return:

Python ae42e95100000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000001 instead of: Python ae42e95100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001

Python identity: constant(address) = 0x0000000000000000000000000000000000000004

@external def foo(): pass

@internal @view def getaddress()->address: a:uint256 = maxvalue(uint256) # 0xfff...fff return identity @external def bar(f:uint256, u:uint256) -> Bytes[100]: a: Bytes[100] = rawcall(self.getaddress(), msg.data, maxoutsize=100) return a

createcopyof In the following contract, after calling test(), the code deployed at self.createdaddress does not match the bytecode at target.

Vyper createdaddress: public(address)

@external def test(target: address) -> address: # The expression in salt= is complex and will require to store to memory self.createdaddress = createcopyof(target, salt = keccak256(abiencode(target))) return self.createdaddress

createfromblueprint In the following contract, after calling test(), the init bytecode used to create the contract deployed at the address self.createdaddress will not match the blueprint bytecode stored at target.

Vyper createdaddress: public(address)

salt: constant(bytes32) = keccak256("kebab")

@external @payable def test(target: address): # The expression in salt= is complex and will require to store to memory self.createdaddress = createfromblueprint(target, codeoffset=0, salt=keccak256(abiencode(target))) Patches issue tracking in https://github.com/vyperlang/vyper/issues/3609, patched in #3610

Workarounds

The complex expressions that are being passed as kwargs to the builtin should be cached in memory prior to the call to the builtin. For the last example above, it would be:

Vyper createdaddress: public(address)

salt: constant(bytes32) = keccak256("kebab")

@external @payable def test(target: address): salt: bytes32 = keccak256(abiencode(target)) self.createdaddress = createfromblueprint(target, codeoffset=0, salt=salt) References Are there any links users can visit to find out more?

Other sources

Vyper is a Pythonic Smart Contract Language for the Ethereum Virtual Machine (EVM). In version 0.3.9 and prior, under certain conditions, the memory used by the builtins rawcall, createfromblueprint and createcopyof can be corrupted. For rawcall, the argument buffer of the call can be corrupted, leading to incorrect calldata in the sub-context. For createfromblueprint and createcopyof, the buffer for the to-be-deployed bytecode can be corrupted, leading to deploying incorrect bytecode.

Each builtin has conditions that must be fulfilled for the corruption to happen. For rawcall, the data argument of the builtin must be msg.data and the value or gas passed to the builtin must be some complex expression that results in writing to the memory. For createcopyof, the value or salt passed to the builtin must be some complex expression that results in writing to the memory. For createfromblueprint, either no constructor parameters should be passed to the builtin or rawargs should be set to True, and the value or salt passed to the builtin must be some complex expression that results in writing to the memory.

As of time of publication, no patched version exists. The issue is still being investigated, and there might be other cases where the corruption might happen. When the builtin is being called from an internal function F, the issue is not present provided that the function calling F wrote to memory before calling F. As a workaround, the complex expressions that are being passed as kwargs to the builtin should be cached in memory prior to the call to the builtin.

— MITRE

Affected Software

2 affected componentsFixes available
pip/vyper>=0.3.4<=0.3.9
0.3.10
vyperlang Vyper Python<0.3.10

Event History

Sep 18, 2023
CVE Published
via MITRE·08:52 PM
Data Sourced
via MITRE·08:52 PM
DescriptionSeverityWeakness
Sep 20, 2023
Advisory Published
11:05 PM

Frequently Asked Questions

1

What is CVE-2023-42443?

CVE-2023-42443 is a vulnerability in Vyper, a Pythonic smart contract language for the Ethereum Virtual Machine (EVM).

2

What is the impact of CVE-2023-42443?

CVE-2023-42443 can lead to memory corruption in Vyper's builtins, potentially resulting in incorrect calldata in certain contexts.

3

How does CVE-2023-42443 affect Vyper?

CVE-2023-42443 affects Vyper version 0.3.9 and possibly earlier versions.

4

What is the severity rating of CVE-2023-42443?

CVE-2023-42443 has a severity rating of 8.1 (high).

5

How can I fix CVE-2023-42443?

To fix CVE-2023-42443, update Vyper to a version that is not affected by the vulnerability.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203