From db06c7c61c5b3f40ca5a145b6842b25b550b30af Mon Sep 17 00:00:00 2001 From: Olivier Matz Date: Thu, 8 Mar 2018 19:14:45 +0100 Subject: [PATCH] save --- lib/ecoli_completed.c | 7 ++++-- lib/ecoli_log.c | 4 ++++ lib/ecoli_node.c | 19 ++++++--------- lib/ecoli_node.h | 3 --- lib/ecoli_node_cmd.c | 20 ++++++++-------- lib/ecoli_node_dynamic.c | 8 +++++-- lib/ecoli_node_expr_test.c | 2 +- lib/ecoli_node_file.c | 17 +++++++------- lib/ecoli_node_int.c | 18 +++++++------- lib/ecoli_node_once.c | 8 +++++-- lib/ecoli_node_option.c | 1 - lib/ecoli_node_or.c | 5 +--- lib/ecoli_node_seq.c | 1 - lib/ecoli_node_sh_lex.c | 12 +++++----- lib/ecoli_node_subset.c | 1 - lib/ecoli_node_weakref.c | 1 - lib/ecoli_parsed.c | 28 +++++++++++----------- lib/ecoli_string.c | 48 ++++++++++++++++++++++++++++++++++++++ lib/ecoli_string.h | 6 +++++ lib/ecoli_vec.c | 6 ++--- lib/main.c | 10 ++++---- 21 files changed, 140 insertions(+), 85 deletions(-) diff --git a/lib/ecoli_completed.c b/lib/ecoli_completed.c index 0159797..e44ba9e 100644 --- a/lib/ecoli_completed.c +++ b/lib/ecoli_completed.c @@ -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; diff --git a/lib/ecoli_log.c b/lib/ecoli_log.c index 92e2145..75ece93 100644 --- a/lib/ecoli_log.c +++ b/lib/ecoli_log.c @@ -32,6 +32,7 @@ #include #include +#include #include 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; diff --git a/lib/ecoli_node.c b/lib/ecoli_node.c index 458d6bc..17a18a8 100644 --- a/lib/ecoli_node.c +++ b/lib/ecoli_node.c @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -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) { diff --git a/lib/ecoli_node.h b/lib/ecoli_node.h index 5a25a1f..ac88033 100644 --- a/lib/ecoli_node.h +++ b/lib/ecoli_node.h @@ -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); diff --git a/lib/ecoli_node_cmd.c b/lib/ecoli_node_cmd.c index 85b97b2..5d47a7b 100644 --- a/lib/ecoli_node_cmd.c +++ b/lib/ecoli_node_cmd.c @@ -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; } diff --git a/lib/ecoli_node_dynamic.c b/lib/ecoli_node_dynamic.c index de99f1b..e4b538d 100644 --- a/lib/ecoli_node_dynamic.c +++ b/lib/ecoli_node_dynamic.c @@ -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); diff --git a/lib/ecoli_node_expr_test.c b/lib/ecoli_node_expr_test.c index 45c169e..935eec0 100644 --- a/lib/ecoli_node_expr_test.c +++ b/lib/ecoli_node_expr_test.c @@ -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, }; diff --git a/lib/ecoli_node_file.c b/lib/ecoli_node_file.c index a92c629..fbba156 100644 --- a/lib/ecoli_node_file.c +++ b/lib/ecoli_node_file.c @@ -25,7 +25,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define _GNU_SOURCE /* for asprintf */ #include #include #include @@ -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) diff --git a/lib/ecoli_node_int.c b/lib/ecoli_node_int.c index 9dae63a..b086c56 100644 --- a/lib/ecoli_node_int.c +++ b/lib/ecoli_node_int.c @@ -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); diff --git a/lib/ecoli_node_once.c b/lib/ecoli_node_once.c index 086f185..940ab4b 100644 --- a/lib/ecoli_node_once.c +++ b/lib/ecoli_node_once.c @@ -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 */ diff --git a/lib/ecoli_node_option.c b/lib/ecoli_node_option.c index 6f8d229..bc912ef 100644 --- a/lib/ecoli_node_option.c +++ b/lib/ecoli_node_option.c @@ -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; diff --git a/lib/ecoli_node_or.c b/lib/ecoli_node_or.c index ddf8281..c0d43e2 100644 --- a/lib/ecoli_node_or.c +++ b/lib/ecoli_node_or.c @@ -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; diff --git a/lib/ecoli_node_seq.c b/lib/ecoli_node_seq.c index e239bcf..f825d54 100644 --- a/lib/ecoli_node_seq.c +++ b/lib/ecoli_node_seq.c @@ -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; diff --git a/lib/ecoli_node_sh_lex.c b/lib/ecoli_node_sh_lex.c index 7f532fe..d2b73ab 100644 --- a/lib/ecoli_node_sh_lex.c +++ b/lib/ecoli_node_sh_lex.c @@ -25,7 +25,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define _GNU_SOURCE /* for asprintf */ #include #include #include @@ -36,6 +35,7 @@ #include #include +#include #include #include #include @@ -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; } diff --git a/lib/ecoli_node_subset.c b/lib/ecoli_node_subset.c index 5d8ca0a..9dc6020 100644 --- a/lib/ecoli_node_subset.c +++ b/lib/ecoli_node_subset.c @@ -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; diff --git a/lib/ecoli_node_weakref.c b/lib/ecoli_node_weakref.c index c598195..2a8f1f9 100644 --- a/lib/ecoli_node_weakref.c +++ b/lib/ecoli_node_weakref.c @@ -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? diff --git a/lib/ecoli_parsed.c b/lib/ecoli_parsed.c index 54bed70..b4b59e8 100644 --- a/lib/ecoli_parsed.c +++ b/lib/ecoli_parsed.c @@ -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, diff --git a/lib/ecoli_string.c b/lib/ecoli_string.c index 49e4a37..d51533f 100644 --- a/lib/ecoli_string.c +++ b/lib/ecoli_string.c @@ -25,9 +25,13 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include +#include +#include +#include #include /* 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; +} diff --git a/lib/ecoli_string.h b/lib/ecoli_string.h index ae92b4d..4df061d 100644 --- a/lib/ecoli_string.h +++ b/lib/ecoli_string.h @@ -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 diff --git a/lib/ecoli_vec.c b/lib/ecoli_vec.c index 8126526..b3249b5 100644 --- a/lib/ecoli_vec.c +++ b/lib/ecoli_vec.c @@ -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); diff --git a/lib/main.c b/lib/main.c index 4a48d1e..1a6a0d3 100644 --- a/lib/main.c +++ b/lib/main.c @@ -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++; -- 2.20.1