Skip to content

Commit 2901bbe

Browse files
committed
apply: free patch->{def,old,new}_name fields
These were all allocated in the heap by parsing the header parts of the patch, but we did not bother to free them. Some used to share the memory (e.g. copying def_name to old_name) so this is not just the matter of adding three calls to free(). Signed-off-by: Junio C Hamano <[email protected]>
1 parent a604dde commit 2901bbe

File tree

1 file changed

+39
-26
lines changed

1 file changed

+39
-26
lines changed

builtin/apply.c

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ static void free_patch(struct patch *patch)
207207
free(fragment);
208208
fragment = fragment_next;
209209
}
210+
free(patch->def_name);
211+
free(patch->old_name);
212+
free(patch->new_name);
210213
free(patch);
211214
}
212215

@@ -439,7 +442,7 @@ static char *squash_slash(char *name)
439442
return name;
440443
}
441444

442-
static char *find_name_gnu(const char *line, char *def, int p_value)
445+
static char *find_name_gnu(const char *line, const char *def, int p_value)
443446
{
444447
struct strbuf name = STRBUF_INIT;
445448
char *cp;
@@ -462,11 +465,7 @@ static char *find_name_gnu(const char *line, char *def, int p_value)
462465
cp++;
463466
}
464467

465-
/* name can later be freed, so we need
466-
* to memmove, not just return cp
467-
*/
468468
strbuf_remove(&name, 0, cp - name.buf);
469-
free(def);
470469
if (root)
471470
strbuf_insert(&name, 0, root, root_len);
472471
return squash_slash(strbuf_detach(&name, NULL));
@@ -631,8 +630,13 @@ static size_t diff_timestamp_len(const char *line, size_t len)
631630
return line + len - end;
632631
}
633632

634-
static char *find_name_common(const char *line, char *def, int p_value,
635-
const char *end, int terminate)
633+
static char *null_strdup(const char *s)
634+
{
635+
return s ? xstrdup(s) : NULL;
636+
}
637+
638+
static char *find_name_common(const char *line, const char *def,
639+
int p_value, const char *end, int terminate)
636640
{
637641
int len;
638642
const char *start = NULL;
@@ -653,10 +657,10 @@ static char *find_name_common(const char *line, char *def, int p_value,
653657
start = line;
654658
}
655659
if (!start)
656-
return squash_slash(def);
660+
return squash_slash(null_strdup(def));
657661
len = line - start;
658662
if (!len)
659-
return squash_slash(def);
663+
return squash_slash(null_strdup(def));
660664

661665
/*
662666
* Generally we prefer the shorter name, especially
@@ -667,8 +671,7 @@ static char *find_name_common(const char *line, char *def, int p_value,
667671
if (def) {
668672
int deflen = strlen(def);
669673
if (deflen < len && !strncmp(start, def, deflen))
670-
return squash_slash(def);
671-
free(def);
674+
return squash_slash(xstrdup(def));
672675
}
673676

674677
if (root) {
@@ -865,8 +868,10 @@ static void parse_traditional_patch(const char *first, const char *second, struc
865868
name = find_name_traditional(first, NULL, p_value);
866869
patch->old_name = name;
867870
} else {
868-
name = find_name_traditional(first, NULL, p_value);
869-
name = find_name_traditional(second, name, p_value);
871+
char *first_name;
872+
first_name = find_name_traditional(first, NULL, p_value);
873+
name = find_name_traditional(second, first_name, p_value);
874+
free(first_name);
870875
if (has_epoch_timestamp(first)) {
871876
patch->is_new = 1;
872877
patch->is_delete = 0;
@@ -876,7 +881,8 @@ static void parse_traditional_patch(const char *first, const char *second, struc
876881
patch->is_delete = 1;
877882
patch->old_name = name;
878883
} else {
879-
patch->old_name = patch->new_name = name;
884+
patch->old_name = name;
885+
patch->new_name = xstrdup(name);
880886
}
881887
}
882888
if (!name)
@@ -926,13 +932,19 @@ static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name,
926932

927933
static int gitdiff_oldname(const char *line, struct patch *patch)
928934
{
935+
char *orig = patch->old_name;
929936
patch->old_name = gitdiff_verify_name(line, patch->is_new, patch->old_name, "old");
937+
if (orig != patch->old_name)
938+
free(orig);
930939
return 0;
931940
}
932941

933942
static int gitdiff_newname(const char *line, struct patch *patch)
934943
{
944+
char *orig = patch->new_name;
935945
patch->new_name = gitdiff_verify_name(line, patch->is_delete, patch->new_name, "new");
946+
if (orig != patch->new_name)
947+
free(orig);
936948
return 0;
937949
}
938950

@@ -951,41 +963,47 @@ static int gitdiff_newmode(const char *line, struct patch *patch)
951963
static int gitdiff_delete(const char *line, struct patch *patch)
952964
{
953965
patch->is_delete = 1;
954-
patch->old_name = patch->def_name;
966+
free(patch->old_name);
967+
patch->old_name = null_strdup(patch->def_name);
955968
return gitdiff_oldmode(line, patch);
956969
}
957970

958971
static int gitdiff_newfile(const char *line, struct patch *patch)
959972
{
960973
patch->is_new = 1;
961-
patch->new_name = patch->def_name;
974+
free(patch->new_name);
975+
patch->new_name = null_strdup(patch->def_name);
962976
return gitdiff_newmode(line, patch);
963977
}
964978

965979
static int gitdiff_copysrc(const char *line, struct patch *patch)
966980
{
967981
patch->is_copy = 1;
982+
free(patch->old_name);
968983
patch->old_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0);
969984
return 0;
970985
}
971986

972987
static int gitdiff_copydst(const char *line, struct patch *patch)
973988
{
974989
patch->is_copy = 1;
990+
free(patch->new_name);
975991
patch->new_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0);
976992
return 0;
977993
}
978994

979995
static int gitdiff_renamesrc(const char *line, struct patch *patch)
980996
{
981997
patch->is_rename = 1;
998+
free(patch->old_name);
982999
patch->old_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0);
9831000
return 0;
9841001
}
9851002

9861003
static int gitdiff_renamedst(const char *line, struct patch *patch)
9871004
{
9881005
patch->is_rename = 1;
1006+
free(patch->new_name);
9891007
patch->new_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0);
9901008
return 0;
9911009
}
@@ -1426,7 +1444,8 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc
14261444
if (!patch->def_name)
14271445
die("git diff header lacks filename information when removing "
14281446
"%d leading pathname components (line %d)" , p_value, linenr);
1429-
patch->old_name = patch->new_name = patch->def_name;
1447+
patch->old_name = xstrdup(patch->def_name);
1448+
patch->new_name = xstrdup(patch->def_name);
14301449
}
14311450
if (!patch->is_delete && !patch->new_name)
14321451
die("git diff header lacks filename information "
@@ -3109,6 +3128,7 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
31093128
is_new:
31103129
patch->is_new = 1;
31113130
patch->is_delete = 0;
3131+
free(patch->old_name);
31123132
patch->old_name = NULL;
31133133
return 0;
31143134
}
@@ -3689,15 +3709,8 @@ static void prefix_patches(struct patch *p)
36893709
if (!prefix || p->is_toplevel_relative)
36903710
return;
36913711
for ( ; p; p = p->next) {
3692-
if (p->new_name == p->old_name) {
3693-
char *prefixed = p->new_name;
3694-
prefix_one(&prefixed);
3695-
p->new_name = p->old_name = prefixed;
3696-
}
3697-
else {
3698-
prefix_one(&p->new_name);
3699-
prefix_one(&p->old_name);
3700-
}
3712+
prefix_one(&p->new_name);
3713+
prefix_one(&p->old_name);
37013714
}
37023715
}
37033716

0 commit comments

Comments
 (0)