mirror of
https://github.com/git-for-windows/git.git
synced 2026-06-14 15:01:15 -05:00
cat-file: validate remote atoms with allow_list
strstr() is not enough to validate the format placeholders in remote-object-info causing two errors: - Atoms recognized by expand_atom() but the remote doesn't returns 1, but data->type contains garbage causing segfault. - expand_atom() returns 0 for unknown atoms, calling strbuf_expand_bad_format() which ends in die() blocking local queries if the same format is shared. Add an allow_list with the supported atoms at the top of expand_atom(). In remote mode, unsupported atoms return 1 leaving the sb empty, honoring how for-each-ref handles known but inapplicable atoms. As extra safety, initialize data->type to OBJ_BAD and add a NULL check for type_name() so uninitialized data doesn't cause segfault. Update tests that expect previous die() behaviour to expect an empty string and add an explicit test for empty string return on unknown placeholder. Update caveat behaviour documentation. Mentored-by: Karthik Nayak <karthik.188@gmail.com> Mentored-by: Chandra Pratap <chandrapratap3519@gmail.com> Signed-off-by: Pablo Sabater <pabloosabaterr@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
committed by
Junio C Hamano
parent
82b4ab8001
commit
5b591f977f
@@ -451,8 +451,9 @@ CAVEATS
|
||||
-------
|
||||
|
||||
Note that since %(objecttype), %(objectsize:disk) and %(deltabase) are
|
||||
currently not supported by the `remote-object-info` command, we will raise
|
||||
an error and exit when they appear in the format string.
|
||||
currently not supported by the `remote-object-info` command, they will
|
||||
return an empty string for remote queries, matching how `for-each-ref`
|
||||
behaves for known but inapplicable placeholders.
|
||||
|
||||
Note that the sizes of objects on disk are reported accurately, but care
|
||||
should be taken in drawing conclusions about which refs or objects are
|
||||
|
||||
@@ -336,8 +336,18 @@ struct expand_data {
|
||||
* optimized out.
|
||||
*/
|
||||
unsigned skip_object_info : 1;
|
||||
|
||||
/*
|
||||
* Flags about when an object info is being fetched from remote.
|
||||
*/
|
||||
unsigned is_remote:1;
|
||||
};
|
||||
#define EXPAND_DATA_INIT { .mode = S_IFINVALID, .type = OBJ_BAD }
|
||||
|
||||
static const char *remote_object_info_atoms[] = {
|
||||
"objectname",
|
||||
"objectsize",
|
||||
};
|
||||
#define EXPAND_DATA_INIT { .mode = S_IFINVALID }
|
||||
|
||||
static int is_atom(const char *atom, const char *s, int slen)
|
||||
{
|
||||
@@ -348,14 +358,31 @@ static int is_atom(const char *atom, const char *s, int slen)
|
||||
static int expand_atom(struct strbuf *sb, const char *atom, int len,
|
||||
struct expand_data *data)
|
||||
{
|
||||
if (data->is_remote) {
|
||||
size_t i, allowed_nr = ARRAY_SIZE(remote_object_info_atoms);
|
||||
for (i = 0; i < allowed_nr; i++)
|
||||
if (is_atom(remote_object_info_atoms[i], atom, len))
|
||||
break;
|
||||
|
||||
/*
|
||||
* On remote, skip unsupported atoms returning an empty sb,
|
||||
* honoring how for-each-ref handles known but inapplicable
|
||||
* atoms (e.g. %(tagger)).
|
||||
*/
|
||||
if (i == allowed_nr)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (is_atom("objectname", atom, len)) {
|
||||
if (!data->mark_query)
|
||||
strbuf_addstr(sb, oid_to_hex(&data->oid));
|
||||
} else if (is_atom("objecttype", atom, len)) {
|
||||
if (data->mark_query)
|
||||
if (data->mark_query) {
|
||||
data->info.typep = &data->type;
|
||||
else
|
||||
strbuf_addstr(sb, type_name(data->type));
|
||||
} else {
|
||||
const char *t = type_name(data->type);
|
||||
strbuf_addstr(sb, t ? t : "");
|
||||
}
|
||||
} else if (is_atom("objectsize", atom, len)) {
|
||||
if (data->mark_query)
|
||||
data->info.sizep = &data->size;
|
||||
@@ -699,10 +726,6 @@ static int get_remote_info(struct batch_options *opt,
|
||||
gtransport->smart_options->object_info = 1;
|
||||
gtransport->smart_options->object_info_oids = object_info_oids;
|
||||
|
||||
/* 'objectsize' is the only option currently supported */
|
||||
if (!strstr(opt->format, "%(objectsize)"))
|
||||
die(_("%s is currently not supported with remote-object-info"), opt->format);
|
||||
|
||||
string_list_append(&object_info_options, "size");
|
||||
|
||||
if (object_info_options.nr > 0) {
|
||||
@@ -832,7 +855,9 @@ static void parse_cmd_remote_object_info(struct batch_options *opt,
|
||||
*/
|
||||
data->size = *remote_object_info[i].sizep;
|
||||
opt->batch_mode = BATCH_MODE_INFO;
|
||||
data->is_remote = 1;
|
||||
batch_object_write(argv[i + 1], output, opt, data, NULL, 0);
|
||||
data->is_remote = 0;
|
||||
}
|
||||
}
|
||||
data->skip_object_info = 0;
|
||||
|
||||
@@ -205,6 +205,22 @@ info $tag_oid
|
||||
)
|
||||
'
|
||||
|
||||
# This tests depends on %(objecttype) not being supported yet, once supported
|
||||
# it needs to be updated.
|
||||
test_expect_success 'unsupported placeholder on remote returns empty string' '
|
||||
(
|
||||
set_transport_variables "$daemon_parent" &&
|
||||
cd "$daemon_parent/daemon_client_empty" &&
|
||||
|
||||
echo "" >expect &&
|
||||
|
||||
git cat-file --batch-command="%(objecttype)" >actual <<-EOF &&
|
||||
remote-object-info "$GIT_DAEMON_URL/parent" $hello_oid
|
||||
EOF
|
||||
test_cmp expect actual
|
||||
)
|
||||
'
|
||||
|
||||
# Test --batch-command remote-object-info with 'git://' and
|
||||
# transfer.advertiseobjectinfo set to false, i.e. server does not have object-info capability
|
||||
test_expect_success 'batch-command remote-object-info git:// fails when transfer.advertiseobjectinfo=false' '
|
||||
@@ -544,10 +560,12 @@ test_expect_success 'remote-object-info fails on unspported filter option (objec
|
||||
set_transport_variables "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" &&
|
||||
cd "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" &&
|
||||
|
||||
test_must_fail git cat-file --batch-command="%(objectsize:disk)" 2>err <<-EOF &&
|
||||
echo "$hello_oid " >expect &&
|
||||
|
||||
git cat-file --batch-command="%(objectname) %(objectsize:disk)" >actual <<-EOF &&
|
||||
remote-object-info "$HTTPD_URL/smart/http_parent" $hello_oid
|
||||
EOF
|
||||
test_grep "%(objectsize:disk) is currently not supported with remote-object-info" err
|
||||
test_cmp expect actual
|
||||
)
|
||||
'
|
||||
|
||||
@@ -556,10 +574,12 @@ test_expect_success 'remote-object-info fails on unspported filter option (delta
|
||||
set_transport_variables "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" &&
|
||||
cd "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" &&
|
||||
|
||||
test_must_fail git cat-file --batch-command="%(deltabase)" 2>err <<-EOF &&
|
||||
echo "" >expect &&
|
||||
|
||||
git cat-file --batch-command="%(deltabase)" >actual <<-EOF &&
|
||||
remote-object-info "$HTTPD_URL/smart/http_parent" $hello_oid
|
||||
EOF
|
||||
test_grep "%(deltabase) is currently not supported with remote-object-info" err
|
||||
test_cmp expect actual
|
||||
)
|
||||
'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user