Skip to content

Commit a0b8262

Browse files
pks-tgitster
authored andcommitted
builtin/fast-export: plug leaking tag names
When resolving revisions in `get_tags_and_duplicates()`, we only partially manage the lifetime of `full_name`. In fact, managing its lifetime properly is almost impossible because we put direct pointers to that variable into multiple lists without duplicating the string. The consequence is that these strings will ultimately leak. Refactor the code to make the lists we put those names into duplicate the memory. This allows us to properly free the string as required and thus plugs the memory leak. While this requires us to allocate more data overall, it shouldn't be all that bad given that the number of allocations corresponds with the number of command line parameters, which typically aren't all that many. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 8ed4e96 commit a0b8262

File tree

2 files changed

+13
-5
lines changed

2 files changed

+13
-5
lines changed

builtin/fast-export.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ static int full_tree;
4242
static int reference_excluded_commits;
4343
static int show_original_ids;
4444
static int mark_tags;
45-
static struct string_list extra_refs = STRING_LIST_INIT_NODUP;
46-
static struct string_list tag_refs = STRING_LIST_INIT_NODUP;
45+
static struct string_list extra_refs = STRING_LIST_INIT_DUP;
46+
static struct string_list tag_refs = STRING_LIST_INIT_DUP;
4747
static struct refspec refspecs = REFSPEC_INIT_FETCH;
4848
static int anonymize;
4949
static struct hashmap anonymized_seeds;
@@ -901,7 +901,7 @@ static void handle_tag(const char *name, struct tag *tag)
901901
free(buf);
902902
}
903903

904-
static struct commit *get_commit(struct rev_cmdline_entry *e, char *full_name)
904+
static struct commit *get_commit(struct rev_cmdline_entry *e, const char *full_name)
905905
{
906906
switch (e->item->type) {
907907
case OBJ_COMMIT:
@@ -932,14 +932,16 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
932932
struct rev_cmdline_entry *e = info->rev + i;
933933
struct object_id oid;
934934
struct commit *commit;
935-
char *full_name;
935+
char *full_name = NULL;
936936

937937
if (e->flags & UNINTERESTING)
938938
continue;
939939

940940
if (repo_dwim_ref(the_repository, e->name, strlen(e->name),
941-
&oid, &full_name, 0) != 1)
941+
&oid, &full_name, 0) != 1) {
942+
free(full_name);
942943
continue;
944+
}
943945

944946
if (refspecs.nr) {
945947
char *private;
@@ -955,6 +957,7 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
955957
warning("%s: Unexpected object of type %s, skipping.",
956958
e->name,
957959
type_name(e->item->type));
960+
free(full_name);
958961
continue;
959962
}
960963

@@ -963,10 +966,12 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
963966
break;
964967
case OBJ_BLOB:
965968
export_blob(&commit->object.oid);
969+
free(full_name);
966970
continue;
967971
default: /* OBJ_TAG (nested tags) is already handled */
968972
warning("Tag points to object of unexpected type %s, skipping.",
969973
type_name(commit->object.type));
974+
free(full_name);
970975
continue;
971976
}
972977

@@ -979,6 +984,8 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
979984

980985
if (!*revision_sources_at(&revision_sources, commit))
981986
*revision_sources_at(&revision_sources, commit) = full_name;
987+
else
988+
free(full_name);
982989
}
983990

984991
string_list_sort(&extra_refs);

t/t9351-fast-export-anonymize.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ test_description='basic tests for fast-export --anonymize'
44
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
55
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
66

7+
TEST_PASSES_SANITIZE_LEAK=true
78
. ./test-lib.sh
89

910
test_expect_success 'setup simple repo' '

0 commit comments

Comments
 (0)