@@ -60,6 +60,10 @@ setup() {
6060 # Write the standard release.conf
6161 write_release_conf
6262
63+ # Copy sha256sum-portable.sh into the fake plugin root so the download script can source it
64+ mkdir -p " ${FAKE_PLUGIN_ROOT} /scripts"
65+ cp " ${SCRIPT_DIR} /plugin/scripts/sha256sum-portable.sh" " ${FAKE_PLUGIN_ROOT} /scripts/"
66+
6367 # Create a stub bin dir for PATH overrides
6468 STUB_BIN_DIR=" $( mktemp -d) "
6569 export STUB_BIN_DIR
169173 [ " ${output} " = " ${CACHE_DIR} /${BINARY_NAME} " ]
170174}
171175
172- # ---------------------------------------------------------------------------
173- # sha256sum output with hex-like filename (regression: no false-positive hash extraction)
174- # ---------------------------------------------------------------------------
175-
176- @test " sha256sum output with hex-like filename does not cause false-positive hash extraction" {
177- # No python3, no git-filter-repo on PATH — force tier-3 resolution
178- write_python3_stub
179-
180- # Fix platform to linux-x64 for deterministic binary name
181- cat > " ${STUB_BIN_DIR} /uname" << 'EOF '
182- #!/usr/bin/env bash
183- if [[ "$1" == "-s" ]]; then
184- echo "Linux"
185- elif [[ "$1" == "-m" ]]; then
186- echo "x86_64"
187- fi
188- EOF
189- chmod +x " ${STUB_BIN_DIR} /uname"
190-
191- BINARY_NAME=" git-filter-repo-linux-x64"
192- CACHE_DIR=" ${FAKE_PLUGIN_ROOT} /lib"
193- mkdir -p " ${CACHE_DIR} "
194-
195- # Create a cached binary and its version file matching RELEASE_TAG
196- echo " fake binary content" > " ${CACHE_DIR} /${BINARY_NAME} "
197- echo " git-filter-repo-v2.38.0" > " ${CACHE_DIR} /${BINARY_NAME} .version"
198-
199- # Write a sha256sum stub whose output filename contains a 64-char hex segment.
200- # The first field (the hash) is FAKE_SHA256_LINUX_X64 (correct); the second field
201- # is a filename that itself embeds another 64-char hex string. The script must
202- # extract only the first field and not be confused by the hex in the filename.
203- mkdir -p " ${STUB_BIN_DIR} "
204- cat > " ${STUB_BIN_DIR} /sha256sum" << EOF
205- #!/usr/bin/env bash
206- printf '%s git-filter-repo-linux-x64-${FAKE_SHA256_LINUX_X64} \n' "${FAKE_SHA256_LINUX_X64} "
207- EOF
208- chmod +x " ${STUB_BIN_DIR} /sha256sum"
209-
210- run env PATH=" ${STUB_BIN_DIR} :${SAFE_PATH} " bash " ${DOWNLOAD_SCRIPT} "
211-
212- [ " ${status} " -eq 0 ]
213- [ " ${output} " = " ${CACHE_DIR} /${BINARY_NAME} " ]
214- }
215-
216176# ---------------------------------------------------------------------------
217177# release.conf missing RELEASE_TAG (error handling)
218178# ---------------------------------------------------------------------------
477437 # Stub sha256sum so SHA256 verification of cache also fails gracefully (no cached binary exists)
478438 write_sha256sum_stub " ${STUB_BIN_DIR} " " ${FAKE_SHA256_LINUX_X64} "
479439
440+ CACHE_DIR=" ${FAKE_PLUGIN_ROOT} /lib"
441+ mkdir -p " ${CACHE_DIR} "
442+
480443 # Stub curl to return a connection failure exit code
481444 cat > " ${STUB_BIN_DIR} /curl" << 'EOF '
482445#!/usr/bin/env bash
@@ -488,4 +451,151 @@ EOF
488451
489452 [ " ${status} " -ne 0 ]
490453 [[ " ${output} " == * " ERROR" * ]] || [[ " ${lines[*]} " == * " ERROR" * ]]
454+ # CACHED_BINARY must not exist
455+ [ ! -f " ${CACHE_DIR} /git-filter-repo-linux-x64" ]
456+ # No .tmp. files must remain in the cache directory
457+ TMP_COUNT=$( find " ${CACHE_DIR} " -name " *.tmp.*" 2> /dev/null | wc -l)
458+ [ " ${TMP_COUNT} " -eq 0 ]
459+ }
460+
461+ @test " curl timeout (exit 28) leaves no partial file in cache directory" {
462+ # Stub python3 to fail so we reach download phase; git-filter-repo excluded via SAFE_PATH
463+ write_python3_stub
464+
465+ # Fix platform to linux-x64 for deterministic binary name
466+ cat > " ${STUB_BIN_DIR} /uname" << 'EOF '
467+ #!/usr/bin/env bash
468+ if [[ "$1" == "-s" ]]; then
469+ echo "Linux"
470+ elif [[ "$1" == "-m" ]]; then
471+ echo "x86_64"
472+ fi
473+ EOF
474+ chmod +x " ${STUB_BIN_DIR} /uname"
475+
476+ write_sha256sum_stub " ${STUB_BIN_DIR} " " ${FAKE_SHA256_LINUX_X64} "
477+
478+ CACHE_DIR=" ${FAKE_PLUGIN_ROOT} /lib"
479+ mkdir -p " ${CACHE_DIR} "
480+
481+ # Stub curl: write partial bytes to the -o output file then exit 28 (timeout)
482+ cat > " ${STUB_BIN_DIR} /curl" << 'EOF '
483+ #!/usr/bin/env bash
484+ for ((i=1; i<=$#; i++)); do
485+ if [[ "${!i}" == "-o" ]]; then
486+ next=$((i+1))
487+ printf 'partial' > "${!next}"
488+ break
489+ fi
490+ done
491+ exit 28
492+ EOF
493+ chmod +x " ${STUB_BIN_DIR} /curl"
494+
495+ run env PATH=" ${STUB_BIN_DIR} :${SAFE_PATH} " bash " ${DOWNLOAD_SCRIPT} "
496+
497+ [ " ${status} " -ne 0 ]
498+ [[ " ${output} " == * " ERROR" * ]] || [[ " ${lines[*]} " == * " ERROR" * ]]
499+ [[ " ${output} " == * " timeout" * ]] || [[ " ${lines[*]} " == * " timeout" * ]]
500+ # CACHED_BINARY must not exist
501+ [ ! -f " ${CACHE_DIR} /git-filter-repo-linux-x64" ]
502+ # No .tmp. files must remain in the cache directory
503+ TMP_COUNT=$( find " ${CACHE_DIR} " -name " *.tmp.*" 2> /dev/null | wc -l)
504+ [ " ${TMP_COUNT} " -eq 0 ]
505+ }
506+
507+ @test " partial download (curl exits 0, wrong SHA256) triggers SHA256 failure and cleanup" {
508+ # Stub python3 to fail so we reach download phase; git-filter-repo excluded via SAFE_PATH
509+ write_python3_stub
510+
511+ # Fix platform to linux-x64 for deterministic binary name
512+ cat > " ${STUB_BIN_DIR} /uname" << 'EOF '
513+ #!/usr/bin/env bash
514+ if [[ "$1" == "-s" ]]; then
515+ echo "Linux"
516+ elif [[ "$1" == "-m" ]]; then
517+ echo "x86_64"
518+ fi
519+ EOF
520+ chmod +x " ${STUB_BIN_DIR} /uname"
521+
522+ # Stub sha256sum to return all-zeros hash (will not match FAKE_SHA256_LINUX_X64)
523+ WRONG_HASH=" 0000000000000000000000000000000000000000000000000000000000000000"
524+ write_sha256sum_stub " ${STUB_BIN_DIR} " " ${WRONG_HASH} "
525+
526+ CACHE_DIR=" ${FAKE_PLUGIN_ROOT} /lib"
527+ mkdir -p " ${CACHE_DIR} "
528+
529+ # Stub curl: write a few bytes (partial content) then exit 0
530+ cat > " ${STUB_BIN_DIR} /curl" << 'EOF '
531+ #!/usr/bin/env bash
532+ for ((i=1; i<=$#; i++)); do
533+ if [[ "${!i}" == "-o" ]]; then
534+ next=$((i+1))
535+ printf 'partial' > "${!next}"
536+ break
537+ fi
538+ done
539+ exit 0
540+ EOF
541+ chmod +x " ${STUB_BIN_DIR} /curl"
542+
543+ run env PATH=" ${STUB_BIN_DIR} :${SAFE_PATH} " bash " ${DOWNLOAD_SCRIPT} "
544+
545+ [ " ${status} " -ne 0 ]
546+ [[ " ${output} " == * " SHA256" * ]] || [[ " ${output} " == * " checksum" * ]] || \
547+ [[ " ${lines[*]} " == * " SHA256" * ]] || [[ " ${lines[*]} " == * " checksum" * ]]
548+ # CACHED_BINARY must not exist after failed SHA256 verification
549+ [ ! -f " ${CACHE_DIR} /git-filter-repo-linux-x64" ]
550+ # No .tmp. files must remain in the cache directory
551+ TMP_COUNT=$( find " ${CACHE_DIR} " -name " *.tmp.*" 2> /dev/null | wc -l)
552+ [ " ${TMP_COUNT} " -eq 0 ]
553+ }
554+
555+ @test " successful download with SHA256 mismatch triggers cleanup (no CACHED_BINARY left)" {
556+ # Stub python3 to fail so we reach download phase; git-filter-repo excluded via SAFE_PATH
557+ write_python3_stub
558+
559+ # Fix platform to linux-x64 for deterministic binary name
560+ cat > " ${STUB_BIN_DIR} /uname" << 'EOF '
561+ #!/usr/bin/env bash
562+ if [[ "$1" == "-s" ]]; then
563+ echo "Linux"
564+ elif [[ "$1" == "-m" ]]; then
565+ echo "x86_64"
566+ fi
567+ EOF
568+ chmod +x " ${STUB_BIN_DIR} /uname"
569+
570+ # Stub sha256sum to return all-f's hash (will not match FAKE_SHA256_LINUX_X64)
571+ WRONG_HASH=" ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
572+ write_sha256sum_stub " ${STUB_BIN_DIR} " " ${WRONG_HASH} "
573+
574+ CACHE_DIR=" ${FAKE_PLUGIN_ROOT} /lib"
575+ mkdir -p " ${CACHE_DIR} "
576+
577+ # Stub curl: write "wrong content" (simulates a full download of wrong data) then exit 0
578+ cat > " ${STUB_BIN_DIR} /curl" << 'EOF '
579+ #!/usr/bin/env bash
580+ for ((i=1; i<=$#; i++)); do
581+ if [[ "${!i}" == "-o" ]]; then
582+ next=$((i+1))
583+ echo "wrong content" > "${!next}"
584+ break
585+ fi
586+ done
587+ exit 0
588+ EOF
589+ chmod +x " ${STUB_BIN_DIR} /curl"
590+
591+ run env PATH=" ${STUB_BIN_DIR} :${SAFE_PATH} " bash " ${DOWNLOAD_SCRIPT} "
592+
593+ [ " ${status} " -ne 0 ]
594+ [[ " ${output} " == * " SHA256" * ]] || [[ " ${output} " == * " checksum" * ]] || \
595+ [[ " ${lines[*]} " == * " SHA256" * ]] || [[ " ${lines[*]} " == * " checksum" * ]]
596+ # CACHED_BINARY must not exist after failed SHA256 verification
597+ [ ! -f " ${CACHE_DIR} /git-filter-repo-linux-x64" ]
598+ # No .tmp. files must remain in the cache directory
599+ TMP_COUNT=$( find " ${CACHE_DIR} " -name " *.tmp.*" 2> /dev/null | wc -l)
600+ [ " ${TMP_COUNT} " -eq 0 ]
491601}
0 commit comments