cat-file: fix a common "struct object_context" memory leak
Fix a memory leak where "cat-file" will leak the "path" member. Seee5fba602e5
(textconv: support for cat_file, 2010-06-15) for the code that introduced the offending get_oid_with_context() call (called get_sha1_with_context() at the time). As a result we can mark several tests as passing with SANITIZE=leak using "TEST_PASSES_SANITIZE_LEAK=true". As noted indc944b65f1
(get_sha1_with_context: dynamically allocate oc->path, 2017-05-19) callers must free the "path" member. That same commit added the relevant free() to this function, but we weren't catching cases where we'd return early. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
55916bba0f
commit
27472b5195
@ -71,6 +71,7 @@ static int stream_blob(const struct object_id *oid)
|
|||||||
static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
|
static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
|
||||||
int unknown_type)
|
int unknown_type)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
struct object_id oid;
|
struct object_id oid;
|
||||||
enum object_type type;
|
enum object_type type;
|
||||||
char *buf;
|
char *buf;
|
||||||
@ -106,7 +107,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
|
|||||||
if (sb.len) {
|
if (sb.len) {
|
||||||
printf("%s\n", sb.buf);
|
printf("%s\n", sb.buf);
|
||||||
strbuf_release(&sb);
|
strbuf_release(&sb);
|
||||||
return 0;
|
ret = 0;
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -115,7 +117,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
|
|||||||
if (oid_object_info_extended(the_repository, &oid, &oi, flags) < 0)
|
if (oid_object_info_extended(the_repository, &oid, &oi, flags) < 0)
|
||||||
die("git cat-file: could not get object info");
|
die("git cat-file: could not get object info");
|
||||||
printf("%"PRIuMAX"\n", (uintmax_t)size);
|
printf("%"PRIuMAX"\n", (uintmax_t)size);
|
||||||
return 0;
|
ret = 0;
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
case 'e':
|
case 'e':
|
||||||
return !has_object_file(&oid);
|
return !has_object_file(&oid);
|
||||||
@ -123,8 +126,10 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
|
|||||||
case 'w':
|
case 'w':
|
||||||
|
|
||||||
if (filter_object(path, obj_context.mode,
|
if (filter_object(path, obj_context.mode,
|
||||||
&oid, &buf, &size))
|
&oid, &buf, &size)) {
|
||||||
return -1;
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
@ -143,11 +148,14 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
|
|||||||
const char *ls_args[3] = { NULL };
|
const char *ls_args[3] = { NULL };
|
||||||
ls_args[0] = "ls-tree";
|
ls_args[0] = "ls-tree";
|
||||||
ls_args[1] = obj_name;
|
ls_args[1] = obj_name;
|
||||||
return cmd_ls_tree(2, ls_args, NULL);
|
ret = cmd_ls_tree(2, ls_args, NULL);
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == OBJ_BLOB)
|
if (type == OBJ_BLOB) {
|
||||||
return stream_blob(&oid);
|
ret = stream_blob(&oid);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
buf = read_object_file(&oid, &type, &size);
|
buf = read_object_file(&oid, &type, &size);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
die("Cannot read object %s", obj_name);
|
die("Cannot read object %s", obj_name);
|
||||||
@ -172,8 +180,10 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
|
|||||||
} else
|
} else
|
||||||
oidcpy(&blob_oid, &oid);
|
oidcpy(&blob_oid, &oid);
|
||||||
|
|
||||||
if (oid_object_info(the_repository, &blob_oid, NULL) == OBJ_BLOB)
|
if (oid_object_info(the_repository, &blob_oid, NULL) == OBJ_BLOB) {
|
||||||
return stream_blob(&blob_oid);
|
ret = stream_blob(&blob_oid);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* we attempted to dereference a tag to a blob
|
* we attempted to dereference a tag to a blob
|
||||||
* and failed; there may be new dereference
|
* and failed; there may be new dereference
|
||||||
@ -193,9 +203,11 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
|
|||||||
die("git cat-file %s: bad file", obj_name);
|
die("git cat-file %s: bad file", obj_name);
|
||||||
|
|
||||||
write_or_die(1, buf, size);
|
write_or_die(1, buf, size);
|
||||||
|
ret = 0;
|
||||||
|
cleanup:
|
||||||
free(buf);
|
free(buf);
|
||||||
free(obj_context.path);
|
free(obj_context.path);
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct expand_data {
|
struct expand_data {
|
||||||
|
@ -5,6 +5,7 @@ test_description='working-tree-encoding conversion via gitattributes'
|
|||||||
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
||||||
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
. "$TEST_DIRECTORY/lib-encoding.sh"
|
. "$TEST_DIRECTORY/lib-encoding.sh"
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
test_description='test conversion filters on large files'
|
test_description='test conversion filters on large files'
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
set_attr() {
|
set_attr() {
|
||||||
|
@ -5,6 +5,7 @@ test_description='Test notes trees that also contain non-notes'
|
|||||||
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
||||||
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
number_of_commits=100
|
number_of_commits=100
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
test_description='test unique sha1 abbreviation on "index from..to" line'
|
test_description='test unique sha1 abbreviation on "index from..to" line'
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
test_expect_success 'setup' '
|
test_expect_success 'setup' '
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
test_description='git apply of i-t-a file'
|
test_description='git apply of i-t-a file'
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
test_expect_success setup '
|
test_expect_success setup '
|
||||||
|
@ -49,10 +49,10 @@ Then no matter which order we start looking at the packs in, we know that we
|
|||||||
will always find a delta for "file", because its lookup will always come
|
will always find a delta for "file", because its lookup will always come
|
||||||
immediately after the lookup for "dummy".
|
immediately after the lookup for "dummy".
|
||||||
'
|
'
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Create a pack containing the tree $1 and blob $1:file, with
|
# Create a pack containing the tree $1 and blob $1:file, with
|
||||||
# the latter stored as a delta against $2:file.
|
# the latter stored as a delta against $2:file.
|
||||||
#
|
#
|
||||||
|
@ -6,6 +6,7 @@ test_description="recursive merge corner cases w/ renames but not criss-crosses"
|
|||||||
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
||||||
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
. "$TEST_DIRECTORY"/lib-merge.sh
|
. "$TEST_DIRECTORY"/lib-merge.sh
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
test_description='git cat-file textconv support'
|
test_description='git cat-file textconv support'
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
cat >helper <<'EOF'
|
cat >helper <<'EOF'
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
test_description='git cat-file filters support'
|
test_description='git cat-file filters support'
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
test_expect_success 'setup ' '
|
test_expect_success 'setup ' '
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
test_description='git svn fetching'
|
test_description='git svn fetching'
|
||||||
|
|
||||||
TEST_FAILS_SANITIZE_LEAK=true
|
|
||||||
. ./lib-git-svn.sh
|
. ./lib-git-svn.sh
|
||||||
|
|
||||||
test_expect_success 'initialize repo' '
|
test_expect_success 'initialize repo' '
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
test_description='test that git handles an svn repository with empty symlinks'
|
test_description='test that git handles an svn repository with empty symlinks'
|
||||||
|
|
||||||
TEST_FAILS_SANITIZE_LEAK=true
|
|
||||||
. ./lib-git-svn.sh
|
. ./lib-git-svn.sh
|
||||||
test_expect_success 'load svn dumpfile' '
|
test_expect_success 'load svn dumpfile' '
|
||||||
svnadmin load "$rawsvnrepo" <<EOF
|
svnadmin load "$rawsvnrepo" <<EOF
|
||||||
|
@ -7,6 +7,7 @@ test_description='test git fast-import of notes objects'
|
|||||||
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
||||||
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user