Skip to content

Commit aa86eeb

Browse files
jeffhostetlerdscho
authored andcommitted
gvfs-helper: ignore .idx files in prefetch multi-part responses
The GVFS cache server can return multiple pairs of (.pack, .idx) files. If both are provided, `gvfs-helper` assumes that they are valid without any validation. This might cause problems if the .pack file is corrupt inside the data stream. (This might happen if the cache server sends extra unexpected STDERR data or if the .pack file is corrupt on the cache server's disk.) All of the .pack file verification logic is already contained within `git index-pack`, so let's ignore the .idx from the data stream and force compute it. This defeats the purpose of some of the data cacheing on the cache server, but safety is more important. Signed-off-by: Jeff Hostetler <jeffhostetler@github.com>
1 parent b282ae7 commit aa86eeb

File tree

2 files changed

+24
-38
lines changed

2 files changed

+24
-38
lines changed

Diff for: gvfs-helper.c

+23-34
Original file line numberDiff line numberDiff line change
@@ -2126,7 +2126,6 @@ static void extract_packfile_from_multipack(
21262126
{
21272127
struct ph ph;
21282128
struct tempfile *tempfile_pack = NULL;
2129-
struct tempfile *tempfile_idx = NULL;
21302129
int result = -1;
21312130
int b_no_idx_in_multipack;
21322131
struct object_id packfile_checksum;
@@ -2160,16 +2159,14 @@ static void extract_packfile_from_multipack(
21602159
b_no_idx_in_multipack = (ph.idx_len == maximum_unsigned_value_of_type(uint64_t) ||
21612160
ph.idx_len == 0);
21622161

2163-
if (b_no_idx_in_multipack) {
2164-
my_create_tempfile(status, 0, "pack", &tempfile_pack, NULL, NULL);
2165-
if (!tempfile_pack)
2166-
goto done;
2167-
} else {
2168-
/* create a pair of tempfiles with the same basename */
2169-
my_create_tempfile(status, 0, "pack", &tempfile_pack, "idx", &tempfile_idx);
2170-
if (!tempfile_pack || !tempfile_idx)
2171-
goto done;
2172-
}
2162+
/*
2163+
* We are going to harden `gvfs-helper` here and ignore the .idx file
2164+
* if it is provided and always compute it locally so that we get the
2165+
* added verification that `git index-pack` provides.
2166+
*/
2167+
my_create_tempfile(status, 0, "pack", &tempfile_pack, NULL, NULL);
2168+
if (!tempfile_pack)
2169+
goto done;
21732170

21742171
/*
21752172
* Copy the current packfile from the open stream and capture
@@ -2196,38 +2193,31 @@ static void extract_packfile_from_multipack(
21962193

21972194
oid_to_hex_r(hex_checksum, &packfile_checksum);
21982195

2199-
if (b_no_idx_in_multipack) {
2200-
/*
2201-
* The server did not send the corresponding .idx, so
2202-
* we have to compute it ourselves.
2203-
*/
2204-
strbuf_addbuf(&temp_path_idx, &temp_path_pack);
2205-
strbuf_strip_suffix(&temp_path_idx, ".pack");
2206-
strbuf_addstr(&temp_path_idx, ".idx");
2196+
/*
2197+
* Always compute the .idx file from the .pack file.
2198+
*/
2199+
strbuf_addbuf(&temp_path_idx, &temp_path_pack);
2200+
strbuf_strip_suffix(&temp_path_idx, ".pack");
2201+
strbuf_addstr(&temp_path_idx, ".idx");
22072202

2208-
my_run_index_pack(params, status,
2209-
&temp_path_pack, &temp_path_idx,
2210-
NULL);
2211-
if (status->ec != GH__ERROR_CODE__OK)
2212-
goto done;
2203+
my_run_index_pack(params, status,
2204+
&temp_path_pack, &temp_path_idx,
2205+
NULL);
2206+
if (status->ec != GH__ERROR_CODE__OK)
2207+
goto done;
22132208

2214-
} else {
2209+
if (!b_no_idx_in_multipack) {
22152210
/*
22162211
* Server sent the .idx immediately after the .pack in the
2217-
* data stream. I'm tempted to verify it, but that defeats
2218-
* the purpose of having it cached...
2212+
* data stream. Skip over it.
22192213
*/
2220-
if (my_copy_fd_len(fd_multipack, get_tempfile_fd(tempfile_idx),
2221-
ph.idx_len) < 0) {
2214+
if (lseek(fd_multipack, ph.idx_len, SEEK_CUR) < 0) {
22222215
strbuf_addf(&status->error_message,
2223-
"could not extract index[%d] in multipack",
2216+
"could not skip index[%d] in multipack",
22242217
k);
22252218
status->ec = GH__ERROR_CODE__COULD_NOT_INSTALL_PREFETCH;
22262219
goto done;
22272220
}
2228-
2229-
strbuf_addstr(&temp_path_idx, get_tempfile_path(tempfile_idx));
2230-
close_tempfile_gently(tempfile_idx);
22312221
}
22322222

22332223
strbuf_addf(&buf_timestamp, "%u", (unsigned int)ph.timestamp);
@@ -2243,7 +2233,6 @@ static void extract_packfile_from_multipack(
22432233

22442234
done:
22452235
delete_tempfile(&tempfile_pack);
2246-
delete_tempfile(&tempfile_idx);
22472236
strbuf_release(&temp_path_pack);
22482237
strbuf_release(&temp_path_idx);
22492238
strbuf_release(&final_path_pack);

Diff for: t/t5799-gvfs-helper.sh

+1-4
Original file line numberDiff line numberDiff line change
@@ -1367,14 +1367,11 @@ test_expect_success 'prefetch corrupt pack without idx' '
13671367

13681368
# Send corrupt PACK files with IDX files. Since the cache server
13691369
# sends both, `gvfs-helper` might fail to verify both of them.
1370-
test_expect_failure 'prefetch corrupt pack with corrupt idx' '
1370+
test_expect_success 'prefetch corrupt pack with corrupt idx' '
13711371
test_when_finished "per_test_cleanup" &&
13721372
start_gvfs_protocol_server_with_mayhem \
13731373
bad_prefetch_pack_sha &&
13741374
1375-
# TODO This is a false-positive since `gvfs-helper`
1376-
# TODO does not verify either of them when a pair
1377-
# TODO is sent.
13781375
test_must_fail \
13791376
git -C "$REPO_T1" gvfs-helper \
13801377
--cache-server=disable \

0 commit comments

Comments
 (0)