Join GitHub today
GitHub is home to over 50 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
Comments
|
To quickly reproduce the buggy behavior:
Also see: ethereum/eth2.0-specs#1341 |
|
Thanks for the heads up. I'll try and figure this out. |
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_countfunction 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_countfails 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_padfunction ofvyper/parser/stmt.py):the third argument of the
repeatloop is 8, where it should be at least 24. In a quick examination of the Vyper compiler code, it seems that the number8comes from themaxlenof 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_64function 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.]