Created
May 17, 2020 13:39
-
-
Save loredanacirstea/cf38ace41b609b629293070cbc172216 to your computer and use it in GitHub Desktop.
yulToEwasm - div with calldata argument bug
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
solc --version | |
0.6.8+commit.0bbfe453.Darwin.appleclang | |
solc --strict-assembly --optimize --yul-dialect evm --machine ewasm ./tests/contracts/taylor.yul | |
-> const wmodule = new WebAssembly.Module(hexToUint8Array(bytecode)); | |
CompileError: WebAssembly.Module(): Compiling function #9 failed: expected 1 elements on the stack for return, found 0 @+987 | |
======= ./tests/contracts/taylor.yul - initial source ======= | |
object "TestContract" { | |
code { | |
datacopy(0, dataoffset("Runtime"), datasize("Runtime")) | |
return(0, datasize("Runtime")) | |
} | |
object "Runtime" { | |
code { | |
let _calldata := 256 | |
calldatacopy(_calldata, 0, calldatasize()) | |
mstore(0, div(mload(_calldata), 10)) | |
return (0, 32) | |
} | |
} | |
} | |
======= ./tests/contracts/taylor.yul (Ewasm) ======= | |
Pretty printed source: | |
object "TestContract" { | |
code { | |
{ | |
let _1 := datasize("Runtime") | |
datacopy(0, dataoffset("Runtime"), _1) | |
return(0, _1) | |
} | |
} | |
object "Runtime" { | |
code { | |
{ | |
let _1 := 256 | |
calldatacopy(_1, 0, calldatasize()) | |
mstore(0, div(mload(_1), 10)) | |
return(0, 32) | |
} | |
} | |
} | |
} | |
========================== | |
Translated source: | |
object "TestContract" { | |
code { | |
function main() | |
{ | |
let _1 := datasize("Runtime") | |
let _2 := 0 | |
let _3:i32 := u256_to_i32(_2, _2, _2, _1) | |
let _4:i32 := u256_to_i32(_2, _2, _2, dataoffset("Runtime")) | |
let p:i32 := u256_to_i32(_2, _2, _2, _2) | |
let r:i32 := i32.add(p, 64:i32) | |
if i32.lt_u(r, p) { unreachable() } | |
eth.codeCopy(r, _4, _3) | |
let _5:i32 := u256_to_i32(_2, _2, _2, _1) | |
let p_1:i32 := u256_to_i32(_2, _2, _2, _2) | |
let r_1:i32 := i32.add(p_1, 64:i32) | |
if i32.lt_u(r_1, p_1) { unreachable() } | |
eth.finish(r_1, _5) | |
} | |
function u256_to_i32(x1, x2, x3, x4) -> v:i32 | |
{ | |
if i64.ne(0, i64.or(i64.or(x1, x2), x3)) { unreachable() } | |
if i64.ne(0, i64.shr_u(x4, 32)) { unreachable() } | |
v := i32.wrap_i64(x4) | |
} | |
} | |
object "Runtime" { | |
code { | |
function main() | |
{ | |
let _1 := i64.extend_i32_u(eth.getCallDataSize()) | |
let _2 := 0 | |
let _3:i32 := u256_to_i32(_2, _2, _2, _1) | |
let _4:i32 := u256_to_i32(_2, _2, _2, _2) | |
let _5 := 256 | |
let p:i32 := u256_to_i32(_2, _2, _2, _5) | |
let r:i32 := i32.add(p, 64:i32) | |
if i32.lt_u(r, p) { unreachable() } | |
eth.callDataCopy(r, _4, _3) | |
let p_1:i32 := u256_to_i32(_2, _2, _2, _5) | |
let r_1:i32 := i32.add(p_1, 64:i32) | |
if i32.lt_u(r_1, p_1) { unreachable() } | |
let z1 := endian_swap(i64.load(r_1)) | |
let z2 := endian_swap(i64.load(i32.add(r_1, 8:i32))) | |
let z3 := endian_swap(i64.load(i32.add(r_1, 16:i32))) | |
let _6, _7, _8, _9 := div(z1, z2, z3, endian_swap(i64.load(i32.add(r_1, 24:i32))), _2, _2, _2, 10) | |
let _10:i32 := to_internal_i32ptr(_2, _2, _2, _2) | |
i64.store(_10, endian_swap(_6)) | |
i64.store(i32.add(_10, 8:i32), endian_swap(_7)) | |
i64.store(i32.add(_10, 16:i32), endian_swap(_8)) | |
i64.store(i32.add(_10, 24:i32), endian_swap(_9)) | |
return(_2, _2, _2, _2, _2, _2, _2, 32) | |
} | |
function add_carry(x, y, c) -> r, r_c | |
{ | |
let t := i64.add(x, y) | |
r := i64.add(t, c) | |
r_c := i64.extend_i32_u(i32.or(i64.lt_u(t, x), i64.lt_u(r, t))) | |
} | |
function add(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 | |
{ | |
let t := i64.add(x4, y4) | |
r4 := i64.add(t, 0) | |
let r3_1, carry := add_carry(x3, y3, i64.extend_i32_u(i32.or(i64.lt_u(t, x4), i64.lt_u(r4, t)))) | |
r3 := r3_1 | |
let r2_1, carry_1 := add_carry(x2, y2, carry) | |
r2 := r2_1 | |
let r1_1, carry_2 := add_carry(x1, y1, carry_1) | |
r1 := r1_1 | |
} | |
function sub(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 | |
{ | |
let _1 := 0xffffffffffffffff | |
let t := i64.add(x4, i64.xor(y4, _1)) | |
r4 := i64.add(t, 1) | |
let r3_1, carry := add_carry(x3, i64.xor(y3, _1), i64.extend_i32_u(i32.or(i64.lt_u(t, x4), i64.lt_u(r4, t)))) | |
r3 := r3_1 | |
let r2_1, carry_1 := add_carry(x2, i64.xor(y2, _1), carry) | |
r2 := r2_1 | |
let r1_1, carry_2 := add_carry(x1, i64.xor(y1, _1), carry_1) | |
r1 := r1_1 | |
} | |
function shl_internal(amount, x1, x2, x3, x4) -> r1, r2, r3, r4 | |
{ | |
let _1 := i64.sub(64, amount) | |
r1 := i64.add(i64.shl(x1, amount), i64.shr_u(x2, _1)) | |
r2 := i64.add(i64.shl(x2, amount), i64.shr_u(x3, _1)) | |
r3 := i64.add(i64.shl(x3, amount), i64.shr_u(x4, _1)) | |
r4 := i64.shl(x4, amount) | |
} | |
function shr_internal(amount, x1, x2, x3, x4) -> r1, r2, r3, r4 | |
{ | |
let _1 := i64.sub(64, amount) | |
r4 := i64.add(i64.shr_u(x4, amount), i64.shl(x3, _1)) | |
r3 := i64.add(i64.shr_u(x3, amount), i64.shl(x2, _1)) | |
r2 := i64.add(i64.shr_u(x2, amount), i64.shl(x1, _1)) | |
r1 := i64.shr_u(x1, amount) | |
} | |
function div(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 | |
{ | |
if i64.eqz(i64.or(i64.or(y1, y2), i64.or(y3, y4))) { leave } | |
let m1 := 0 | |
let m2 := m1 | |
let m3 := m1 | |
let m4 := 1 | |
for { } true { } | |
{ | |
if i32.or(i64.eqz(i64.clz(y1)), i32.eqz(lt_256x256_64(y1, y2, y3, y4, x1, x2, x3, x4))) { break } | |
let y1_1, y2_1, y3_1, y4_1 := shl_internal(1, y1, y2, y3, y4) | |
y1 := y1_1 | |
y2 := y2_1 | |
y3 := y3_1 | |
y4 := y4_1 | |
let m1_1, m2_1, m3_1, m4_1 := shl_internal(1, m1, m2, m3, m4) | |
m1 := m1_1 | |
m2 := m2_1 | |
m3 := m3_1 | |
m4 := m4_1 | |
} | |
for { } | |
i32.eqz(i64.eqz(i64.or(i64.or(m1, m2), i64.or(m3, m4)))) | |
{ } | |
{ | |
if i32.eqz(lt_256x256_64(x1, x2, x3, x4, y1, y2, y3, y4)) | |
{ | |
let x1_1, x2_1, x3_1, x4_1 := sub(x1, x2, x3, x4, y1, y2, y3, y4) | |
x1 := x1_1 | |
x2 := x2_1 | |
x3 := x3_1 | |
x4 := x4_1 | |
let r1_1, r2_1, r3_1, r4_1 := add(r1, r2, r3, r4, m1, m2, m3, m4) | |
r1 := r1_1 | |
r2 := r2_1 | |
r3 := r3_1 | |
r4 := r4_1 | |
} | |
let y1_2, y2_2, y3_2, y4_2 := shr_internal(1, y1, y2, y3, y4) | |
y1 := y1_2 | |
y2 := y2_2 | |
y3 := y3_2 | |
y4 := y4_2 | |
let m1_2, m2_2, m3_2, m4_2 := shr_internal(1, m1, m2, m3, m4) | |
m1 := m1_2 | |
m2 := m2_2 | |
m3 := m3_2 | |
m4 := m4_2 | |
} | |
} | |
function cmp(a, b) -> r:i32 | |
{ | |
switch i64.lt_u(a, b) | |
case 1:i32 { r := 0xffffffff:i32 } | |
default { r := i64.ne(a, b) } | |
} | |
function lt_256x256_64(x1, x2, x3, x4, y1, y2, y3, y4) -> z:i32 | |
{ | |
switch cmp(x1, y1) | |
case 0:i32 { | |
switch cmp(x2, y2) | |
case 0:i32 { | |
switch cmp(x3, y3) | |
case 0:i32 { z := i64.lt_u(x4, y4) } | |
case 1:i32 { z := 0:i32 } | |
default { z := 1:i32 } | |
} | |
case 1:i32 { z := 0:i32 } | |
default { z := 1:i32 } | |
} | |
case 1:i32 { z := 0:i32 } | |
default { z := 1:i32 } | |
} | |
function u256_to_i32(x1, x2, x3, x4) -> v:i32 | |
{ | |
if i64.ne(0, i64.or(i64.or(x1, x2), x3)) { unreachable() } | |
if i64.ne(0, i64.shr_u(x4, 32)) { unreachable() } | |
v := i32.wrap_i64(x4) | |
} | |
function to_internal_i32ptr(x1, x2, x3, x4) -> r:i32 | |
{ | |
let p:i32 := u256_to_i32(x1, x2, x3, x4) | |
r := i32.add(p, 64:i32) | |
if i32.lt_u(r, p) { unreachable() } | |
} | |
function endian_swap_16(x) -> y | |
{ | |
y := i64.or(i64.and(i64.shl(x, 8), 0xff00), i64.and(i64.shr_u(x, 8), 0xff)) | |
} | |
function endian_swap_32(x) -> y | |
{ | |
let hi := i64.shl(endian_swap_16(x), 16) | |
y := i64.or(hi, endian_swap_16(i64.shr_u(x, 16))) | |
} | |
function endian_swap(x) -> y | |
{ | |
let hi := i64.shl(endian_swap_32(x), 32) | |
y := i64.or(hi, endian_swap_32(i64.shr_u(x, 32))) | |
} | |
function return(x1, x2, x3, x4, y1, y2, y3, y4) | |
{ | |
eth.finish(to_internal_i32ptr(x1, x2, x3, x4), u256_to_i32(y1, y2, y3, y4)) | |
} | |
} | |
} | |
} | |
Binary representation: | |
0061736d0100000001170460000060047e7e7e7e017e60027f7f0060037f7f7f0002270208657468657265756d08636f6465436f7079000308657468657265756d0666696e697368000203030200010503010001060100071102066d656d6f72790200046d61696e000200810e0752756e74696d650061736d01000000014d0b6000006000017f60017e017e60027e7e017e60037e7e7e017e60047e7e7e7e017e60057e7e7e7e7e017e60087e7e7e7e7e7e7e7e0060087e7e7e7e7e7e7e7e017e60027f7f0060037f7f7f0002460308657468657265756d0f67657443616c6c4461746153697a65000108657468657265756d0666696e697368000908657468657265756d0c63616c6c44617461436f7079000a03100f00040808060608030805050202020705030100010610037e0142000b7e0142000b7e0142000b071102066d656d6f72790200046d61696e00030a9b0c0fb40201117e1000ada7ad2100420021012001200120012000100c21022001200120012001100c210342800221042001200120012004100c21052005a742c000a76aad21062006a72005a749ad4200520440000b2006a72003a72002a710022001200120012004100c21072007a742c000a76aad21082008a72007a749ad4200520440000b2008a7290300101021092008a74208a76aada72903001010210a2008a74210a76aada72903001010210b02402009200a200b2008a74218a76aada72903001010200120012001420a1009210c2300210d2301210e2302210f0b2001200120012001100d21102010a7200c10103703002010a74208a76aada7200d10103703002010a74210a76aada7200e10103703002010a74218a76aada7200f10103703002001200120012001200120012001422010110b2c01037e200020017c2105200520027c21032005200054ada72003200554ada772ada7ad21042004240020030b6f010b7e200320077c210c200c42007c210b024020022006200c200354ada7200b200c54ada772ada7ad1004210d2300210e0b200d210a024020012005200e1004210f230021100b200f2109024020002004201010042111230021120b2011210820092400200a2401200b240220080b7f010c7e427f210c20032007200c857c210d200d42017c210b024020022006200c85200d200354ada7200b200d54ada772ada7ad1004210e2300210f0b200e210a024020012005200c85200f10042110230021110b20102109024020002004200c85201110042112230021130b2012210820092400200a2401200b240220080b4801057e42c00020007d2109200120008620022009887c2105200220008620032009887c2106200320008620042009887c21072004200086210820062400200724012008240220050b4801057e42c00020007d2109200420008820032009867c2108200320008820022009867c2107200220008820012009867c21062001200088210520062400200724012008240220050bbb0301207e200420058420062007848450ad42005204400f0b4200210c200c210d200c210e4201210f024003404201500d01024020047950ada720042005200620072000200120022003100ba745ada772ad42005204400c030b024042012004200520062007100721102300211123012112230221130b2010210420112105201221062013210702404201200c200d200e200f100721142300211523012116230221170b2014210c2015210d2016210e2017210f0b0b0b02400340200c200d84200e200f848450ada745ad500d01024020002001200220032004200520062007100ba745ad420052044002402000200120022003200420052006200710062118230021192301211a2302211b0b2018210020192101201a2102201b2103024020082009200a200b200c200d200e200f1005211c2300211d2301211e2302211f0b201c2108201d2109201e210a201f210b0b024042012004200520062007100821202300212123012122230221230b2020210420212105202221062023210702404201200c200d200e200f100821242300212523012126230221270b2024210c2025210d2026210e2027210f0b0b0b20092400200a2401200b240220080b2a01027e02402000200154ad21032003420151044042ffffffff0f2102052000200152ad21020b0b20020b7d01047e024020002004100a210920094200510440024020012005100a210a200a4200510440024020022006100a210b200b42005104402003200754ad210805200b42015104404200210805420121080b0b0b05200a42015104404200210805420121080b0b0b05200942015104404200210805420121080b0b0b20080b2f01017e4200200020018420028452ad4200520440000b4200200342208852ad4200520440000b2003a7ad210420040b2c01027e2000200120022003100c21052005a742c000a76aad21042004a72005a749ad4200520440000b20040b1c01017e20004208864280fe0383200042088842ff018384210120010b1b01027e2000100e421086210220022000421088100e84210120010b1b01027e2000100f422086210220022000422088100f84210120010b1c01007e2000200120022003100da72004200520062007100ca710010b0ac40102910101097e42f90d21004200210120012001200120001003210220012001200142f500100321032001200120012001100321042004a742c000a76aad21052005a72004a749ad4200520440000b2005a72003a72002a710002001200120012000100321062001200120012001100321072007a742c000a76aad21082008a72007a749ad4200520440000b2008a72006a710010b2f01017e4200200020018420028452ad4200520440000b4200200342208852ad4200520440000b2003a7ad210420040b | |
Text representation: | |
(module | |
;; sub-module "Runtime" will be encoded as custom section in binary here, but is skipped in text mode. | |
(import "ethereum" "codeCopy" (func $eth.codeCopy (param i32 i32 i32))) | |
(import "ethereum" "finish" (func $eth.finish (param i32 i32))) | |
(memory $memory (export "memory") 1) | |
(export "main" (func $main)) | |
(func $main | |
(local $_1 i64) | |
(local $_2 i64) | |
(local $_3 i64) | |
(local $_4 i64) | |
(local $p i64) | |
(local $r i64) | |
(local $_5 i64) | |
(local $p_1 i64) | |
(local $r_1 i64) | |
(local.set $_1 (datasize "Runtime")) | |
(local.set $_2 (i64.const 0)) | |
(local.set $_3 (call $u256_to_i32 (local.get $_2) (local.get $_2) (local.get $_2) (local.get $_1))) | |
(local.set $_4 (call $u256_to_i32 (local.get $_2) (local.get $_2) (local.get $_2) (dataoffset "Runtime"))) | |
(local.set $p (call $u256_to_i32 (local.get $_2) (local.get $_2) (local.get $_2) (local.get $_2))) | |
(local.set $r (i64.extend_i32_u (i32.add (i32.wrap_i64 (local.get $p)) (i32.wrap_i64 (i64.const 64))))) | |
(if (i64.ne (i64.extend_i32_u (i32.lt_u (i32.wrap_i64 (local.get $r)) (i32.wrap_i64 (local.get $p)))) (i64.const 0)) (then | |
(unreachable))) | |
(call $eth.codeCopy (i32.wrap_i64 (local.get $r)) (i32.wrap_i64 (local.get $_4)) (i32.wrap_i64 (local.get $_3))) | |
(local.set $_5 (call $u256_to_i32 (local.get $_2) (local.get $_2) (local.get $_2) (local.get $_1))) | |
(local.set $p_1 (call $u256_to_i32 (local.get $_2) (local.get $_2) (local.get $_2) (local.get $_2))) | |
(local.set $r_1 (i64.extend_i32_u (i32.add (i32.wrap_i64 (local.get $p_1)) (i32.wrap_i64 (i64.const 64))))) | |
(if (i64.ne (i64.extend_i32_u (i32.lt_u (i32.wrap_i64 (local.get $r_1)) (i32.wrap_i64 (local.get $p_1)))) (i64.const 0)) (then | |
(unreachable))) | |
(call $eth.finish (i32.wrap_i64 (local.get $r_1)) (i32.wrap_i64 (local.get $_5))) | |
) | |
(func $u256_to_i32 | |
(param $x1 i64) | |
(param $x2 i64) | |
(param $x3 i64) | |
(param $x4 i64) | |
(result i64) | |
(local $v i64) | |
(if (i64.ne (i64.extend_i32_u (i64.ne (i64.const 0) (i64.or (i64.or (local.get $x1) (local.get $x2)) (local.get $x3)))) (i64.const 0)) (then | |
(unreachable))) | |
(if (i64.ne (i64.extend_i32_u (i64.ne (i64.const 0) (i64.shr_u (local.get $x4) (i64.const 32)))) (i64.const 0)) (then | |
(unreachable))) | |
(local.set $v (i64.extend_i32_u (i32.wrap_i64 (local.get $x4)))) | |
(local.get $v) | |
) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment