Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.
Sign upInsufficient zero-padding bug for functions returning byte arrays of size < 16 #1563
Labels
Comments
This comment has been minimized.
This comment has been minimized.
To quickly reproduce the buggy behavior:
Also see: ethereum/eth2.0-specs#1341 |
This comment has been minimized.
This comment has been minimized.
Thanks for the heads up. I'll try and figure this out. |
Merged
Merged
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Version Information
vyper --version
): 0.1.0b11+commit.c775cda (the latest master)What's your issue about?
Summary:
A function whose return type is
bytes[n]
wheren < 16
, returns a value that does not conform to the ABI encoding, having incorrect zero-padding.Details:
For example, the
get_deposit_count
function of the deposit contract, whose return type isbytes[8]
, returns the following 96 bytes (in hexadecimal notation):where the first 32 bytes (the first line) denotes the header (the offset 32 = 0x20), the second 32 bytes (the second line) denotes the length of the byte array (8), and the "
deadbeefdeadbeef
" denotes the content of the byte array (bytes[8]
). Here, the problem is that the last byte is 32 (= 0x20) while it should be 0 (= 0x00) according to the ABI specification. This means that any contract (written in either Solidity or Vyper) that calls to this type of functions expecting the correct zero-padding may misbehave.What happens is that the compiled bytecode of
get_deposit_count
fails to sufficiently pad zeros when it prepares for the return value. In the following return statement,it first copies the returned value (of 8 bytes) to some specific region of the memory, and puts only 8 bytes of zero-padding after that, instead of 24 bytes of zeros, which results in including some garbage values in the last 16 bytes. Indeed, in this particular case, the last 16 bytes (
000000000000000000000000020
) came from the side-effect of the sub-function call toself.to_little_endian_64()
.To be more specific, in the following zero-padding LLL code of
get_deposit_count
(generated by thezero_pad
function ofvyper/parser/stmt.py
):the third argument of the
repeat
loop is 8, where it should be at least 24. In a quick examination of the Vyper compiler code, it seems that the number8
comes from themaxlen
of the typebytes[8]
, but I couldn't have a chance to further investigate the root cause and a quick fix.Indeed, the same problem happens in the
to_little_endian_64
function as well, which has less effect because it is a private function, though.[This bug was privately reported on July 22, 2019, confirmed as not a security vulnerability, and made public here for the transparency.]