btcs

bitcoin script parser/evaluator/compiler/decompiler
git clone git://jb55.com/btcs
Log | Files | Refs | README | LICENSE

commit 959e3cf982e564cd5f4791fe3205faeda805935f
parent dcc97bed52d6218d8d4a4cdb40dd3238b8b9071e
Author: William Casarin <jb55@jb55.com>
Date:   Thu, 21 Dec 2017 06:17:20 -0800

OP_DUP: copy vals

otherwise it only copies as reference, which is not what we want and is really
bad

Diffstat:
Malloc.c | 4++--
Malloc.h | 4++--
Mscript.c | 14+++++++-------
Mscript_num.c | 4++--
Mval.c | 27++++++++++++++++++++++++++-
Mval.h | 1+
6 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/alloc.c b/alloc.c @@ -26,7 +26,7 @@ alloc_arena_sizes(struct arenas *arenas, const int nums, const int bytes) { } struct num * -num_pool_get(const int ind) { +num_pool_get(const u16 ind) { return &g_arenas.nums[ind]; } @@ -39,7 +39,7 @@ num_pool_pop() { struct num * -num_pool_new(int *ind) { +num_pool_new(u16 *ind) { *ind = g_arenas.num_count++; struct num *p; p = &g_arenas.nums[*ind]; diff --git a/alloc.h b/alloc.h @@ -10,9 +10,9 @@ #define MAX_PUSHDATA_REFS (MAX_OPS_PER_SCRIPT * MAX_STACK_SIZE) #define ALLOC_PUSHDATA_BYTES (MAX_STACK_SIZE * MAX_OPS_PER_SCRIPT) -struct num * num_pool_new(int *ind); +struct num * num_pool_new(u16 *ind); struct num * num_pool_pop(); -struct num * num_pool_get(const int ind); +struct num * num_pool_get(const u16 ind); u8 *byte_pool_new(u32 len, u16 *ind); u8 *byte_pool_get(int ind, u32 *len); diff --git a/script.c b/script.c @@ -288,8 +288,8 @@ script_eval(const u8 *script, size_t script_size, struct stack *stack, SCRIPTERR("INVALID_STACK_OPERATION"); struct val v1 = stack_top_val(stack, -2); struct val v2 = stack_top_val(stack, -1); - stack_push_val(stack, v1); - stack_push_val(stack, v2); + stack_push_val(stack, val_copy(v1)); + stack_push_val(stack, val_copy(v2)); } break; @@ -301,9 +301,9 @@ script_eval(const u8 *script, size_t script_size, struct stack *stack, struct val v1 = stack_top_val(stack, -3); struct val v2 = stack_top_val(stack, -2); struct val v3 = stack_top_val(stack, -1); - stack_push_val(stack, v1); - stack_push_val(stack, v2); - stack_push_val(stack, v3); + stack_push_val(stack, val_copy(v1)); + stack_push_val(stack, val_copy(v2)); + stack_push_val(stack, val_copy(v3)); } break; @@ -387,7 +387,7 @@ script_eval(const u8 *script, size_t script_size, struct stack *stack, if (stack_size(stack) < 1) SCRIPTERR("INVALID_STACK_OPERATION"); struct val val = stack_top_val(stack, (-1)); - stack_push_val(stack, val); + stack_push_val(stack, val_copy(val)); } break; @@ -532,7 +532,7 @@ script_eval(const u8 *script, size_t script_size, struct stack *stack, // (in -- out) if (stack_size(stack) < 1) SCRIPTERR("INVALID_STACK_OPERATION"); - struct num *bn; + struct num *bn; enum sn_result res = sn_from_val(stack_top_val(stack, -1), &bn, require_minimal); diff --git a/script_num.c b/script_num.c @@ -101,7 +101,7 @@ int_from_data(u8 *data, u16 size) { enum sn_result sn_from_data(u8 *data, u16 size, struct num **num) { - int ind; + u16 ind; s64 i; i = int_from_data(data, size); if (int_overflowed(i)) { @@ -157,7 +157,7 @@ struct val sn_to_val(struct num *sn) { struct val val; struct num *snref; - int ind; + u16 ind; if (sn_overflowed(sn)) { u16 ind, len; diff --git a/val.c b/val.c @@ -18,7 +18,7 @@ struct val val_from_int(s64 intval) { struct val val; struct num *sn; - int ind; + u16 ind; sn = num_pool_new(&ind); val.type = VT_SCRIPTNUM; val.ind = ind; @@ -133,6 +133,31 @@ val_eq(struct val a, struct val b, int require_minimal) { return eq; } +struct val +val_copy(struct val a) { + u32 len; + u16 newind; + u8 *src, *dst; + struct num *nsrc, *ndst; + + switch (a.type) { + case VT_SMALLINT: + return a; + case VT_DATA: + src = byte_pool_get(a.ind, &len); + dst = byte_pool_new(len, &newind); + memcpy(dst, src, len); + a.ind = newind; + return a; + case VT_SCRIPTNUM: + nsrc = num_pool_get(a.ind); + ndst = num_pool_new(&newind); + ndst->val = nsrc->val; + return sn_to_val(ndst); + default: + assert(!"unhandle val_copy enum"); + } +} /* struct val */ /* val_int(s64 n) { */ diff --git a/val.h b/val.h @@ -31,6 +31,7 @@ struct val { // we want val to fit into the size of a 32-bit pointer STATIC_ASSERT(sizeof(struct val) <= 4, val_doesnt_fit_in_stack); +struct val val_copy(struct val a); int val_eq(struct val a, struct val b, int require_minimal);