list-objects-filter: disable 'sparse:path' filters
If someone wants to use as a filter a sparse file that is in the repository, something like "--filter=sparse:oid=<ref>:<path>" already works. So 'sparse:path' is only interesting if the sparse file is not in the repository. In this case though the current implementation has a big security issue, as it makes it possible to ask the server to read any file, like for example /etc/password, and to explore the filesystem, as well as individual lines of files. If someone is interested in using a sparse file that is not in the repository as a filter, then at the minimum a config option, such as "uploadpack.sparsePathFilter", should be implemented first to restrict the directory from which the files specified by 'sparse:path' can be read. For now though, let's just disable 'sparse:path' filters. Helped-by: Matthew DeVore <matvore@google.com> Helped-by: Jeff Hostetler <git@jeffhostetler.com> Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									aa25c82427
								
							
						
					
					
						commit
						e693237e2b
					
				| 
						 | 
				
			
			@ -725,9 +725,6 @@ specification contained in the blob (or blob-expression) '<blob-ish>'
 | 
			
		|||
to omit blobs that would not be not required for a sparse checkout on
 | 
			
		||||
the requested refs.
 | 
			
		||||
+
 | 
			
		||||
The form '--filter=sparse:path=<path>' similarly uses a sparse-checkout
 | 
			
		||||
specification contained in <path>.
 | 
			
		||||
+
 | 
			
		||||
The form '--filter=tree:<depth>' omits all blobs and trees whose depth
 | 
			
		||||
from the root tree is >= <depth> (minimum depth if an object is located
 | 
			
		||||
at multiple depths in the commits traversed). <depth>=0 will not include
 | 
			
		||||
| 
						 | 
				
			
			@ -737,6 +734,10 @@ tree and blobs which are referenced directly by a commit reachable from
 | 
			
		|||
<commit> or an explicitly-given object. <depth>=2 is like <depth>=1
 | 
			
		||||
while also including trees and blobs one more level removed from an
 | 
			
		||||
explicitly-given commit or tree.
 | 
			
		||||
+
 | 
			
		||||
Note that the form '--filter=sparse:path=<path>' that wants to read
 | 
			
		||||
from an arbitrary path on the filesystem has been dropped for security
 | 
			
		||||
reasons.
 | 
			
		||||
 | 
			
		||||
--no-filter::
 | 
			
		||||
	Turn off any previous `--filter=` argument.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1536,7 +1536,7 @@ _git_fetch ()
 | 
			
		|||
		return
 | 
			
		||||
		;;
 | 
			
		||||
	--filter=*)
 | 
			
		||||
		__gitcomp "blob:none blob:limit= sparse:oid= sparse:path=" "" "${cur##--filter=}"
 | 
			
		||||
		__gitcomp "blob:none blob:limit= sparse:oid=" "" "${cur##--filter=}"
 | 
			
		||||
		return
 | 
			
		||||
		;;
 | 
			
		||||
	--*)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,9 +78,12 @@ static int gently_parse_list_objects_filter(
 | 
			
		|||
		return 0;
 | 
			
		||||
 | 
			
		||||
	} else if (skip_prefix(arg, "sparse:path=", &v0)) {
 | 
			
		||||
		filter_options->choice = LOFC_SPARSE_PATH;
 | 
			
		||||
		filter_options->sparse_path_value = strdup(v0);
 | 
			
		||||
		return 0;
 | 
			
		||||
		if (errbuf) {
 | 
			
		||||
			strbuf_addstr(
 | 
			
		||||
				errbuf,
 | 
			
		||||
				_("sparse:path filters support has been dropped"));
 | 
			
		||||
		}
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
	/*
 | 
			
		||||
	 * Please update _git_fetch() in git-completion.bash when you
 | 
			
		||||
| 
						 | 
				
			
			@ -136,7 +139,6 @@ void list_objects_filter_release(
 | 
			
		|||
{
 | 
			
		||||
	free(filter_options->filter_spec);
 | 
			
		||||
	free(filter_options->sparse_oid_value);
 | 
			
		||||
	free(filter_options->sparse_path_value);
 | 
			
		||||
	memset(filter_options, 0, sizeof(*filter_options));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,6 @@ enum list_objects_filter_choice {
 | 
			
		|||
	LOFC_BLOB_LIMIT,
 | 
			
		||||
	LOFC_TREE_DEPTH,
 | 
			
		||||
	LOFC_SPARSE_OID,
 | 
			
		||||
	LOFC_SPARSE_PATH,
 | 
			
		||||
	LOFC__COUNT /* must be last */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -44,7 +43,6 @@ struct list_objects_filter_options {
 | 
			
		|||
	 * choice.
 | 
			
		||||
	 */
 | 
			
		||||
	struct object_id *sparse_oid_value;
 | 
			
		||||
	char *sparse_path_value;
 | 
			
		||||
	unsigned long blob_limit_value;
 | 
			
		||||
	unsigned long tree_exclude_depth;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -478,27 +478,6 @@ static void *filter_sparse_oid__init(
 | 
			
		|||
	return d;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void *filter_sparse_path__init(
 | 
			
		||||
	struct oidset *omitted,
 | 
			
		||||
	struct list_objects_filter_options *filter_options,
 | 
			
		||||
	filter_object_fn *filter_fn,
 | 
			
		||||
	filter_free_fn *filter_free_fn)
 | 
			
		||||
{
 | 
			
		||||
	struct filter_sparse_data *d = xcalloc(1, sizeof(*d));
 | 
			
		||||
	d->omits = omitted;
 | 
			
		||||
	if (add_excludes_from_file_to_list(filter_options->sparse_path_value,
 | 
			
		||||
					   NULL, 0, &d->el, NULL) < 0)
 | 
			
		||||
		die("could not load filter specification");
 | 
			
		||||
 | 
			
		||||
	ALLOC_GROW(d->array_frame, d->nr + 1, d->alloc);
 | 
			
		||||
	d->array_frame[d->nr].defval = 0; /* default to include */
 | 
			
		||||
	d->array_frame[d->nr].child_prov_omit = 0;
 | 
			
		||||
 | 
			
		||||
	*filter_fn = filter_sparse;
 | 
			
		||||
	*filter_free_fn = filter_sparse_free;
 | 
			
		||||
	return d;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef void *(*filter_init_fn)(
 | 
			
		||||
	struct oidset *omitted,
 | 
			
		||||
	struct list_objects_filter_options *filter_options,
 | 
			
		||||
| 
						 | 
				
			
			@ -514,7 +493,6 @@ static filter_init_fn s_filters[] = {
 | 
			
		|||
	filter_blobs_limit__init,
 | 
			
		||||
	filter_trees_depth__init,
 | 
			
		||||
	filter_sparse_oid__init,
 | 
			
		||||
	filter_sparse_path__init,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void *list_objects_filter__init(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -277,6 +277,10 @@ test_expect_success 'verify normal and blob:limit packfiles have same commits/tr
 | 
			
		|||
'
 | 
			
		||||
 | 
			
		||||
# Test sparse:path=<path> filter.
 | 
			
		||||
# !!!!
 | 
			
		||||
# NOTE: sparse:path filter support has been dropped for security reasons,
 | 
			
		||||
# so the tests have been changed to make sure that using it fails.
 | 
			
		||||
# !!!!
 | 
			
		||||
# Use a local file containing a sparse-checkout specification to filter
 | 
			
		||||
# out blobs not required for the corresponding sparse-checkout.  We do not
 | 
			
		||||
# require sparse-checkout to actually be enabled.
 | 
			
		||||
| 
						 | 
				
			
			@ -315,73 +319,24 @@ test_expect_success 'verify blob count in normal packfile' '
 | 
			
		|||
	test_cmp expected observed
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'verify sparse:path=pattern1' '
 | 
			
		||||
	git -C r3 ls-files -s dir1/sparse1 dir1/sparse2 >ls_files_result &&
 | 
			
		||||
	awk -f print_2.awk ls_files_result |
 | 
			
		||||
	sort >expected &&
 | 
			
		||||
 | 
			
		||||
	git -C r3 pack-objects --revs --stdout --filter=sparse:path=../pattern1 >filter.pack <<-EOF &&
 | 
			
		||||
test_expect_success 'verify sparse:path=pattern1 fails' '
 | 
			
		||||
	test_must_fail git -C r3 pack-objects --revs --stdout \
 | 
			
		||||
		--filter=sparse:path=../pattern1 <<-EOF
 | 
			
		||||
	HEAD
 | 
			
		||||
	EOF
 | 
			
		||||
	git -C r3 index-pack ../filter.pack &&
 | 
			
		||||
 | 
			
		||||
	git -C r3 verify-pack -v ../filter.pack >verify_result &&
 | 
			
		||||
	grep blob verify_result |
 | 
			
		||||
	awk -f print_1.awk |
 | 
			
		||||
	sort >observed &&
 | 
			
		||||
 | 
			
		||||
	test_cmp expected observed
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'verify normal and sparse:path=pattern1 packfiles have same commits/trees' '
 | 
			
		||||
	git -C r3 verify-pack -v ../all.pack >verify_result &&
 | 
			
		||||
	grep -E "commit|tree" verify_result |
 | 
			
		||||
	awk -f print_1.awk |
 | 
			
		||||
	sort >expected &&
 | 
			
		||||
 | 
			
		||||
	git -C r3 verify-pack -v ../filter.pack >verify_result &&
 | 
			
		||||
	grep -E "commit|tree" verify_result |
 | 
			
		||||
	awk -f print_1.awk |
 | 
			
		||||
	sort >observed &&
 | 
			
		||||
 | 
			
		||||
	test_cmp expected observed
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'verify sparse:path=pattern2' '
 | 
			
		||||
	git -C r3 ls-files -s sparse1 dir1/sparse1 >ls_files_result &&
 | 
			
		||||
	awk -f print_2.awk ls_files_result |
 | 
			
		||||
	sort >expected &&
 | 
			
		||||
 | 
			
		||||
	git -C r3 pack-objects --revs --stdout --filter=sparse:path=../pattern2 >filter.pack <<-EOF &&
 | 
			
		||||
test_expect_success 'verify sparse:path=pattern2 fails' '
 | 
			
		||||
	test_must_fail git -C r3 pack-objects --revs --stdout \
 | 
			
		||||
		--filter=sparse:path=../pattern2 <<-EOF
 | 
			
		||||
	HEAD
 | 
			
		||||
	EOF
 | 
			
		||||
	git -C r3 index-pack ../filter.pack &&
 | 
			
		||||
 | 
			
		||||
	git -C r3 verify-pack -v ../filter.pack >verify_result &&
 | 
			
		||||
	grep blob verify_result |
 | 
			
		||||
	awk -f print_1.awk |
 | 
			
		||||
	sort >observed &&
 | 
			
		||||
 | 
			
		||||
	test_cmp expected observed
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'verify normal and sparse:path=pattern2 packfiles have same commits/trees' '
 | 
			
		||||
	git -C r3 verify-pack -v ../all.pack >verify_result &&
 | 
			
		||||
	grep -E "commit|tree" verify_result |
 | 
			
		||||
	awk -f print_1.awk |
 | 
			
		||||
	sort >expected &&
 | 
			
		||||
 | 
			
		||||
	git -C r3 verify-pack -v ../filter.pack >verify_result &&
 | 
			
		||||
	grep -E "commit|tree" verify_result |
 | 
			
		||||
	awk -f print_1.awk |
 | 
			
		||||
	sort >observed &&
 | 
			
		||||
 | 
			
		||||
	test_cmp expected observed
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
# Test sparse:oid=<oid-ish> filter.
 | 
			
		||||
# Like sparse:path, but we get the sparse-checkout specification from
 | 
			
		||||
# a blob rather than a file on disk.
 | 
			
		||||
# Use a blob containing a sparse-checkout specification to filter
 | 
			
		||||
# out blobs not required for the corresponding sparse-checkout.  We do not
 | 
			
		||||
# require sparse-checkout to actually be enabled.
 | 
			
		||||
 | 
			
		||||
test_expect_success 'setup r4' '
 | 
			
		||||
	git init r4 &&
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -157,6 +157,10 @@ test_expect_success 'verify blob:limit=1m' '
 | 
			
		|||
'
 | 
			
		||||
 | 
			
		||||
# Test sparse:path=<path> filter.
 | 
			
		||||
# !!!!
 | 
			
		||||
# NOTE: sparse:path filter support has been dropped for security reasons,
 | 
			
		||||
# so the tests have been changed to make sure that using it fails.
 | 
			
		||||
# !!!!
 | 
			
		||||
# Use a local file containing a sparse-checkout specification to filter
 | 
			
		||||
# out blobs not required for the corresponding sparse-checkout.  We do not
 | 
			
		||||
# require sparse-checkout to actually be enabled.
 | 
			
		||||
| 
						 | 
				
			
			@ -176,37 +180,20 @@ test_expect_success 'setup r3' '
 | 
			
		|||
	echo sparse1 >pattern2
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'verify sparse:path=pattern1 omits top-level files' '
 | 
			
		||||
	git -C r3 ls-files -s sparse1 sparse2 >ls_files_result &&
 | 
			
		||||
	awk -f print_2.awk ls_files_result |
 | 
			
		||||
	sort >expected &&
 | 
			
		||||
 | 
			
		||||
	git -C r3 rev-list --quiet --objects --filter-print-omitted \
 | 
			
		||||
		--filter=sparse:path=../pattern1 HEAD >revs &&
 | 
			
		||||
	awk -f print_1.awk revs |
 | 
			
		||||
	sed "s/~//" |
 | 
			
		||||
	sort >observed &&
 | 
			
		||||
 | 
			
		||||
	test_cmp expected observed
 | 
			
		||||
test_expect_success 'verify sparse:path=pattern1 fails' '
 | 
			
		||||
	test_must_fail git -C r3 rev-list --quiet --objects \
 | 
			
		||||
		--filter-print-omitted --filter=sparse:path=../pattern1 HEAD
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'verify sparse:path=pattern2 omits both sparse2 files' '
 | 
			
		||||
	git -C r3 ls-files -s sparse2 dir1/sparse2 >ls_files_result &&
 | 
			
		||||
	awk -f print_2.awk ls_files_result |
 | 
			
		||||
	sort >expected &&
 | 
			
		||||
 | 
			
		||||
	git -C r3 rev-list --quiet --objects --filter-print-omitted \
 | 
			
		||||
		--filter=sparse:path=../pattern2 HEAD >revs &&
 | 
			
		||||
	awk -f print_1.awk revs |
 | 
			
		||||
	sed "s/~//" |
 | 
			
		||||
	sort >observed &&
 | 
			
		||||
 | 
			
		||||
	test_cmp expected observed
 | 
			
		||||
test_expect_success 'verify sparse:path=pattern2 fails' '
 | 
			
		||||
	test_must_fail git -C r3 rev-list --quiet --objects \
 | 
			
		||||
		--filter-print-omitted --filter=sparse:path=../pattern2 HEAD
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
# Test sparse:oid=<oid-ish> filter.
 | 
			
		||||
# Like sparse:path, but we get the sparse-checkout specification from
 | 
			
		||||
# a blob rather than a file on disk.
 | 
			
		||||
# Use a blob containing a sparse-checkout specification to filter
 | 
			
		||||
# out blobs not required for the corresponding sparse-checkout.  We do not
 | 
			
		||||
# require sparse-checkout to actually be enabled.
 | 
			
		||||
 | 
			
		||||
test_expect_success 'setup r3 part 2' '
 | 
			
		||||
	echo dir1/ >r3/pattern &&
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue