Commit 8fb4acdbfed3bbce1be5f5a32c2460cb16b23a50

Thomas de Grivel 2023-09-19T18:23:18

wip arrays asan

diff --git a/libc3/array.c b/libc3/array.c
index 87702c3..c0ce6e5 100644
--- a/libc3/array.c
+++ b/libc3/array.c
@@ -53,6 +53,7 @@ s_array * array_copy (const s_array *src, s_array *dest)
   dest->dimensions = calloc(src->dimension, sizeof(s_array_dimension));
   memcpy(dest->dimensions, src->dimensions,
          src->dimension * sizeof(s_array_dimension));
+  dest->count = src->count;
   dest->size = src->size;
   dest->type = src->type;
   if (src->data) {
diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index d54b96a..b7c2861 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -50,7 +50,7 @@ sw buf_parse_array (s_buf *buf, s_array *dest)
   assert(buf);
   assert(dest);
   buf_save_init(buf, &save);
-  tmp = *dest;
+  bzero(&tmp, sizeof(tmp));
   if ((r = buf_parse_paren_sym(buf, &tmp.type)) <= 0)
     goto clean;
   result += r;
@@ -86,10 +86,18 @@ sw buf_parse_array_data (s_buf *buf, s_array *dest)
   assert(buf);
   assert(dest);
   tmp = *dest;
-  address = calloc(tmp.dimension, sizeof(sw));
+  if (! (address = calloc(tmp.dimension, sizeof(sw)))) {
+    warnx("buf_parse_array_data: out of memory: address");
+    return -1;
+  }
   tmp.size = tmp.dimensions[0].count * tmp.dimensions[0].item_size;
   tmp.count = tmp.size / tmp.dimensions[tmp.dimension - 1].item_size;
-  tmp.tags = calloc(tmp.count, sizeof(s_tag));
+  assert(tmp.count);
+  if (! (tmp.tags = calloc(tmp.count, sizeof(s_tag)))) {
+    free(address);
+    warnx("buf_parse_array_data: out of memory: tags");
+    return -1;
+  }
   tag = tmp.tags;
   if ((r = buf_parse_array_data_rec(buf, &tmp, address, &tag,
                                     0)) <= 0) {
diff --git a/libc3/call.c b/libc3/call.c
index 798404a..6835db1 100644
--- a/libc3/call.c
+++ b/libc3/call.c
@@ -140,7 +140,8 @@ s_call * call_init_1 (s_call *call, const s8 *p)
   return call;
 }
 
-s_call * call_init_cast (s_call *call, const s_sym *type, s_tag *tag)
+s_call * call_init_cast (s_call *call, const s_sym *type,
+                         const s_tag *tag)
 {
   assert(call);
   bzero(call, sizeof(s_call));
diff --git a/libc3/call.h b/libc3/call.h
index 11c1ca9..0dadb06 100644
--- a/libc3/call.h
+++ b/libc3/call.h
@@ -19,7 +19,8 @@
 void     call_clean (s_call *call);
 s_call * call_init (s_call *call);
 s_call * call_init_1 (s_call *call, const s8 *p);
-s_call * call_init_cast (s_call *call, const s_sym *type, s_tag *tag);
+s_call * call_init_cast (s_call *call, const s_sym *type,
+                         const s_tag *tag);
 s_call * call_init_op (s_call *call);
 s_call * call_init_op_unary (s_call *call);
 
diff --git a/libc3/env.c b/libc3/env.c
index b8e6e82..3967ca7 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -45,7 +45,7 @@
 
 s_env g_c3_env;
 
-bool env_eval_array_cast (s_env *env, s_array *tmp, s_tag *tag,
+bool env_eval_array_cast (s_env *env, s_array *tmp, const s_tag *tag,
                           u8 *data, uw size);
 
 void env_clean (s_env *env)
@@ -99,26 +99,30 @@ void env_error_tag (s_env *env, const s_tag *tag)
 bool env_eval_array (s_env *env, const s_array *array, s_tag *dest)
 {
   u8 *data;
-  uw i = 0;
-  uw size;
+  uw i;
+  uw item_size;
   s_tag *tag;
   s_array tmp;
   assert(env);
   assert(array);
   assert(dest);
   array_copy(array, &tmp);
-  size = tmp.dimensions[tmp.dimension - 1].item_size;
+  item_size = tmp.dimensions[tmp.dimension - 1].item_size;
   if (! tmp.data &&
       ! (tmp.data = calloc(tmp.dimensions[0].count,
                            tmp.dimensions[0].item_size))) {
-    assert(! "env_eval_array: out of memory");
-    errx(1, "env_eval_array: out of memory");
+    assert(! "env_eval_array: out of memory: data");
+    errx(1, "env_eval_array: out of memory: data");
   }
   data = tmp.data;
   tag = tmp.tags;
+  i = 0;
   while (i < tmp.count) {
-    env_eval_array_cast(env, &tmp, tag, data, size);
-    data += size;
+    if (! env_eval_array_cast(env, &tmp, tag, data, item_size)) {
+      array_clean(&tmp);
+      return false;
+    }
+    data += item_size;
     tag++;
     i++;
   }
@@ -127,11 +131,12 @@ bool env_eval_array (s_env *env, const s_array *array, s_tag *dest)
   return true;
 }
 
-bool env_eval_array_cast (s_env *env, s_array *tmp, s_tag *tag,
+bool env_eval_array_cast (s_env *env, s_array *tmp, const s_tag *tag,
                           u8 *data, uw size)
 {
   s_call call;
   s_tag tag_eval;
+  e_tag_type tag_type;
   void *data_eval;
   assert(env);
   assert(tmp);
@@ -142,8 +147,8 @@ bool env_eval_array_cast (s_env *env, s_array *tmp, s_tag *tag,
     return false;
   if (! env_eval_call(env, &call, &tag_eval))
     return false;
-  data_eval = tag_to_pointer(&tag_eval,
-                             array_type_to_tag_type(tmp->type));
+  tag_type = array_type_to_tag_type(tmp->type);
+  data_eval = tag_to_pointer(&tag_eval, tag_type);
   memcpy(data, data_eval, size);
   return true;
 }
@@ -598,8 +603,8 @@ bool env_eval_tag (s_env *env, const s_tag *tag, s_tag *dest)
     tag_copy(tag, dest);
     return true;
   }
-  assert(! "env_eval_tag: invalid tag");
-  errx(1, "env_eval_tag: invalid tag");
+  assert(! "env_eval_tag: unknown tag type");
+  errx(1, "env_eval_tag: unknown tag type: %d", tag->type);
   return false;
 }