diff options
author | Petr Machata <pmachata@redhat.com> | 2012-12-13 18:22:32 +0100 |
---|---|---|
committer | Petr Machata <pmachata@redhat.com> | 2013-03-08 22:55:30 +0100 |
commit | 7f1d856ea4882a23461886d0f589244cc11f0b2f (patch) | |
tree | 0794a3791a7dc7460e6f8cf122c26aae19dbcac4 /read_config_file.c | |
parent | 93eb0ee606dc4425cc2f1019f5e549acf77f40b0 (diff) | |
download | ltrace-7f1d856ea4882a23461886d0f589244cc11f0b2f.tar.gz |
Fix memory errors
With this, valgrind run of ltrace on x86_64 is clean.
Diffstat (limited to 'read_config_file.c')
-rw-r--r-- | read_config_file.c | 111 |
1 files changed, 61 insertions, 50 deletions
diff --git a/read_config_file.c b/read_config_file.c index 38b854a..7382adc 100644 --- a/read_config_file.c +++ b/read_config_file.c @@ -532,20 +532,33 @@ parse_struct(struct protolib *plib, struct locus *loc, } } +/* Make a copy of INFO and set the *OWN bit if it's not already + * owned. */ static int -parse_string(struct protolib *plib, struct locus *loc, - char **str, struct arg_type_info **retp, int *ownp) +unshare_type_info(struct locus *loc, struct arg_type_info **infop, int *ownp) { - struct arg_type_info *info = malloc(sizeof(*info) * 2); - if (info == NULL) { - fail: - free(info); + if (*ownp) + return 0; + + struct arg_type_info *ninfo = malloc(sizeof(*ninfo)); + if (ninfo == NULL) { + report_error(loc->filename, loc->line_no, + "malloc: %s", strerror(errno)); return -1; } + *ninfo = **infop; + *infop = ninfo; + *ownp = 1; + return 0; +} +static int +parse_string(struct protolib *plib, struct locus *loc, + char **str, struct arg_type_info **retp, int *ownp) +{ + struct arg_type_info *info = NULL; struct expr_node *length; int own_length; - int with_arg = 0; if (isdigit(CTYPE_CONV(**str))) { /* string0 is string[retval], length is zero(retval) @@ -553,11 +566,11 @@ parse_string(struct protolib *plib, struct locus *loc, long l; if (parse_int(loc, str, &l) < 0 || check_int(loc, l) < 0) - goto fail; + return -1; struct expr_node *length_arg = malloc(sizeof(*length_arg)); if (length_arg == NULL) - goto fail; + return -1; if (l == 0) expr_init_named(length_arg, "retval", 0); @@ -568,7 +581,7 @@ parse_string(struct protolib *plib, struct locus *loc, if (length == NULL) { expr_destroy(length_arg); free(length_arg); - goto fail; + return -1; } own_length = 1; @@ -580,7 +593,7 @@ parse_string(struct protolib *plib, struct locus *loc, length = parse_argnum(loc, str, &own_length, 1); if (length == NULL) - goto fail; + return -1; eat_spaces(str); parse_char(loc, str, ']'); @@ -589,18 +602,17 @@ parse_string(struct protolib *plib, struct locus *loc, /* Usage of "string" as lens. */ ++*str; - free(info); - eat_spaces(str); info = parse_type(plib, loc, str, NULL, 0, ownp, NULL); if (info == NULL) - goto fail; + return -1; + + length = NULL; + own_length = 0; eat_spaces(str); parse_char(loc, str, ')'); - with_arg = 1; - } else { /* It was just a simple string after all. */ length = expr_node_zero(); @@ -609,14 +621,35 @@ parse_string(struct protolib *plib, struct locus *loc, } /* String is a pointer to array of chars. */ - if (!with_arg) { - type_init_array(&info[1], type_get_simple(ARGTYPE_CHAR), 0, + if (info == NULL) { + struct arg_type_info *info1 = malloc(sizeof(*info1)); + struct arg_type_info *info2 = malloc(sizeof(*info2)); + if (info1 == NULL || info2 == NULL) { + free(info1); + free(info2); + fail: + if (own_length) { + assert(length != NULL); + expr_destroy(length); + free(length); + } + return -1; + } + type_init_array(info2, type_get_simple(ARGTYPE_CHAR), 0, length, own_length); + type_init_pointer(info1, info2, 1); - type_init_pointer(&info[0], &info[1], 0); + info = info1; *ownp = 1; } + /* We'll need to set the lens, so unshare. */ + if (unshare_type_info(loc, &info, ownp) < 0) + /* If unshare_type_info failed, it must have been as a + * result of cloning attempt because *OWNP was 0. + * Thus we don't need to destroy INFO. */ + goto fail; + info->lens = &string_lens; info->own_lens = 0; @@ -669,26 +702,6 @@ try_parse_kwd(char **str, const char *kwd) return -1; } -/* Make a copy of INFO and set the *OWN bit if it's not already - * owned. */ -static int -unshare_type_info(struct locus *loc, struct arg_type_info **infop, int *ownp) -{ - if (*ownp) - return 0; - - struct arg_type_info *ninfo = malloc(sizeof(*ninfo)); - if (ninfo == NULL) { - report_error(loc->filename, loc->line_no, - "malloc: %s", strerror(errno)); - return -1; - } - *ninfo = **infop; - *infop = ninfo; - *ownp = 1; - return 0; -} - /* XXX extra_param and param_num are a kludge to get in * backward-compatible support for "format" parameter type. The * latter is only valid if the former is non-NULL, which is only in @@ -875,20 +888,18 @@ parse_nonpointer_type(struct protolib *plib, struct locus *loc, const char *orig_str = *str; enum arg_type type; if (parse_arg_type(str, &type) < 0) { - struct arg_type_info *simple; - if (parse_alias(plib, loc, str, &simple, + struct arg_type_info *type; + if (parse_alias(plib, loc, str, &type, ownp, extra_param, param_num) < 0) return NULL; - if (simple == NULL) - simple = parse_typedef_name(plib, str); - if (simple != NULL) { - *ownp = 0; - return simple; - } + else if (type != NULL) + return type; - report_error(loc->filename, loc->line_no, - "unknown type around '%s'", orig_str); - return NULL; + *ownp = 0; + if ((type = parse_typedef_name(plib, str)) == NULL) + report_error(loc->filename, loc->line_no, + "unknown type around '%s'", orig_str); + return type; } /* For some types that's all we need. */ |