The 'original' string entry in a pathspec_item is only duplicated some
of the time, instead always make a copy of the original and take
ownership of the memory.

Since both 'match' and 'original' string entries in a pathspec_item are
owned by the pathspec struct, they need to be freed when clearing the
pathspec struct (in 'clear_pathspec()') and duplicated when copying the
pathspec struct (in 'copy_pathspec()').

Also change the type of 'match' and 'original' to 'char *' in order to
more explicitly show the ownership of the memory.

Signed-off-by: Brandon Williams <bmw...@google.com>
---
 pathspec.c | 23 +++++++++++++++++++----
 pathspec.h |  4 ++--
 2 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/pathspec.c b/pathspec.c
index 1f918cbae..b8faa8f46 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -259,8 +259,9 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
                }
                strbuf_addstr(&sb, match);
                item->original = strbuf_detach(&sb, NULL);
-       } else
-               item->original = elt;
+       } else {
+               item->original = xstrdup(elt);
+       }
        item->len = strlen(item->match);
        item->prefix = prefixlen;
 
@@ -388,8 +389,8 @@ void parse_pathspec(struct pathspec *pathspec,
                        die("BUG: PATHSPEC_PREFER_CWD requires arguments");
 
                pathspec->items = item = xcalloc(1, sizeof(*item));
-               item->match = prefix;
-               item->original = prefix;
+               item->match = xstrdup(prefix);
+               item->original = xstrdup(prefix);
                item->nowildcard_len = item->len = strlen(prefix);
                item->prefix = item->len;
                pathspec->nr = 1;
@@ -453,13 +454,27 @@ void parse_pathspec(struct pathspec *pathspec,
 
 void copy_pathspec(struct pathspec *dst, const struct pathspec *src)
 {
+       int i;
+
        *dst = *src;
        ALLOC_ARRAY(dst->items, dst->nr);
        COPY_ARRAY(dst->items, src->items, dst->nr);
+
+       for (i = 0; i < dst->nr; i++) {
+               dst->items[i].match = xstrdup(src->items[i].match);
+               dst->items[i].original = xstrdup(src->items[i].original);
+       }
 }
 
 void clear_pathspec(struct pathspec *pathspec)
 {
+       int i;
+
+       for (i = 0; i < pathspec->nr; i++) {
+               free(pathspec->items[i].match);
+               free(pathspec->items[i].original);
+       }
        free(pathspec->items);
        pathspec->items = NULL;
+       pathspec->nr = 0;
 }
diff --git a/pathspec.h b/pathspec.h
index 70a592e91..49fd823dd 100644
--- a/pathspec.h
+++ b/pathspec.h
@@ -25,8 +25,8 @@ struct pathspec {
        unsigned magic;
        int max_depth;
        struct pathspec_item {
-               const char *match;
-               const char *original;
+               char *match;
+               char *original;
                unsigned magic;
                int len, prefix;
                int nowildcard_len;
-- 
2.11.0.390.gc69c2f50cf-goog

Reply via email to