pathspec: copy and free owned memory

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 <bmwill@google.com>
Reviewed-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Brandon Williams 2017-01-04 10:04:01 -08:00 committed by Junio C Hamano
parent 34305f7753
commit 8aee769fa1
2 changed files with 21 additions and 6 deletions

View File

@ -259,8 +259,9 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
} }
strbuf_addstr(&sb, match); strbuf_addstr(&sb, match);
item->original = strbuf_detach(&sb, NULL); item->original = strbuf_detach(&sb, NULL);
} else } else {
item->original = elt; item->original = xstrdup(elt);
}
item->len = strlen(item->match); item->len = strlen(item->match);
item->prefix = prefixlen; item->prefix = prefixlen;
@ -388,8 +389,8 @@ void parse_pathspec(struct pathspec *pathspec,
die("BUG: PATHSPEC_PREFER_CWD requires arguments"); die("BUG: PATHSPEC_PREFER_CWD requires arguments");
pathspec->items = item = xcalloc(1, sizeof(*item)); pathspec->items = item = xcalloc(1, sizeof(*item));
item->match = prefix; item->match = xstrdup(prefix);
item->original = prefix; item->original = xstrdup(prefix);
item->nowildcard_len = item->len = strlen(prefix); item->nowildcard_len = item->len = strlen(prefix);
item->prefix = item->len; item->prefix = item->len;
pathspec->nr = 1; pathspec->nr = 1;
@ -453,13 +454,27 @@ void parse_pathspec(struct pathspec *pathspec,
void copy_pathspec(struct pathspec *dst, const struct pathspec *src) void copy_pathspec(struct pathspec *dst, const struct pathspec *src)
{ {
int i;
*dst = *src; *dst = *src;
ALLOC_ARRAY(dst->items, dst->nr); ALLOC_ARRAY(dst->items, dst->nr);
COPY_ARRAY(dst->items, src->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) 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); free(pathspec->items);
pathspec->items = NULL; pathspec->items = NULL;
pathspec->nr = 0;
} }

View File

@ -25,8 +25,8 @@ struct pathspec {
unsigned magic; unsigned magic;
int max_depth; int max_depth;
struct pathspec_item { struct pathspec_item {
const char *match; char *match;
const char *original; char *original;
unsigned magic; unsigned magic;
int len, prefix; int len, prefix;
int nowildcard_len; int nowildcard_len;