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:
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);