From 298d28726b0fc708201f0471f214cc2b8d4c2fb4 Mon Sep 17 00:00:00 2001 From: Silur Date: Sun, 14 Jan 2018 18:41:32 +0100 Subject: [PATCH 1/2] Reimplement the translator in C --- .gitignore | 2 + libs/evm2wasm/CMakeLists.txt | 10 + libs/evm2wasm/evm2wasm.cpp | 16 +- libs/evm2wasm/evm2wast.c | 693 +++++++++++++++++++++++++++++++++++ libs/evm2wasm/evm2wast.h | 16 + libs/evm2wasm/gadgets.h | 5 + libs/evm2wasm/gen_gadgets.sh | 55 +++ wasm/SIGNEXTEND.wast | 1 - wasm/bswap_i32.wast | 3 +- wasm/bswap_i64.wast | 3 +- 10 files changed, 794 insertions(+), 10 deletions(-) create mode 100644 libs/evm2wasm/evm2wast.c create mode 100644 libs/evm2wasm/evm2wast.h create mode 100644 libs/evm2wasm/gadgets.h create mode 100755 libs/evm2wasm/gen_gadgets.sh diff --git a/.gitignore b/.gitignore index efc294f2..39034cf6 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ tmp/* !tmp/.gitkeep node_modules/ + +libs/evm2wasm/gadgets.c diff --git a/libs/evm2wasm/CMakeLists.txt b/libs/evm2wasm/CMakeLists.txt index f7c6901c..bc5b31dd 100644 --- a/libs/evm2wasm/CMakeLists.txt +++ b/libs/evm2wasm/CMakeLists.txt @@ -1,9 +1,19 @@ set(include_dir ${PROJECT_SOURCE_DIR}/include) +add_custom_target(gen_gadgets + ${CMAKE_CURRENT_SOURCE_DIR}/gen_gadgets.sh + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + BYPRODUCTS ${CMAKE_CURRENT_SOURCE_DIR}/gadgets.c +) + add_library(libevm2wasm evm2wasm.cpp ${include_dir}/evm2wasm.h + evm2wast.c + gadgets.c ) set_target_properties(libevm2wasm PROPERTIES OUTPUT_NAME evm2wasm) +add_dependencies(libevm2wasm gen_gadgets) + target_include_directories(libevm2wasm PUBLIC ${include_dir}) target_link_libraries(libevm2wasm PRIVATE binaryen::binaryen) \ No newline at end of file diff --git a/libs/evm2wasm/evm2wasm.cpp b/libs/evm2wasm/evm2wasm.cpp index 46ec3984..f9f619ff 100644 --- a/libs/evm2wasm/evm2wasm.cpp +++ b/libs/evm2wasm/evm2wasm.cpp @@ -4,6 +4,8 @@ #include #include +#include "evm2wast.h" + using namespace std; namespace { @@ -48,14 +50,18 @@ string wast2wasm(const string& input, bool debug = false) { return output.str(); } -string evm2wast(const string& input) { - (void)input; - // FIXME: do evm magic here - return "(module (export \"main\" (func $main)) (func $main))"; +string evm2wast_wrapper(const string& input) { + size_t len = 0; + char *output = NULL; + if (evm2wast(const_cast(input.c_str()), input.size(), &output, &len) < 0) + return string(); + string ret(output, output + len); + free(output); + return ret; } } string evm2wasm(const string& input) { - return wast2wasm(evm2wast(input)); + return wast2wasm(evm2wast_wrapper(input), true); } diff --git a/libs/evm2wasm/evm2wast.c b/libs/evm2wasm/evm2wast.c new file mode 100644 index 00000000..bdd70708 --- /dev/null +++ b/libs/evm2wasm/evm2wast.c @@ -0,0 +1,693 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "evm2wast.h" +#include "gadgets.h" + +struct opcode { + char *name; + size_t fee; + int off_stack; + int on_stack; + char *cb; +}; + +enum op_nums { + STOP = 0x00, + ADD, MUL, SUB, DIV, SDIV, MOD, SMOD, + ADDMOD, MULMOD, EXP, SIGNEXTEND, + LT = 0X10, GT, SLT, SGT, EQ, ISZERO, + AND, OR, XOR, NOT, BYTE, + SHA3 = 0X20, + ADDRESS = 0x30, BALANCE, ORIGIN, CALLER, + CALLVALUE, CALLDATALOAD, CALLDATASIZE, + CALLDATACOPY, CODESIZE, CODECOPY, GASPRICE, + EXTCODESIZE, EXTCODECOPY, RETURNDATASIZE, + RETURNDATACOPY, + BLOCKHASH = 0X40, COINBASE, TIMESTAMP, NUMBER, + DIFFICULTY, GASLIMIT, + POP = 0X50, MLOAD, MSTORE, MSTORE8, SLOAD, + SSTORE, JUMP, JUMPI, PC, MSIZE, GAS, JUMPDEST, + PUSH1 = 0X60, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, + PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, + PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, + PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, + PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, + PUSH31, PUSH32, + DUP1 = 0X80, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, + DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, + DUP15, DUP16, SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, + SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, + SWAP12, SWAP13, SWAP14, SWAP15, SWAP16, LOG1, + LOG2, LOG3, LOG4, LOG5, + CREATE = 0xf0, CALL, CALLCODE, RETURN, DELEGATECALL, + STATICCALL, REVERT, + INVALID = 0xfe, SELFDESTRUCT +}; + +struct opcode opcodes[] = { + [STOP] = {"STOP", 0, 0, 0}, + [ADD] = {"ADD", 3, 2, 1}, + [MUL] = {"MUL", 5, 2, 1}, + [SUB] = {"SUB", 3, 2, 1}, + [DIV] = {"DIV", 5, 2, 1}, + [SDIV] = {"SDIV", 5, 2, 1}, + [MOD] = {"MOD", 5, 2, 1}, + [SMOD] = {"SMOD", 5, 2, 1}, + [ADDMOD] = {"ADDMOD", 8, 3, 1}, + [MULMOD] = {"MULMOD", 8, 3, 1}, + [EXP] = {"EXP", 10, 2, 1}, + [SIGNEXTEND] = {"SIGNEXTEND", 5, 2, 1}, + + [LT] = {"LT", 3, 2, 1}, + [GT] = {"GT", 3, 2, 1}, + [SLT] = {"SLT", 3, 2, 1}, + [SGT] = {"SGT", 3, 2, 1}, + [EQ] = {"EQ", 3, 2, 1}, + [ISZERO] = {"ISZERO", 3, 1, 1}, + [AND] = {"AND", 3, 2, 1}, + [OR] = {"OR", 3, 2, 1}, + [XOR] = {"XOR", 3, 2, 1}, + [NOT] = {"NOT", 3, 1, 1}, + [BYTE] = {"BYTE", 3, 2, 1}, + + // 0x20 range - crypto + [SHA3] = {"SHA3", 30, 2, 1}, + + // 0x30 range - closure state + [ADDRESS] = {"ADDRESS", 2, 0, 1}, + [BALANCE] = {"BALANCE", 400, 1, 1, "$callback_128"}, + [ORIGIN] = {"ORIGIN", 2, 0, 1}, + [CALLER] = {"CALLER", 2, 0, 1}, + [CALLVALUE] = {"CALLVALUE", 2, 0, 1}, + [CALLDATALOAD] = {"CALLDATALOAD", 3, 1, 1}, + [CALLDATASIZE] = {"CALLDATASIZE", 2, 0, 1}, + [CALLDATACOPY] = {"CALLDATACOPY", 3, 3, 0}, + [CODESIZE] = {"CODESIZE", 2, 0, 1, "$callback_32"}, + [CODECOPY] = {"CODECOPY", 3, 3, 0, "$callback"}, + [GASPRICE] = {"GASPRICE", 2, 0, 1}, + [EXTCODESIZE] = {"EXTCODESIZE", 700, 1, 1, "$callback_32"}, + [EXTCODECOPY] = {"EXTCODECOPY", 700, 4, 0, "$callback"}, + [RETURNDATASIZE] = {"RETURNDATASIZE", 2, 0, 1}, + [RETURNDATACOPY] = {"RETURNDATACOPY", 3, 3, 0}, + + // '0x40' range - block operations + [BLOCKHASH] = {"BLOCKHASH", 20, 1, 1, "$callback_256"}, + [COINBASE] = {"COINBASE", 2, 0, 1}, + [TIMESTAMP] = {"TIMESTAMP", 2, 0, 1}, + [NUMBER] = {"NUMBER", 2, 0, 1}, + [DIFFICULTY] = {"DIFFICULTY", 2, 0, 1}, + [GASLIMIT] = {"GASLIMIT", 2, 0, 1}, + + // 0x50 range - 'storage' and execution + [POP] = {"POP", 2, 1, 0}, + [MLOAD] = {"MLOAD", 3, 1, 1}, + [MSTORE] = {"MSTORE", 3, 2, 0}, + [MSTORE8] = {"MSTORE8", 3, 2, 0}, + [SLOAD] = {"SLOAD", 200, 1, 1, "$callback_256"}, + [SSTORE] = {"SSTORE", 0, 2, 0, "$callback"}, + [JUMP] = {"JUMP", 8, 1, 0}, + [JUMPI] = {"JUMPI", 10, 2, 0}, + [PC] = {"PC", 2, 0, 1}, + [MSIZE] = {"MSIZE", 2, 0, 1}, + [GAS] = {"GAS", 2, 0, 1}, + [JUMPDEST] = {"JUMPDEST", 1, 0, 0}, + + // 0x60, range + [PUSH1] = {"PUSH", 3, 0, 1}, + [PUSH2] = {"PUSH", 3, 0, 1}, + [PUSH3] = {"PUSH", 3, 0, 1}, + [PUSH4] = {"PUSH", 3, 0, 1}, + [PUSH5] = {"PUSH", 3, 0, 1}, + [PUSH6] = {"PUSH", 3, 0, 1}, + [PUSH7] = {"PUSH", 3, 0, 1}, + [PUSH8] = {"PUSH", 3, 0, 1}, + [PUSH9] = {"PUSH", 3, 0, 1}, + [PUSH10] = {"PUSH", 3, 0, 1}, + [PUSH11] = {"PUSH", 3, 0, 1}, + [PUSH12] = {"PUSH", 3, 0, 1}, + [PUSH13] = {"PUSH", 3, 0, 1}, + [PUSH14] = {"PUSH", 3, 0, 1}, + [PUSH15] = {"PUSH", 3, 0, 1}, + [PUSH16] = {"PUSH", 3, 0, 1}, + [PUSH17] = {"PUSH", 3, 0, 1}, + [PUSH18] = {"PUSH", 3, 0, 1}, + [PUSH19] = {"PUSH", 3, 0, 1}, + [PUSH20] = {"PUSH", 3, 0, 1}, + [PUSH21] = {"PUSH", 3, 0, 1}, + [PUSH22] = {"PUSH", 3, 0, 1}, + [PUSH23] = {"PUSH", 3, 0, 1}, + [PUSH24] = {"PUSH", 3, 0, 1}, + [PUSH25] = {"PUSH", 3, 0, 1}, + [PUSH26] = {"PUSH", 3, 0, 1}, + [PUSH27] = {"PUSH", 3, 0, 1}, + [PUSH28] = {"PUSH", 3, 0, 1}, + [PUSH29] = {"PUSH", 3, 0, 1}, + [PUSH30] = {"PUSH", 3, 0, 1}, + [PUSH31] = {"PUSH", 3, 0, 1}, + [PUSH32] = {"PUSH", 3, 0, 1}, + + [DUP1] = {"DUP", 3, 0, 1}, + [DUP2] = {"DUP", 3, 0, 1}, + [DUP3] = {"DUP", 3, 0, 1}, + [DUP4] = {"DUP", 3, 0, 1}, + [DUP5] = {"DUP", 3, 0, 1}, + [DUP6] = {"DUP", 3, 0, 1}, + [DUP7] = {"DUP", 3, 0, 1}, + [DUP8] = {"DUP", 3, 0, 1}, + [DUP9] = {"DUP", 3, 0, 1}, + [DUP10] = {"DUP", 3, 0, 1}, + [DUP11] = {"DUP", 3, 0, 1}, + [DUP12] = {"DUP", 3, 0, 1}, + [DUP13] = {"DUP", 3, 0, 1}, + [DUP14] = {"DUP", 3, 0, 1}, + [DUP15] = {"DUP", 3, 0, 1}, + [DUP16] = {"DUP", 3, 0, 1}, + + [SWAP1] = {"SWAP", 3, 0, 0}, + [SWAP2] = {"SWAP", 3, 0, 0}, + [SWAP3] = {"SWAP", 3, 0, 0}, + [SWAP4] = {"SWAP", 3, 0, 0}, + [SWAP5] = {"SWAP", 3, 0, 0}, + [SWAP6] = {"SWAP", 3, 0, 0}, + [SWAP7] = {"SWAP", 3, 0, 0}, + [SWAP8] = {"SWAP", 3, 0, 0}, + [SWAP9] = {"SWAP", 3, 0, 0}, + [SWAP10] = {"SWAP", 3, 0, 0}, + [SWAP11] = {"SWAP", 3, 0, 0}, + [SWAP12] = {"SWAP", 3, 0, 0}, + [SWAP13] = {"SWAP", 3, 0, 0}, + [SWAP14] = {"SWAP", 3, 0, 0}, + [SWAP15] = {"SWAP", 3, 0, 0}, + [SWAP16] = {"SWAP", 3, 0, 0}, + + [LOG1] = {"LOG", 375, 2, 0}, + [LOG2] = {"LOG", 375, 2, 0}, + [LOG3] = {"LOG", 375, 2, 0}, + [LOG4] = {"LOG", 375, 2, 0}, + [LOG5] = {"LOG", 375, 2, 0}, + + // '0xf0' range - closures + [CREATE] = {"CREATE", 32000, 3, 1, "$callback_160"}, + [CALL] = {"CALL", 700, 7, 1, "$callback_32"}, + [CALLCODE] = {"CALLCODE", 700, 7, 1, "$callback_32"}, + [RETURN] = {"RETURN", 0, 2, 0}, + [DELEGATECALL] = {"DELEGATECALL", 700, 6, 1, "$callback"}, + [STATICCALL] = {"STATICCALL", 700, 6, 1}, + [REVERT] = {"REVERT", 0, 2, 0}, + + // '0x70', range - other + [INVALID] = {"INVALID", 0, 0, 0}, + [SELFDESTRUCT] = {"SELFDESTRUCT", 5000, 1, 0} +}; + + +static inline int digits(unsigned long x) { return (floor(log10(abs(x))) + 1); } +static void *safe_realloc(void *p, size_t s) +{ + void *ret = realloc(p, s); + if(!ret) + { + perror("allocation error "); + free(p); + return 0; + } + return ret; +} +static int64_t bytes2long(const char *bytes) +{ + int64_t ret = 0; + int i; + for(i = 0; i < 8; i++) + { + ret = (ret << 8) | bytes[i]; + } + return ret; +} +static char *padleft(char *bytes, int curr_len, int len) +{ + if(curr_len > len) + { + fprintf(stderr, "pad failed to prevent memory overlap\n"); + return 0; + } + char *ret = calloc(len, 1); + if(!ret) return 0; + ret = memcpy(ret+(len-curr_len)-1, bytes, curr_len); + + return ret; +} + +/*static char *slice(char *bytes, int len) +{ + char *ret = malloc(sizeof(len)); + ret = memcpy(ret, bytes, len); + return ret; +}*/ + +static int index_of(char **table, char *elem, int len) +{ + int i; + for(i=0; i= PUSH1 && evm_code[i] <= PUSH32) + { + i+=evm_code[i]-0x59; + break; + } + } + return --i; +} +char *build_module(const char *wast) +{ + int i; + size_t gadgets_len = 0; + for(i=0; i stack_high) stack_high = stack_delta; + stack_delta = op.on_stack; + if(stack_delta < stack_low) stack_low = stack_delta; + + switch((unsigned char)evm_code[i]) + { + case JUMP: + has_jump=1; + append_segment("(set_local $jump_dest (call $check_overflow \ + (i64.load (get_global $sp)) \ + (i64.load (i32.add (get_global $sp) (i32.const 8)))\ + (i64.load (i32.add (get_global $sp) (i32.const 16)))\ + (i64.load (i32.add (get_global $sp) (i32.const 24)))))\ + (set_global $sp (i32.sub (get_global $sp) (i32.const 32)))\ + (br $loop)"); + i = next_jump_dest(evm_code, len, i); + break; + + case JUMPI: + has_jump=1; + append_segment("(set_local $jump_dest (call $check_overflow \ + (i64.load (get_global $sp)) \ + (i64.load (i32.add (get_global $sp) (i32.const 8))) \ + (i64.load (i32.add (get_global $sp) (i32.const 16))) \ + (i64.load (i32.add (get_global $sp) (i32.const 24))))) \ + (set_global $sp (i32.sub (get_global $sp) (i32.const 64))) \ + (br_if $loop (i32.eqz (i64.eqz (i64.or \ + (i64.load (i32.add (get_global $sp) (i 32.const 32))) \ + (i64.or \ + (i64.load (i32.add (get_global $sp) (i32.const 40))) \ + (i64.or \ + (i64.load (i32.add (get_global $sp) (i32.const 48))) \ + (i64.load (i32.add (get_global $sp) (i32.const 56))) \ + ) \ + ) \ + ))))"); + add_stack_check(&segment); + add_metering(&wast_code, &segment); + break; + + case JUMPDEST: + end_segment(wast_code, segment); + jumps = realloc(jumps, jumps_len); + jumps[jumps_len++] = i; + gas_count = 1; + break; + + case GAS: + append_segment("(call $GAS)\n"); + add_metering(wast_code, segment); + break; + + case LOG1: + case LOG2: + case LOG3: + case LOG4: + case LOG5: + format_segment("(call $LOG (i32.const %d))", 36, (int)evm_code[i]); + break; + + case DUP1: + case DUP2: + case DUP3: + case DUP4: + case DUP5: + case DUP6: + case DUP7: + case DUP8: + case DUP9: + case DUP10: + case DUP11: + case DUP12: + case DUP13: + case DUP14: + case DUP15: + case DUP16: + case SWAP1: + case SWAP2: + case SWAP3: + case SWAP4: + case SWAP5: + case SWAP6: + case SWAP7: + case SWAP8: + case SWAP9: + case SWAP10: + case SWAP11: + case SWAP12: + case SWAP13: + case SWAP14: + case SWAP15: + case SWAP16: + format_segment("(call $%s (i32.const $%d))\n", 60, + op.name, (int)evm_code[i]); + break; + + case PC: + format_segment("(call $PC (i32.const %ld", 40, i); + break; + + case PUSH1: + case PUSH2: + case PUSH3: + case PUSH4: + case PUSH5: + case PUSH6: + case PUSH7: + case PUSH8: + case PUSH9: + case PUSH10: + case PUSH11: + case PUSH12: + case PUSH13: + case PUSH14: + case PUSH15: + case PUSH16: + case PUSH17: + case PUSH18: + case PUSH19: + case PUSH20: + case PUSH21: + case PUSH22: + case PUSH23: + case PUSH24: + case PUSH25: + case PUSH26: + case PUSH27: + case PUSH28: + case PUSH29: + case PUSH30: + case PUSH31: + case PUSH32: + { + char *bytes = padleft(evm_code+1, evm_code[i]-0x5f, 32); + if(!bytes) goto err; + int bytes_rounded = (evm_code[i-1] + 7) >> 3; + char *push = 0; + int q; + for(q=0; q<4-bytes_rounded; q++) + { + push = realloc(push, (q+1)*32); // FIXME segfault + if(!push) goto err; + sprintf(push, "(i64.const 0)%s", push); + } + for(; q<4; q++) + { + int64_t i64 = bytes2long(slice(bytes+(q*8), q*8+8)); + push = realloc(push, (q+1)*32); + if(!push) goto err; + sprintf(push, "%s (i64.const %ld)", push, i64); + + } + format_segment("(call $PUSH %s)", 13+strlen(push), push); + i+=(size_t)evm_code[i]-0x5f; + free(push); + } + break; + + case POP: + // do nothing + break; + + case STOP: + append_segment("(br $done)"); + if(has_jump) + { + i = next_jump_dest(evm_code, len, i); + } + else + { + i = len; + } + break; + + //case SUICIDE: + case RETURN: + format_segment("(call $%s) (br $done)\n", 56, op.name); + if(has_jump) + { + i = next_jump_dest(evm_code, len, i); + } + else + { + i = len; + } + break; + + case INVALID: + append_segment("(unreachable)"); + i = next_jump_dest(evm_code, len, i); + break; + + default: + if(op.cb != 0) + { + int cb_index = index_of(cb_array, op.name, cb_len); + if(cb_index == -1) + { + cb_array[cb_len++] = op.cb; + } + format_segment("(call $%s (i32.const %d))", 72, op.name, cb_index); + } + format_segment("(call $%s)", 32, op.name); + break; + } + + stack_delta = op.on_stack - op.off_stack; + if(stack_delta != 0) + { + format_segment("(set_global $sp (i32.add (get_global $sp) (i32.const %ld)))\n", + 72, stack_delta); + } + + //TODO stacktrace + if(op.cb != 0) + { + format_segment("(set_global $cb_dest (i32.const %ld)) (br $done))", 72, jumps_len+1); + jumps = realloc(jumps, (jumps_len+1)*sizeof(size_t)); + if(!jumps) goto err; + jumps[jumps_len++] = i; + } + } + end_segment(wast_code, segment); + char *with_jumps = assemble_segments(jumps, jumps_len); + wast_code = realloc(wast_code, strlen(wast_code) + strlen(with_jumps)); + if(wast_code == 0) goto err; + wast_code = strcat(with_jumps, wast_code); + wast_code = strcat(wast_code, "))"); + wast_code = build_module(wast_code); + free(segment); + free(with_jumps); + free(jumps); + *wast_ret = wast_code; + *wast_size = strlen(wast_code); + return 1; +#undef append_segment +err: + // TODO optimize this double-branch + if(segment) free(segment); + if(wast_code) free(wast_code); + //if(with_jumps) free(with_jumps); + if(jumps) free(jumps); + return 0; +} diff --git a/libs/evm2wasm/evm2wast.h b/libs/evm2wasm/evm2wast.h new file mode 100644 index 00000000..93549b65 --- /dev/null +++ b/libs/evm2wasm/evm2wast.h @@ -0,0 +1,16 @@ +#ifndef __EVM2WAST_H +#define __EVM2WAST_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int evm2wast(const char *evm_code, size_t len, char **wast_code, size_t *wast_size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/evm2wasm/gadgets.h b/libs/evm2wasm/gadgets.h new file mode 100644 index 00000000..c4246f24 --- /dev/null +++ b/libs/evm2wasm/gadgets.h @@ -0,0 +1,5 @@ +#ifndef __EVM2WASM_GADGETS_H +#define __EVM2WASM_GADGETS_H +extern int gadget_count; +extern const char *gadgets[]; +#endif diff --git a/libs/evm2wasm/gen_gadgets.sh b/libs/evm2wasm/gen_gadgets.sh new file mode 100755 index 00000000..288fb51a --- /dev/null +++ b/libs/evm2wasm/gen_gadgets.sh @@ -0,0 +1,55 @@ +#!/bin/bash +cstr () { +sed 's/;;.*//g' $1 2>/dev/null | sed '$!s/$/\\n\\/' | sed 's/"/\\"/g' +} +fill () { + for i in {0..$1} + do + echo "\"\"," >> gadgets.c + done +} +#0x00 +opcodes=("STOP" "ADD" "MUL" "SUB" "DIV" "SDIV" "MOD" +"ADDMOD" "MULMOD" "EXP" "SIGNEXTEND" 0 0 0 0 +"LT" "GT" "SLT" "SGT" "EQ" "ISZERO" "AND" "OR" "XOR" +"NOT" "BYTE" 0 0 0 0 0 "SHA3" 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 "ADDRESS" "BALANCE" "ORIGIN" "CALLER" +"CALLVALUE" "CALLDATALOAD" "CALLDATASIZE" +"CALLDATACOPY" "CODESIZE" "CODECOPY" "GASPRICE" +"EXTCODZISE" "EXTCODECOPY" "RETURNDATASIZE" +"RETURNDATACOPY" 0 "BLOCKHASH" "COINBASE" "TIMESTAMP" +"NUMBER" "DIFFICULTY" "GASLIMIT" 0 0 0 0 0 0 0 0 0 0 +"POP" "MLOAD" "MSTORE" "MSTORE8" "SLOAD" "SLOAD" "SSTORE" +"JUMP" "JUMPI" "PC" "MSIZE" "GAS" "JUMPDEST" 0 0 0 0 0 +"SELFDESTRUCT" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +"CALL" "CALLCODE" "RETURN" "DELEGATECALL" "STATICCALL" +"REVERT" 0 0 0 0 0 0 0 "bswap_i32" "bswap_i64" +"bswap_m128" "bswap_m160" "bswap_m256" "callback_128" +"callback_160" "callback_256" "callback_32" "callback" +"check_overflow_i64" "check_overflow" "gte_256" +"gte_320" "gte_512" "iszero_256" "iszero_320" "iszero_512" +"keccak" "memcpy" "memset" "memusegas" "mod_320" +"mod_512" "mul_256") + +cat < gadgets.c +/* This is an autogenerated output by gen_gadgets.sh. DO NOT CHANGE */ +#pragma GCC diagnostic ignored "-Woverlength-strings" +#include "gadgets.h" +EOF +echo "int gadget_count = ${#opcodes[@]};" >> gadgets.c +echo "const char *gadgets[${#opcodes[@]}+1] = {" >> gadgets.c +for i in ${opcodes[@]} +do + if [[ $i == 0 ]] + then + echo "\"\"," >> gadgets.c + continue + fi + echo "\"$(cstr ../../wasm/$i.wast)\"," >> gadgets.c +done +echo "\"\"};" >> gadgets.c +exit 0 diff --git a/wasm/SIGNEXTEND.wast b/wasm/SIGNEXTEND.wast index ca60bc57..0c726e0d 100644 --- a/wasm/SIGNEXTEND.wast +++ b/wasm/SIGNEXTEND.wast @@ -46,4 +46,3 @@ ) ) ) - diff --git a/wasm/bswap_i32.wast b/wasm/bswap_i32.wast index fbaa91fd..c62a5cc8 100644 --- a/wasm/bswap_i32.wast +++ b/wasm/bswap_i32.wast @@ -8,5 +8,4 @@ (i32.and (i32.shr_u (get_local $int) (i32.const 8)) (i32.const 0xff00))) ;; 6 -> 1 (i32.or (i32.and (i32.shl (get_local $int) (i32.const 8)) (i32.const 0xff0000)) ;; 5 -> 2 - (i32.and (i32.shl (get_local $int) (i32.const 24)) (i32.const 0xff000000)))) ;; 4 -> 3 -) + (i32.and (i32.shl (get_local $int) (i32.const 24)) (i32.const 0xff000000))))) ;; 4 -> 3 diff --git a/wasm/bswap_i64.wast b/wasm/bswap_i64.wast index c5a8ab04..0dda2acb 100644 --- a/wasm/bswap_i64.wast +++ b/wasm/bswap_i64.wast @@ -16,5 +16,4 @@ (i64.and (i64.shl (get_local $int) (i64.const 24)) (i64.const 0xff0000000000))) ;; 2 -> 5 (i64.or (i64.and (i64.shl (get_local $int) (i64.const 40)) (i64.const 0xff000000000000)) ;; 1 -> 6 - (i64.and (i64.shl (get_local $int) (i64.const 56)) (i64.const 0xff00000000000000))))) ;; 0 -> 7 -) + (i64.and (i64.shl (get_local $int) (i64.const 56)) (i64.const 0xff00000000000000)))))) ;; 0 -> 7 From ff58adb94bab0af6a6433d8f3ab7fe3bb7079417 Mon Sep 17 00:00:00 2001 From: Silur Date: Sat, 3 Feb 2018 18:52:46 +0100 Subject: [PATCH 2/2] sexpression fixes --- libs/evm2wasm/evm2wast.c | 337 ++++++++++++++++++++------------------- 1 file changed, 170 insertions(+), 167 deletions(-) diff --git a/libs/evm2wasm/evm2wast.c b/libs/evm2wasm/evm2wast.c index bdd70708..38713ae7 100644 --- a/libs/evm2wasm/evm2wast.c +++ b/libs/evm2wasm/evm2wast.c @@ -53,159 +53,159 @@ enum op_nums { }; struct opcode opcodes[] = { - [STOP] = {"STOP", 0, 0, 0}, - [ADD] = {"ADD", 3, 2, 1}, - [MUL] = {"MUL", 5, 2, 1}, - [SUB] = {"SUB", 3, 2, 1}, - [DIV] = {"DIV", 5, 2, 1}, - [SDIV] = {"SDIV", 5, 2, 1}, - [MOD] = {"MOD", 5, 2, 1}, - [SMOD] = {"SMOD", 5, 2, 1}, - [ADDMOD] = {"ADDMOD", 8, 3, 1}, - [MULMOD] = {"MULMOD", 8, 3, 1}, - [EXP] = {"EXP", 10, 2, 1}, - [SIGNEXTEND] = {"SIGNEXTEND", 5, 2, 1}, - - [LT] = {"LT", 3, 2, 1}, - [GT] = {"GT", 3, 2, 1}, - [SLT] = {"SLT", 3, 2, 1}, - [SGT] = {"SGT", 3, 2, 1}, - [EQ] = {"EQ", 3, 2, 1}, - [ISZERO] = {"ISZERO", 3, 1, 1}, - [AND] = {"AND", 3, 2, 1}, - [OR] = {"OR", 3, 2, 1}, - [XOR] = {"XOR", 3, 2, 1}, - [NOT] = {"NOT", 3, 1, 1}, - [BYTE] = {"BYTE", 3, 2, 1}, + [STOP] = {"STOP", 0, 0, 0, 0}, + [ADD] = {"ADD", 3, 2, 1, 0}, + [MUL] = {"MUL", 5, 2, 1, 0}, + [SUB] = {"SUB", 3, 2, 1, 0}, + [DIV] = {"DIV", 5, 2, 1, 0}, + [SDIV] = {"SDIV", 5, 2, 1, 0}, + [MOD] = {"MOD", 5, 2, 1, 0}, + [SMOD] = {"SMOD", 5, 2, 1, 0}, + [ADDMOD] = {"ADDMOD", 8, 3, 1, 0}, + [MULMOD] = {"MULMOD", 8, 3, 1, 0}, + [EXP] = {"EXP", 10, 2, 1, 0}, + [SIGNEXTEND] = {"SIGNEXTEND", 5, 2, 1, 0}, + + [LT] = {"LT", 3, 2, 1, 0}, + [GT] = {"GT", 3, 2, 1, 0}, + [SLT] = {"SLT", 3, 2, 1, 0}, + [SGT] = {"SGT", 3, 2, 1, 0}, + [EQ] = {"EQ", 3, 2, 1, 0}, + [ISZERO] = {"ISZERO", 3, 1, 1, 0}, + [AND] = {"AND", 3, 2, 1, 0}, + [OR] = {"OR", 3, 2, 1, 0}, + [XOR] = {"XOR", 3, 2, 1, 0}, + [NOT] = {"NOT", 3, 1, 1, 0}, + [BYTE] = {"BYTE", 3, 2, 1, 0}, // 0x20 range - crypto - [SHA3] = {"SHA3", 30, 2, 1}, + [SHA3] = {"SHA3", 30, 2, 1, 0}, // 0x30 range - closure state - [ADDRESS] = {"ADDRESS", 2, 0, 1}, + [ADDRESS] = {"ADDRESS", 2, 0, 1, 0}, [BALANCE] = {"BALANCE", 400, 1, 1, "$callback_128"}, - [ORIGIN] = {"ORIGIN", 2, 0, 1}, - [CALLER] = {"CALLER", 2, 0, 1}, - [CALLVALUE] = {"CALLVALUE", 2, 0, 1}, - [CALLDATALOAD] = {"CALLDATALOAD", 3, 1, 1}, - [CALLDATASIZE] = {"CALLDATASIZE", 2, 0, 1}, - [CALLDATACOPY] = {"CALLDATACOPY", 3, 3, 0}, + [ORIGIN] = {"ORIGIN", 2, 0, 1, 0}, + [CALLER] = {"CALLER", 2, 0, 1, 0}, + [CALLVALUE] = {"CALLVALUE", 2, 0, 1, 0}, + [CALLDATALOAD] = {"CALLDATALOAD", 3, 1, 1, 0}, + [CALLDATASIZE] = {"CALLDATASIZE", 2, 0, 1, 0}, + [CALLDATACOPY] = {"CALLDATACOPY", 3, 3, 0, 0}, [CODESIZE] = {"CODESIZE", 2, 0, 1, "$callback_32"}, [CODECOPY] = {"CODECOPY", 3, 3, 0, "$callback"}, - [GASPRICE] = {"GASPRICE", 2, 0, 1}, + [GASPRICE] = {"GASPRICE", 2, 0, 1, 0}, [EXTCODESIZE] = {"EXTCODESIZE", 700, 1, 1, "$callback_32"}, [EXTCODECOPY] = {"EXTCODECOPY", 700, 4, 0, "$callback"}, - [RETURNDATASIZE] = {"RETURNDATASIZE", 2, 0, 1}, - [RETURNDATACOPY] = {"RETURNDATACOPY", 3, 3, 0}, + [RETURNDATASIZE] = {"RETURNDATASIZE", 2, 0, 1, 0}, + [RETURNDATACOPY] = {"RETURNDATACOPY", 3, 3, 0, 0}, // '0x40' range - block operations [BLOCKHASH] = {"BLOCKHASH", 20, 1, 1, "$callback_256"}, - [COINBASE] = {"COINBASE", 2, 0, 1}, - [TIMESTAMP] = {"TIMESTAMP", 2, 0, 1}, - [NUMBER] = {"NUMBER", 2, 0, 1}, - [DIFFICULTY] = {"DIFFICULTY", 2, 0, 1}, - [GASLIMIT] = {"GASLIMIT", 2, 0, 1}, + [COINBASE] = {"COINBASE", 2, 0, 1, 0}, + [TIMESTAMP] = {"TIMESTAMP", 2, 0, 1, 0}, + [NUMBER] = {"NUMBER", 2, 0, 1, 0}, + [DIFFICULTY] = {"DIFFICULTY", 2, 0, 1, 0}, + [GASLIMIT] = {"GASLIMIT", 2, 0, 1, 0}, // 0x50 range - 'storage' and execution - [POP] = {"POP", 2, 1, 0}, - [MLOAD] = {"MLOAD", 3, 1, 1}, - [MSTORE] = {"MSTORE", 3, 2, 0}, - [MSTORE8] = {"MSTORE8", 3, 2, 0}, + [POP] = {"POP", 2, 1, 0, 0}, + [MLOAD] = {"MLOAD", 3, 1, 1, 0}, + [MSTORE] = {"MSTORE", 3, 2, 0, 0}, + [MSTORE8] = {"MSTORE8", 3, 2, 0, 0}, [SLOAD] = {"SLOAD", 200, 1, 1, "$callback_256"}, [SSTORE] = {"SSTORE", 0, 2, 0, "$callback"}, - [JUMP] = {"JUMP", 8, 1, 0}, - [JUMPI] = {"JUMPI", 10, 2, 0}, - [PC] = {"PC", 2, 0, 1}, - [MSIZE] = {"MSIZE", 2, 0, 1}, - [GAS] = {"GAS", 2, 0, 1}, - [JUMPDEST] = {"JUMPDEST", 1, 0, 0}, + [JUMP] = {"JUMP", 8, 1, 0, 0}, + [JUMPI] = {"JUMPI", 10, 2, 0, 0}, + [PC] = {"PC", 2, 0, 1, 0}, + [MSIZE] = {"MSIZE", 2, 0, 1, 0}, + [GAS] = {"GAS", 2, 0, 1, 0}, + [JUMPDEST] = {"JUMPDEST", 1, 0, 0, 0}, // 0x60, range - [PUSH1] = {"PUSH", 3, 0, 1}, - [PUSH2] = {"PUSH", 3, 0, 1}, - [PUSH3] = {"PUSH", 3, 0, 1}, - [PUSH4] = {"PUSH", 3, 0, 1}, - [PUSH5] = {"PUSH", 3, 0, 1}, - [PUSH6] = {"PUSH", 3, 0, 1}, - [PUSH7] = {"PUSH", 3, 0, 1}, - [PUSH8] = {"PUSH", 3, 0, 1}, - [PUSH9] = {"PUSH", 3, 0, 1}, - [PUSH10] = {"PUSH", 3, 0, 1}, - [PUSH11] = {"PUSH", 3, 0, 1}, - [PUSH12] = {"PUSH", 3, 0, 1}, - [PUSH13] = {"PUSH", 3, 0, 1}, - [PUSH14] = {"PUSH", 3, 0, 1}, - [PUSH15] = {"PUSH", 3, 0, 1}, - [PUSH16] = {"PUSH", 3, 0, 1}, - [PUSH17] = {"PUSH", 3, 0, 1}, - [PUSH18] = {"PUSH", 3, 0, 1}, - [PUSH19] = {"PUSH", 3, 0, 1}, - [PUSH20] = {"PUSH", 3, 0, 1}, - [PUSH21] = {"PUSH", 3, 0, 1}, - [PUSH22] = {"PUSH", 3, 0, 1}, - [PUSH23] = {"PUSH", 3, 0, 1}, - [PUSH24] = {"PUSH", 3, 0, 1}, - [PUSH25] = {"PUSH", 3, 0, 1}, - [PUSH26] = {"PUSH", 3, 0, 1}, - [PUSH27] = {"PUSH", 3, 0, 1}, - [PUSH28] = {"PUSH", 3, 0, 1}, - [PUSH29] = {"PUSH", 3, 0, 1}, - [PUSH30] = {"PUSH", 3, 0, 1}, - [PUSH31] = {"PUSH", 3, 0, 1}, - [PUSH32] = {"PUSH", 3, 0, 1}, - - [DUP1] = {"DUP", 3, 0, 1}, - [DUP2] = {"DUP", 3, 0, 1}, - [DUP3] = {"DUP", 3, 0, 1}, - [DUP4] = {"DUP", 3, 0, 1}, - [DUP5] = {"DUP", 3, 0, 1}, - [DUP6] = {"DUP", 3, 0, 1}, - [DUP7] = {"DUP", 3, 0, 1}, - [DUP8] = {"DUP", 3, 0, 1}, - [DUP9] = {"DUP", 3, 0, 1}, - [DUP10] = {"DUP", 3, 0, 1}, - [DUP11] = {"DUP", 3, 0, 1}, - [DUP12] = {"DUP", 3, 0, 1}, - [DUP13] = {"DUP", 3, 0, 1}, - [DUP14] = {"DUP", 3, 0, 1}, - [DUP15] = {"DUP", 3, 0, 1}, - [DUP16] = {"DUP", 3, 0, 1}, - - [SWAP1] = {"SWAP", 3, 0, 0}, - [SWAP2] = {"SWAP", 3, 0, 0}, - [SWAP3] = {"SWAP", 3, 0, 0}, - [SWAP4] = {"SWAP", 3, 0, 0}, - [SWAP5] = {"SWAP", 3, 0, 0}, - [SWAP6] = {"SWAP", 3, 0, 0}, - [SWAP7] = {"SWAP", 3, 0, 0}, - [SWAP8] = {"SWAP", 3, 0, 0}, - [SWAP9] = {"SWAP", 3, 0, 0}, - [SWAP10] = {"SWAP", 3, 0, 0}, - [SWAP11] = {"SWAP", 3, 0, 0}, - [SWAP12] = {"SWAP", 3, 0, 0}, - [SWAP13] = {"SWAP", 3, 0, 0}, - [SWAP14] = {"SWAP", 3, 0, 0}, - [SWAP15] = {"SWAP", 3, 0, 0}, - [SWAP16] = {"SWAP", 3, 0, 0}, - - [LOG1] = {"LOG", 375, 2, 0}, - [LOG2] = {"LOG", 375, 2, 0}, - [LOG3] = {"LOG", 375, 2, 0}, - [LOG4] = {"LOG", 375, 2, 0}, - [LOG5] = {"LOG", 375, 2, 0}, + [PUSH1] = {"PUSH", 3, 0, 1, 0}, + [PUSH2] = {"PUSH", 3, 0, 1, 0}, + [PUSH3] = {"PUSH", 3, 0, 1, 0}, + [PUSH4] = {"PUSH", 3, 0, 1, 0}, + [PUSH5] = {"PUSH", 3, 0, 1, 0}, + [PUSH6] = {"PUSH", 3, 0, 1, 0}, + [PUSH7] = {"PUSH", 3, 0, 1, 0}, + [PUSH8] = {"PUSH", 3, 0, 1, 0}, + [PUSH9] = {"PUSH", 3, 0, 1, 0}, + [PUSH10] = {"PUSH", 3, 0, 1, 0}, + [PUSH11] = {"PUSH", 3, 0, 1, 0}, + [PUSH12] = {"PUSH", 3, 0, 1, 0}, + [PUSH13] = {"PUSH", 3, 0, 1, 0}, + [PUSH14] = {"PUSH", 3, 0, 1, 0}, + [PUSH15] = {"PUSH", 3, 0, 1, 0}, + [PUSH16] = {"PUSH", 3, 0, 1, 0}, + [PUSH17] = {"PUSH", 3, 0, 1, 0}, + [PUSH18] = {"PUSH", 3, 0, 1, 0}, + [PUSH19] = {"PUSH", 3, 0, 1, 0}, + [PUSH20] = {"PUSH", 3, 0, 1, 0}, + [PUSH21] = {"PUSH", 3, 0, 1, 0}, + [PUSH22] = {"PUSH", 3, 0, 1, 0}, + [PUSH23] = {"PUSH", 3, 0, 1, 0}, + [PUSH24] = {"PUSH", 3, 0, 1, 0}, + [PUSH25] = {"PUSH", 3, 0, 1, 0}, + [PUSH26] = {"PUSH", 3, 0, 1, 0}, + [PUSH27] = {"PUSH", 3, 0, 1, 0}, + [PUSH28] = {"PUSH", 3, 0, 1, 0}, + [PUSH29] = {"PUSH", 3, 0, 1, 0}, + [PUSH30] = {"PUSH", 3, 0, 1, 0}, + [PUSH31] = {"PUSH", 3, 0, 1, 0}, + [PUSH32] = {"PUSH", 3, 0, 1, 0}, + + [DUP1] = {"DUP", 3, 0, 1, 0}, + [DUP2] = {"DUP", 3, 0, 1, 0}, + [DUP3] = {"DUP", 3, 0, 1, 0}, + [DUP4] = {"DUP", 3, 0, 1, 0}, + [DUP5] = {"DUP", 3, 0, 1, 0}, + [DUP6] = {"DUP", 3, 0, 1, 0}, + [DUP7] = {"DUP", 3, 0, 1, 0}, + [DUP8] = {"DUP", 3, 0, 1, 0}, + [DUP9] = {"DUP", 3, 0, 1, 0}, + [DUP10] = {"DUP", 3, 0, 1, 0}, + [DUP11] = {"DUP", 3, 0, 1, 0}, + [DUP12] = {"DUP", 3, 0, 1, 0}, + [DUP13] = {"DUP", 3, 0, 1, 0}, + [DUP14] = {"DUP", 3, 0, 1, 0}, + [DUP15] = {"DUP", 3, 0, 1, 0}, + [DUP16] = {"DUP", 3, 0, 1, 0}, + + [SWAP1] = {"SWAP", 3, 0, 0, 0}, + [SWAP2] = {"SWAP", 3, 0, 0, 0}, + [SWAP3] = {"SWAP", 3, 0, 0, 0}, + [SWAP4] = {"SWAP", 3, 0, 0, 0}, + [SWAP5] = {"SWAP", 3, 0, 0, 0}, + [SWAP6] = {"SWAP", 3, 0, 0, 0}, + [SWAP7] = {"SWAP", 3, 0, 0, 0}, + [SWAP8] = {"SWAP", 3, 0, 0, 0}, + [SWAP9] = {"SWAP", 3, 0, 0, 0}, + [SWAP10] = {"SWAP", 3, 0, 0, 0}, + [SWAP11] = {"SWAP", 3, 0, 0, 0}, + [SWAP12] = {"SWAP", 3, 0, 0, 0}, + [SWAP13] = {"SWAP", 3, 0, 0, 0}, + [SWAP14] = {"SWAP", 3, 0, 0, 0}, + [SWAP15] = {"SWAP", 3, 0, 0, 0}, + [SWAP16] = {"SWAP", 3, 0, 0, 0}, + + [LOG1] = {"LOG", 375, 2, 0, 0}, + [LOG2] = {"LOG", 375, 2, 0, 0}, + [LOG3] = {"LOG", 375, 2, 0, 0}, + [LOG4] = {"LOG", 375, 2, 0, 0}, + [LOG5] = {"LOG", 375, 2, 0, 0}, // '0xf0' range - closures [CREATE] = {"CREATE", 32000, 3, 1, "$callback_160"}, [CALL] = {"CALL", 700, 7, 1, "$callback_32"}, [CALLCODE] = {"CALLCODE", 700, 7, 1, "$callback_32"}, - [RETURN] = {"RETURN", 0, 2, 0}, + [RETURN] = {"RETURN", 0, 2, 0, 0}, [DELEGATECALL] = {"DELEGATECALL", 700, 6, 1, "$callback"}, - [STATICCALL] = {"STATICCALL", 700, 6, 1}, - [REVERT] = {"REVERT", 0, 2, 0}, + [STATICCALL] = {"STATICCALL", 700, 6, 1, 0}, + [REVERT] = {"REVERT", 0, 2, 0, 0}, // '0x70', range - other - [INVALID] = {"INVALID", 0, 0, 0}, - [SELFDESTRUCT] = {"SELFDESTRUCT", 5000, 1, 0} + [INVALID] = {"INVALID", 0, 0, 0, 0}, + [SELFDESTRUCT] = {"SELFDESTRUCT", 5000, 1, 0, 0} }; @@ -231,24 +231,24 @@ static int64_t bytes2long(const char *bytes) } return ret; } -static char *padleft(char *bytes, int curr_len, int len) +static char *padleft(const char *bytes, int curr_len, int len) { if(curr_len > len) { fprintf(stderr, "pad failed to prevent memory overlap\n"); return 0; } - char *ret = calloc(len, 1); + char *ret = calloc(len+1, 1); if(!ret) return 0; - ret = memcpy(ret+(len-curr_len)-1, bytes, curr_len); + memcpy(ret+(len-curr_len), bytes, curr_len); return ret; } /*static char *slice(char *bytes, int len) { - char *ret = malloc(sizeof(len)); - ret = memcpy(ret, bytes, len); + char *ret = malloc(len+1); + memcpy(ret, bytes, len); return ret; }*/ @@ -283,21 +283,21 @@ static char *build_jump_map(size_t *segments, size_t len) segments[i], i, wasm); } size_t s = strlen(wasm) + 358; - wasm = realloc(wasm, s); + wasm = safe_realloc(wasm, s); if(wasm == 0) goto err; snprintf(wasm + strlen(wasm), s, "(block $0 (if (i32.eqz (get_global $init)) (then (set_global $init (i32.const 1)) (br $0)) (else (if (i32.eq (get_global $cb_dest) (i32.const 0)) (then %s) (else $cb_dest get_global $cb_dest (set_global $cb_dest (i32.const 0)) (br_table $0 ${brTable}))))))", wasm); free(brtable); return wasm; err: - perror("Falied to allocate memory for assemble_segments"); + perror("Falied to allocate memory for jump map building"); return 0; } static char *assemble_segments(size_t *segments, size_t len) { char *wasm = build_jump_map(segments, len); - char *ret = malloc(len*(8+digits(len)+strlen(wasm)+1) + 200); + char *ret = calloc(len*(8+digits(len)+strlen(wasm)+1) + 200, 1); if(ret == 0) goto err; strcat(ret, "(func $main (export \"main\") (local $jump_dest i32) (set_local $jump_dest (i32.const -1)) (block $done (loop $loop "); unsigned int i; @@ -305,9 +305,8 @@ static char *assemble_segments(size_t *segments, size_t len) { sprintf(ret+strlen(ret), "(block $%d %s ))", i+1, wasm); } - strcat(ret+strlen(ret), "))"); + strcat(ret, "))"); free(wasm); - free(ret); return ret; err: perror("Falied to allocate memory for assemble_segments"); @@ -333,7 +332,7 @@ static char *add_stack_check(char **segment) if(!check) goto err; snprintf(check, strlen(template_low)+32, template_low, (-stack_low*32)-32); } - char *ret = malloc(strlen(check) + strlen(*segment)+1); + char *ret = calloc(strlen(check) + strlen(*segment)+1, 1); sprintf(ret, "%s%s", check, *segment); stack_high = 0; stack_low = 0; @@ -367,7 +366,7 @@ static inline void end_segment(char **wast, char **segment) add_metering(wast, segment); } -static size_t next_jump_dest(char *evm_code, size_t len, size_t i) +static size_t next_jump_dest(const char *evm_code, size_t len, size_t i) { for(; i> 3; - char *push = 0; + int bytes_rounded = (evm_code[i] + 7) >> 3; + char *push = calloc(1, 1); int q; for(q=0; q<4-bytes_rounded; q++) { - push = realloc(push, (q+1)*32); // FIXME segfault + push = safe_realloc(push, (q+1)*32); // FIXME segfault if(!push) goto err; sprintf(push, "(i64.const 0)%s", push); } + + int64_t i64; for(; q<4; q++) { - int64_t i64 = bytes2long(slice(bytes+(q*8), q*8+8)); - push = realloc(push, (q+1)*32); + i64 = bytes2long(bytes+(q*8)); + push = safe_realloc(push, (q+1)*32); if(!push) goto err; - sprintf(push, "%s (i64.const %ld)", push, i64); - + snprintf(push, (q+1)*32, "%s (i64.const %ld)", push, i64); } - format_segment("(call $PUSH %s)", 13+strlen(push), push); + format_segment("(call $PUSH %s)", 14+strlen(push)+digits(i64), push); i+=(size_t)evm_code[i]-0x5f; free(push); + free(bytes); } break; @@ -664,18 +665,20 @@ int evm2wast(const char *evm_code, size_t len, char **wast_ret, size_t *wast_siz if(op.cb != 0) { format_segment("(set_global $cb_dest (i32.const %ld)) (br $done))", 72, jumps_len+1); - jumps = realloc(jumps, (jumps_len+1)*sizeof(size_t)); + jumps = safe_realloc(jumps, (jumps_len+1)*sizeof(size_t)); if(!jumps) goto err; jumps[jumps_len++] = i; } } - end_segment(wast_code, segment); + end_segment(&wast_code, &segment); char *with_jumps = assemble_segments(jumps, jumps_len); - wast_code = realloc(wast_code, strlen(wast_code) + strlen(with_jumps)); - if(wast_code == 0) goto err; - wast_code = strcat(with_jumps, wast_code); - wast_code = strcat(wast_code, "))"); - wast_code = build_module(wast_code); + //wast_code = safe_realloc(wast_code, strlen(wast_code) + strlen(with_jumps)+3); + //if(wast_code == 0) goto err; + char *temp = calloc(strlen(wast_code) + strlen(with_jumps)+3, 1); + sprintf(temp, "%s%s)", with_jumps, wast_code); + free(wast_code); + wast_code = build_module(temp); + free(temp); free(segment); free(with_jumps); free(jumps);