@@ -908,6 +908,66 @@ test_expect_success PERL_TEST_HELPERS 'tolerate server sending REF_DELTA against
908908 ! test -e "$HTTPD_ROOT_PATH/one-time-script"
909909'
910910
911+ test_expect_success PERL_TEST_HELPERS ' lazy-fetch of REF_DELTA with missing base does not recurse' '
912+ SERVER="$HTTPD_DOCUMENT_ROOT_PATH/server" &&
913+ rm -rf "$SERVER" repo &&
914+ test_create_repo "$SERVER" &&
915+ test_config -C "$SERVER" uploadpack.allowfilter 1 &&
916+ test_config -C "$SERVER" uploadpack.allowanysha1inwant 1 &&
917+
918+ # Create a commit with 2 blobs to be used as delta base and content.
919+ for i in $(test_seq 10)
920+ do
921+ echo "this is a line" >>"$SERVER/foo.txt" &&
922+ echo "this is another line" >>"$SERVER/bar.txt" || return 1
923+ done &&
924+ git -C "$SERVER" add foo.txt bar.txt &&
925+ git -C "$SERVER" commit -m initial &&
926+ BLOB_FOO=$(git -C "$SERVER" rev-parse HEAD:foo.txt) &&
927+ BLOB_BAR=$(git -C "$SERVER" rev-parse HEAD:bar.txt) &&
928+
929+ # Partial clone with blob:none. The client has commits and
930+ # trees but no blobs.
931+ test_config -C "$SERVER" protocol.version 2 &&
932+ git -c protocol.version=2 clone --no-checkout \
933+ --filter=blob:none $HTTPD_URL/one_time_script/server repo &&
934+
935+ # Sanity check: client does not have either blob locally.
936+ git -C repo rev-list --objects --ignore-missing \
937+ -- $BLOB_FOO >objlist &&
938+ test_line_count = 0 objlist &&
939+
940+ # Craft a thin pack where BLOB_FOO is a REF_DELTA against
941+ # BLOB_BAR. Since the client has neither blob (blob:none
942+ # filter), the delta base will be missing. This simulates a
943+ # misbehaving server that sends REF_DELTA against an object
944+ # the client does not have.
945+ test-tool -C "$SERVER" pack-deltas --num-objects=1 >thin.pack <<-EOF &&
946+ REF_DELTA $BLOB_FOO $BLOB_BAR
947+ EOF
948+
949+ replace_packfile thin.pack &&
950+
951+ # Trigger a lazy fetch for BLOB_FOO. The child fetch spawned
952+ # by fetch_objects() receives our crafted thin pack. Its
953+ # index-pack encounters the missing delta base (BLOB_BAR) and
954+ # tries to lazy-fetch it via promisor_remote_get_direct().
955+ #
956+ # With the fix: fetch_objects() propagates GIT_NO_LAZY_FETCH=1
957+ # to the child, so the depth-2 fetch is blocked and we see the
958+ # "lazy fetching disabled" warning. The object cannot be
959+ # resolved, so cat-file fails.
960+ #
961+ # Without the fix: the depth-2 fetch would proceed, potentially
962+ # recursing unboundedly with a persistently misbehaving server.
963+ test_must_fail git -C repo -c protocol.version=2 \
964+ cat-file -p $BLOB_FOO 2>err &&
965+ test_grep "lazy fetching disabled" err &&
966+
967+ # Ensure that the one-time-script was used.
968+ ! test -e "$HTTPD_ROOT_PATH/one-time-script"
969+ '
970+
911971# DO NOT add non-httpd-specific tests here, because the last part of this
912972# test script is only executed when httpd is available and enabled.
913973
0 commit comments