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>

Brandon Williams committed Jan 4, 2017 at 10:04 UTC 8aee769fa12ff0d3a4100c3d0359bc33e49db672
2 files changed +21 -6
pathspec.c
+19 -4
@@ -259,8 +259,9 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
259 }
260 strbuf_addstr(&sb, match);
261 item->original = strbuf_detach(&sb, NULL);
262 - } else
263 - item->original = elt;
262 + } else {
263 + item->original = xstrdup(elt);
264 + }
265 item->len = strlen(item->match);
266 item->prefix = prefixlen;
267
@@ -388,8 +389,8 @@ void parse_pathspec(struct pathspec *pathspec,
389 die("BUG: PATHSPEC_PREFER_CWD requires arguments");
390
391 pathspec->items = item = xcalloc(1, sizeof(*item));
391 - item->match = prefix;
392 - item->original = prefix;
392 + item->match = xstrdup(prefix);
393 + item->original = xstrdup(prefix);
394 item->nowildcard_len = item->len = strlen(prefix);
395 item->prefix = item->len;
396 pathspec->nr = 1;
@@ -453,13 +454,27 @@ void parse_pathspec(struct pathspec *pathspec,
454
455 void copy_pathspec(struct pathspec *dst, const struct pathspec *src)
456 {
457 + int i;
458 +
459 *dst = *src;
460 ALLOC_ARRAY(dst->items, dst->nr);
461 COPY_ARRAY(dst->items, src->items, dst->nr);
462 +
463 + for (i = 0; i < dst->nr; i++) {
464 + dst->items[i].match = xstrdup(src->items[i].match);
465 + dst->items[i].original = xstrdup(src->items[i].original);
466 + }
467 }
468
469 void clear_pathspec(struct pathspec *pathspec)
470 {
471 + int i;
472 +
473 + for (i = 0; i < pathspec->nr; i++) {
474 + free(pathspec->items[i].match);
475 + free(pathspec->items[i].original);
476 + }
477 free(pathspec->items);
478 pathspec->items = NULL;
479 + pathspec->nr = 0;
480 }
pathspec.h
+2 -2
@@ -25,8 +25,8 @@ struct pathspec {
25 unsigned magic;
26 int max_depth;
27 struct pathspec_item {
28 - const char *match;
29 - const char *original;
28 + char *match;
29 + char *original;
30 unsigned magic;
31 int len, prefix;
32 int nowildcard_len;