save
authorOlivier Matz <zer0@droids-corp.org>
Thu, 8 Mar 2018 18:14:45 +0000 (19:14 +0100)
committerOlivier Matz <zer0@droids-corp.org>
Thu, 8 Mar 2018 18:14:45 +0000 (19:14 +0100)
21 files changed:
lib/ecoli_completed.c
lib/ecoli_log.c
lib/ecoli_node.c
lib/ecoli_node.h
lib/ecoli_node_cmd.c
lib/ecoli_node_dynamic.c
lib/ecoli_node_expr_test.c
lib/ecoli_node_file.c
lib/ecoli_node_int.c
lib/ecoli_node_once.c
lib/ecoli_node_option.c
lib/ecoli_node_or.c
lib/ecoli_node_seq.c
lib/ecoli_node_sh_lex.c
lib/ecoli_node_subset.c
lib/ecoli_node_weakref.c
lib/ecoli_parsed.c
lib/ecoli_string.c
lib/ecoli_string.h
lib/ecoli_vec.c
lib/main.c

index 0159797..e44ba9e 100644 (file)
@@ -260,7 +260,7 @@ ec_completed_item(const struct ec_node *node, enum ec_completed_type type,
        return item;
 
 fail:
-       ec_keyval_free(item->attrs);
+       ec_keyval_free(attrs);
        ec_free(comp_cp);
        ec_free(start_cp);
        ec_free(full_cp);
@@ -599,10 +599,13 @@ ec_completed_iter(struct ec_completed *completed,
 struct ec_completed_item *ec_completed_iter_next(
        struct ec_completed_iter *iter)
 {
-       struct ec_completed *completed = iter->completed;
+       struct ec_completed *completed;
        struct ec_completed_group *cur_node;
        struct ec_completed_item *cur_match;
 
+       if (iter == NULL)
+               return NULL;
+       completed = iter->completed;
        if (completed == NULL)
                return NULL;
 
index 92e2145..75ece93 100644 (file)
@@ -32,6 +32,7 @@
 #include <errno.h>
 
 #include <ecoli_malloc.h>
+#include <ecoli_string.h>
 #include <ecoli_log.h>
 
 static ec_log_t ec_log_fct = ec_log_default_cb;
@@ -145,6 +146,9 @@ int ec_vlog(int type, enum ec_log_level level, const char *format, va_list ap)
        char *s;
        int ret;
 
+       /* don't use ec_vasprintf here, because it will call
+        * ec_malloc(), then ec_log(), ec_vasprintf()...
+        * -> stack overflow */
        ret = vasprintf(&s, format, ap);
        if (ret < 0)
                return ret;
index 458d6bc..17a18a8 100644 (file)
@@ -33,6 +33,7 @@
 #include <errno.h>
 
 #include <ecoli_malloc.h>
+#include <ecoli_string.h>
 #include <ecoli_strvec.h>
 #include <ecoli_keyval.h>
 #include <ecoli_log.h>
@@ -78,7 +79,6 @@ void ec_node_type_dump(FILE *out)
 struct ec_node *__ec_node(const struct ec_node_type *type, const char *id)
 {
        struct ec_node *node = NULL;
-       char buf[256]; // XXX
 
        EC_LOG(EC_LOG_DEBUG, "create node type=%s id=%s\n",
                type->name, id);
@@ -99,9 +99,7 @@ struct ec_node *__ec_node(const struct ec_node_type *type, const char *id)
        if (node->id == NULL)
                goto fail;
 
-       snprintf(buf, sizeof(buf), "<%s>", type->name);
-       node->desc = ec_strdup(buf); // XXX ec_asprintf ?
-       if (node->desc == NULL)
+       if (ec_asprintf(&node->desc, "<%s>", type->name) < 0)
                goto fail;
 
        node->attrs = ec_keyval();
@@ -116,9 +114,11 @@ struct ec_node *__ec_node(const struct ec_node_type *type, const char *id)
        return node;
 
  fail:
-       ec_keyval_free(node->attrs);
-       ec_free(node->desc);
-       ec_free(node->id);
+       if (node != NULL) {
+               ec_keyval_free(node->attrs);
+               ec_free(node->desc);
+               ec_free(node->id);
+       }
        ec_free(node);
 
        return NULL;
@@ -199,11 +199,6 @@ const char *ec_node_id(const struct ec_node *node)
        return node->id;
 }
 
-struct ec_node *ec_node_parent(const struct ec_node *node)
-{
-       return node->parent;
-}
-
 static void __ec_node_dump(FILE *out,
        const struct ec_node *node, size_t indent)
 {
index 5a25a1f..ac88033 100644 (file)
@@ -153,8 +153,6 @@ struct ec_node {
        char *id;
        char *desc;
        struct ec_keyval *attrs;
-       /* XXX ensure parent and child are properly set in all nodes */
-       struct ec_node *parent;
        unsigned int refcnt;
 
        TAILQ_ENTRY(ec_node) next;
@@ -180,7 +178,6 @@ size_t ec_node_get_max_parse_len(const struct ec_node *node);
 
 /* XXX add more accessors */
 struct ec_keyval *ec_node_attrs(const struct ec_node *node);
-struct ec_node *ec_node_parent(const struct ec_node *node);
 const char *ec_node_id(const struct ec_node *node);
 const char *ec_node_desc(const struct ec_node *node);
 
index 85b97b2..5d47a7b 100644 (file)
@@ -250,7 +250,7 @@ static const struct ec_node_expr_eval_ops test_ops = {
 static int ec_node_cmd_build(struct ec_node_cmd *node)
 {
        struct ec_node *expr = NULL, *lex = NULL, *cmd = NULL;
-       struct ec_parsed *p, *child;
+       struct ec_parsed *p = NULL, *child;
        void *result;
        int ret;
 
@@ -435,7 +435,6 @@ int ec_node_cmd_add_child(struct ec_node *gen_node, struct ec_node *child)
        table[node->len] = child;
        node->len++;
 
-       child->parent = gen_node;
        TAILQ_INSERT_TAIL(&gen_node->children, child, next); // XXX really needed?
 
        return 0;
@@ -451,12 +450,14 @@ struct ec_node *__ec_node_cmd(const char *id, const char *cmd, ...)
 
        gen_node = __ec_node(&ec_node_cmd_type, id);
        if (gen_node == NULL)
-               goto fail;
+               fail = 1;
 
-       node = (struct ec_node_cmd *)gen_node;
-       node->cmd_str = ec_strdup(cmd);
-       if (node->cmd_str == NULL)
-               goto fail;
+       if (fail == 0) {
+               node = (struct ec_node_cmd *)gen_node;
+               node->cmd_str = ec_strdup(cmd);
+               if (node->cmd_str == NULL)
+                       fail = 1;
+       }
 
        va_start(ap, cmd);
 
@@ -472,11 +473,11 @@ struct ec_node *__ec_node_cmd(const char *id, const char *cmd, ...)
                }
        }
 
+       va_end(ap);
+
        if (fail == 1)
                goto fail;
 
-       va_end(ap);
-
        if (ec_node_cmd_build(node) < 0)
                goto fail;
 
@@ -484,7 +485,6 @@ struct ec_node *__ec_node_cmd(const char *id, const char *cmd, ...)
 
 fail:
        ec_node_free(gen_node); /* will also free children */
-       va_end(ap);
        return NULL;
 }
 
index de99f1b..e4b538d 100644 (file)
@@ -72,8 +72,10 @@ ec_node_dynamic_parse(const struct ec_node *gen_node,
        snprintf(key, sizeof(key), "_dyn_%p", child);
        ret = ec_keyval_set(ec_parsed_get_attrs(parsed), key, child,
                        (void *)node_free);
-       if (ret < 0)
+       if (ret < 0) {
+               child = NULL; /* already freed */
                goto fail;
+       }
 
        return ec_node_parse_child(child, parsed, strvec);
 
@@ -104,8 +106,10 @@ ec_node_dynamic_complete(const struct ec_node *gen_node,
        snprintf(key, sizeof(key), "_dyn_%p", child);
        ret = ec_keyval_set(completed->attrs, key, child,
                        (void *)node_free);
-       if (ret < 0)
+       if (ret < 0) {
+               child = NULL; /* already freed */
                goto fail;
+       }
 
        return ec_node_complete_child(child, completed, strvec);
 
index 45c169e..935eec0 100644 (file)
@@ -308,7 +308,7 @@ fail:
 /* LCOV_EXCL_STOP */
 
 static struct ec_test ec_node_expr_test = {
-       .name = "expr",
+       .name = "node_expr",
        .test = ec_node_expr_testcase,
 };
 
index a92c629..fbba156 100644 (file)
@@ -25,7 +25,6 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#define _GNU_SOURCE /* for asprintf */
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <stdio.h>
@@ -202,23 +201,23 @@ ec_node_file_complete(const struct ec_node *gen_node,
 
                if (is_dir) {
                        type = EC_COMP_PARTIAL;
-                       if (asprintf(&comp_str, "%s%s/", input,
+                       if (ec_asprintf(&comp_str, "%s%s/", input,
                                        &de->d_name[bname_len]) < 0) {
                                ret = -errno;
                                goto out;
                        }
-                       if (asprintf(&disp_str, "%s/", de->d_name) < 0) {
+                       if (ec_asprintf(&disp_str, "%s/", de->d_name) < 0) {
                                ret = -errno;
                                goto out;
                        }
                } else {
                        type = EC_COMP_FULL;
-                       if (asprintf(&comp_str, "%s%s", input,
+                       if (ec_asprintf(&comp_str, "%s%s", input,
                                        &de->d_name[bname_len]) < 0) {
                                ret = -errno;
                                goto out;
                        }
-                       if (asprintf(&disp_str, "%s", de->d_name) < 0) {
+                       if (ec_asprintf(&disp_str, "%s", de->d_name) < 0) {
                                ret = -errno;
                                goto out;
                        }
@@ -235,16 +234,16 @@ ec_node_file_complete(const struct ec_node *gen_node,
                        goto out;
 
                item = NULL;
-               free(comp_str);
+               ec_free(comp_str);
                comp_str = NULL;
-               free(disp_str);
+               ec_free(disp_str);
                disp_str = NULL;
        }
        ret = 0;
 
 out:
-       free(comp_str);
-       free(disp_str);
+       ec_free(comp_str);
+       ec_free(disp_str);
        ec_free(dname);
        ec_free(bname);
        if (dir != NULL)
index 9dae63a..b086c56 100644 (file)
@@ -379,16 +379,16 @@ static int ec_node_int_testcase(void)
 
        p = ec_node_parse(node, "0");
        s = ec_strvec_val(ec_parsed_strvec(p), 0);
-       EC_TEST_ASSERT(s != NULL);
-       EC_TEST_ASSERT(ec_node_uint_getval(node, s, &u64) == 0);
-       EC_TEST_ASSERT (u64 == 0);
+       EC_TEST_ASSERT(s != NULL &&
+               ec_node_uint_getval(node, s, &u64) == 0 &&
+               u64 == 0);
        ec_parsed_free(p);
 
        p = ec_node_parse(node, "10");
        s = ec_strvec_val(ec_parsed_strvec(p), 0);
-       EC_TEST_ASSERT(s != NULL);
-       EC_TEST_ASSERT(ec_node_uint_getval(node, s, &u64) == 0);
-       EC_TEST_ASSERT(u64 == 10);
+       EC_TEST_ASSERT(s != NULL &&
+               ec_node_uint_getval(node, s, &u64) == 0 &&
+               u64 == 10);
        ec_parsed_free(p);
        ec_node_free(node);
 
@@ -405,9 +405,9 @@ static int ec_node_int_testcase(void)
 
        p = ec_node_parse(node, "10");
        s = ec_strvec_val(ec_parsed_strvec(p), 0);
-       EC_TEST_ASSERT(s != NULL);
-       EC_TEST_ASSERT(ec_node_int_getval(node, s, &i64) == 0);
-       EC_TEST_ASSERT(i64 == 16);
+       EC_TEST_ASSERT(s != NULL &&
+               ec_node_int_getval(node, s, &i64) == 0 &&
+               i64 == 16);
        ec_parsed_free(p);
        ec_node_free(node);
 
index 086f185..940ab4b 100644 (file)
@@ -142,7 +142,6 @@ int ec_node_once_set(struct ec_node *gen_node, struct ec_node *child)
 
        node->child = child;
 
-       child->parent = gen_node;
        TAILQ_INSERT_TAIL(&gen_node->children, child, next); // XXX really needed?
 
        return 0;
@@ -157,11 +156,16 @@ struct ec_node *ec_node_once(const char *id, struct ec_node *child)
 
        gen_node = __ec_node(&ec_node_once_type, id);
        if (gen_node == NULL)
-               return NULL;
+               goto fail;
 
        ec_node_once_set(gen_node, child);
+       child = NULL;
 
        return gen_node;
+
+fail:
+       ec_node_free(child);
+       return NULL;
 }
 
 /* LCOV_EXCL_START */
index 6f8d229..bc912ef 100644 (file)
@@ -110,7 +110,6 @@ struct ec_node *ec_node_option(const char *id, struct ec_node *child)
 
        node->child = child;
 
-       child->parent = gen_node;
        TAILQ_INSERT_TAIL(&gen_node->children, child, next);
 
        return &node->gen;
index ddf8281..c0d43e2 100644 (file)
@@ -123,16 +123,13 @@ int ec_node_or_add(struct ec_node *gen_node, struct ec_node *child)
                return -EINVAL;
 
        table = ec_realloc(node->table, (node->len + 1) * sizeof(*node->table));
-       if (table == NULL) {
-               ec_node_free(child);
+       if (table == NULL)
                return -1;
-       }
 
        node->table = table;
        table[node->len] = child;
        node->len++;
 
-       child->parent = gen_node;
        TAILQ_INSERT_TAIL(&gen_node->children, child, next);
 
        return 0;
index e239bcf..f825d54 100644 (file)
@@ -238,7 +238,6 @@ int ec_node_seq_add(struct ec_node *gen_node, struct ec_node *child)
        table[node->len] = child;
        node->len++;
 
-       child->parent = gen_node;
        TAILQ_INSERT_TAIL(&gen_node->children, child, next); // XXX really needed?
 
        return 0;
index 7f532fe..d2b73ab 100644 (file)
@@ -25,7 +25,6 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#define _GNU_SOURCE /* for asprintf */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -36,6 +35,7 @@
 
 #include <ecoli_malloc.h>
 #include <ecoli_log.h>
+#include <ecoli_string.h>
 #include <ecoli_test.h>
 #include <ecoli_strvec.h>
 #include <ecoli_node.h>
@@ -323,25 +323,25 @@ ec_node_sh_lex_complete(const struct ec_node *gen_node,
                        goto fail;
                while ((item = ec_completed_iter_next(iter)) != NULL) {
                        str = ec_completed_item_get_str(item);
-                       if (asprintf(&new_str, "%c%s%c", missing_quote, str,
+                       if (ec_asprintf(&new_str, "%c%s%c", missing_quote, str,
                                        missing_quote) < 0) {
                                new_str = NULL;
                                goto fail;
                        }
                        if (ec_completed_item_set_str(item, new_str) < 0)
                                goto fail;
-                       free(new_str);
+                       ec_free(new_str);
                        new_str = NULL;
 
                        str = ec_completed_item_get_completion(item);
-                       if (asprintf(&new_str, "%s%c", str,
+                       if (ec_asprintf(&new_str, "%s%c", str,
                                        missing_quote) < 0) {
                                new_str = NULL;
                                goto fail;
                        }
                        if (ec_completed_item_set_completion(item, new_str) < 0)
                                goto fail;
-                       free(new_str);
+                       ec_free(new_str);
                        new_str = NULL;
                }
        }
@@ -357,7 +357,7 @@ ec_node_sh_lex_complete(const struct ec_node *gen_node,
        ec_completed_free(tmp_completed);
        ec_completed_iter_free(iter);
        ec_strvec_free(new_vec);
-       free(new_str);
+       ec_free(new_str);
 
        return -1;
 }
index 5d8ca0a..9dc6020 100644 (file)
@@ -288,7 +288,6 @@ int ec_node_subset_add(struct ec_node *gen_node, struct ec_node *child)
        table[node->len] = child;
        node->len++;
 
-       child->parent = gen_node;
        TAILQ_INSERT_TAIL(&gen_node->children, child, next);
 
        return 0;
index c598195..2a8f1f9 100644 (file)
@@ -92,7 +92,6 @@ int ec_node_weakref_set(struct ec_node *gen_node, struct ec_node *child)
 
        node->child = child;
 
-       child->parent = gen_node;
        // XXX else it breaks the dump()
        //TAILQ_INSERT_TAIL(&gen_node->children, child, next); // XXX really needed?
 
index 54bed70..b4b59e8 100644 (file)
@@ -63,7 +63,7 @@ static int __ec_node_parse_child(const struct ec_node *node,
                                bool is_root, const struct ec_strvec *strvec)
 {
        struct ec_strvec *match_strvec;
-       struct ec_parsed *child;
+       struct ec_parsed *child = NULL;
        int ret;
 
        if (node->type->parse == NULL)
@@ -79,25 +79,25 @@ static int __ec_node_parse_child(const struct ec_node *node,
                child = state;
        }
        ret = node->type->parse(node, child, strvec);
-       if (ret < 0) // XXX should we free state, child?
-               return ret;
-
-       if (ret == EC_PARSED_NOMATCH) {
-               if (!is_root) {
-                       ec_parsed_del_child(state, child);
-                       assert(TAILQ_EMPTY(&child->children));
-                       ec_parsed_free(child);
-               }
-               return ret;
-       }
+       if (ret < 0 || ret == EC_PARSED_NOMATCH)
+               goto free;
 
        match_strvec = ec_strvec_ndup(strvec, 0, ret);
-       if (match_strvec == NULL)
-               return -ENOMEM;
+       if (match_strvec == NULL) {
+               ret = -ENOMEM;
+               goto free;
+       }
 
        child->strvec = match_strvec;
 
        return ret;
+
+free:
+       if (!is_root) {
+               ec_parsed_del_child(state, child);
+               ec_parsed_free(child);
+       }
+       return ret;
 }
 
 int ec_node_parse_child(const struct ec_node *node, struct ec_parsed *state,
index 49e4a37..d51533f 100644 (file)
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <stdarg.h>
 #include <stddef.h>
 #include <string.h>
+#include <stdio.h>
 
+#include <ecoli_assert.h>
+#include <ecoli_malloc.h>
 #include <ecoli_string.h>
 
 /* count the number of identical chars at the beginning of 2 strings */
@@ -51,3 +55,47 @@ int ec_str_startswith(const char *s, const char *beginning)
 
        return 0;
 }
+
+int ec_vasprintf(char **buf, const char *fmt, va_list ap)
+{
+       char dummy;
+       int buflen, ret;
+       va_list aq;
+
+       va_copy(aq, ap);
+       *buf = NULL;
+       ret = vsnprintf(&dummy, 1, fmt, aq);
+       va_end(aq);
+       if (ret < 0)
+               return ret;
+
+       buflen = ret + 1;
+       *buf = ec_malloc(buflen);
+       if (*buf == NULL)
+               return -1;
+
+       va_copy(aq, ap);
+       ret = vsnprintf(*buf, buflen, fmt, aq);
+       va_end(aq);
+
+       ec_assert_print(ret < buflen, "invalid return value for vsnprintf");
+       if (ret < 0) {
+               free(*buf);
+               *buf = NULL;
+               return -1;
+       }
+
+       return ret;
+}
+
+int ec_asprintf(char **buf, const char *fmt, ...)
+{
+       va_list ap;
+       int ret;
+
+       va_start(ap, fmt);
+       ret = ec_vasprintf(buf, fmt, ap);
+       va_end(ap);
+
+       return ret;
+}
index ae92b4d..4df061d 100644 (file)
@@ -36,4 +36,10 @@ size_t ec_strcmp_count(const char *s1, const char *s2);
 /* return 1 if 's' starts with 'beginning' */
 int ec_str_startswith(const char *s, const char *beginning);
 
+/* like asprintf, but use libecoli allocator */
+int ec_asprintf(char **buf, const char *fmt, ...);
+
+/* like vasprintf, but use libecoli allocator */
+int ec_vasprintf(char **buf, const char *fmt, va_list ap);
+
 #endif
index 8126526..b3249b5 100644 (file)
@@ -459,15 +459,15 @@ static int ec_vec_testcase(void)
 
        if (ec_vec_get(&vals, vec, 0) < 0)
                GOTO_FAIL;
-       if (strcmp(vals, "0"))
+       if (vals == NULL || strcmp(vals, "0"))
                GOTO_FAIL;
        if (ec_vec_get(&vals, vec, 1) < 0)
                GOTO_FAIL;
-       if (strcmp(vals, "1"))
+       if (vals == NULL || strcmp(vals, "1"))
                GOTO_FAIL;
        if (ec_vec_get(&vals, vec, 2) < 0)
                GOTO_FAIL;
-       if (strcmp(vals, "2"))
+       if (vals == NULL || strcmp(vals, "2"))
                GOTO_FAIL;
 
        ec_vec_free(vec);
index 4a48d1e..1a6a0d3 100644 (file)
@@ -181,9 +181,9 @@ static void *debug_malloc(size_t size, const char *file, unsigned int line)
        struct debug_alloc_ftr *ftr;
        size_t new_size = size + sizeof(*hdr) + sizeof(*ftr);
        void *ret;
+       int r = random();
 
-
-       if (alloc_fail_proba != 0 && (random() % 100) < alloc_fail_proba)
+       if (alloc_fail_proba != 0 && (r % 100) < alloc_fail_proba)
                hdr = NULL;
        else
                hdr = malloc(new_size);
@@ -203,8 +203,10 @@ static void *debug_malloc(size_t size, const char *file, unsigned int line)
                ftr->cookie = 0x87654321;
        }
 
-       EC_LOG(EC_LOG_DEBUG, "%s:%d: info: malloc(%zd) -> %p\n",
-               file, line, size, ret);
+       EC_LOG(EC_LOG_DEBUG, "%s:%d: info: malloc(%zd) -> %p [rand=%d]\n",
+               file, line, size, ret, r);
+       if (r == 976499400)
+               printf("here\n");
 
        if (ret)
                alloc_success++;