Fix bug in `expr_clone`
[platform/upstream/ltrace.git] / read_config_file.c
index 980b89b..e9c050d 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of ltrace.
- * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2011,2012,2013,2014 Petr Machata, Red Hat Inc.
  * Copyright (C) 1998,1999,2003,2007,2008,2009 Juan Cespedes
  * Copyright (C) 2006 Ian Wienand
  * Copyright (C) 2006 Steve Fink
@@ -168,38 +168,6 @@ parse_ident(struct locus *loc, char **str)
        return xstrndup(ident, *str - ident);
 }
 
-/*
-  Returns position in string at the left parenthesis which starts the
-  function's argument signature. Returns NULL on error.
-*/
-static char *
-start_of_arg_sig(char *str) {
-       char *pos;
-       int stacked = 0;
-
-       if (!strlen(str))
-               return NULL;
-
-       pos = &str[strlen(str)];
-       do {
-               pos--;
-               if (pos < str)
-                       return NULL;
-               while ((pos > str) && (*pos != ')') && (*pos != '('))
-                       pos--;
-
-               if (*pos == ')')
-                       stacked++;
-               else if (*pos == '(')
-                       stacked--;
-               else
-                       return NULL;
-
-       } while (stacked > 0);
-
-       return (stacked == 0) ? pos : NULL;
-}
-
 static int
 parse_int(struct locus *loc, char **str, long *ret)
 {
@@ -541,12 +509,12 @@ unshare_type_info(struct locus *loc, struct arg_type_info **infop, int *ownp)
                return 0;
 
        struct arg_type_info *ninfo = malloc(sizeof(*ninfo));
-       if (ninfo == NULL) {
+       if (ninfo == NULL || type_clone(ninfo, *infop) < 0) {
                report_error(loc->filename, loc->line_no,
                             "malloc: %s", strerror(errno));
+               free(ninfo);
                return -1;
        }
-       *ninfo = **infop;
        *infop = ninfo;
        *ownp = 1;
        return 0;
@@ -678,6 +646,7 @@ build_printf_pack(struct locus *loc, struct param **packp, size_t param_num)
        struct expr_node *node = malloc(sizeof(*node));
        if (node == NULL) {
                free(*packp);
+               *packp = NULL;
                return -1;
        }
 
@@ -695,14 +664,15 @@ try_parse_kwd(char **str, const char *kwd)
 {
        size_t len = strlen(kwd);
        if (strncmp(*str, kwd, len) == 0
-           && !isalnum(CTYPE_CONV((*str)[len]))) {
+           && !isalnum(CTYPE_CONV((*str)[len]))
+           && (*str)[len] != '_') {
                (*str) += len;
                return 0;
        }
        return -1;
 }
 
-/* XXX extra_param and param_num are a kludge to get in
+/* 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
  * top-level context.  */
@@ -1108,7 +1078,6 @@ static int
 process_line(struct protolib *plib, struct locus *loc, char *buf)
 {
        char *str = buf;
-       char *tmp;
 
        debug(3, "Reading line %d of `%s'", loc->line_no, loc->filename);
        eat_spaces(&str);
@@ -1125,12 +1094,19 @@ process_line(struct protolib *plib, struct locus *loc, char *buf)
        struct prototype fun;
        prototype_init(&fun);
 
+       struct param *extra_param = NULL;
        char *proto_name = NULL;
        int own;
        fun.return_info = parse_lens(plib, loc, &str, NULL, 0, &own, NULL);
        if (fun.return_info == NULL) {
        err:
                debug(3, " Skipping line %d", loc->line_no);
+
+               if (extra_param != NULL) {
+                       param_destroy(extra_param);
+                       free(extra_param);
+               }
+
                prototype_destroy(&fun);
                free(proto_name);
                return -1;
@@ -1139,25 +1115,15 @@ process_line(struct protolib *plib, struct locus *loc, char *buf)
        debug(4, " return_type = %d", fun.return_info->type);
 
        eat_spaces(&str);
-       tmp = start_of_arg_sig(str);
-       if (tmp == NULL) {
-               report_error(loc->filename, loc->line_no, "syntax error");
+       proto_name = parse_ident(loc, &str);
+       if (proto_name == NULL)
                goto err;
-       }
-       *tmp = '\0';
 
-       proto_name = strdup(str);
-       if (proto_name == NULL) {
-       oom:
-               report_error(loc->filename, loc->line_no,
-                            "%s", strerror(errno));
+       eat_spaces(&str);
+       if (parse_char(loc, &str, '(') < 0)
                goto err;
-       }
-
-       str = tmp + 1;
        debug(3, " name = %s", proto_name);
 
-       struct param *extra_param = NULL;
        int have_stop = 0;
 
        while (1) {
@@ -1169,8 +1135,13 @@ process_line(struct protolib *plib, struct locus *loc, char *buf)
                        if (have_stop == 0) {
                                struct param param;
                                param_init_stop(&param);
-                               if (prototype_push_param(&fun, &param) < 0)
-                                       goto oom;
+                               if (prototype_push_param(&fun, &param) < 0) {
+                               oom:
+                                       report_error(loc->filename,
+                                                    loc->line_no,
+                                                    "%s", strerror(errno));
+                                       goto err;
+                               }
                                have_stop = 1;
                        }
                        str++;
@@ -1235,6 +1206,7 @@ process_line(struct protolib *plib, struct locus *loc, char *buf)
        if (extra_param != NULL) {
                prototype_push_param(&fun, extra_param);
                free(extra_param);
+               extra_param = NULL;
        }
 
        if (protolib_add_prototype(plib, proto_name, 1, &fun) < 0) {