release: restore ZUPT and harden source-only 5.2.2
This commit is contained in:
parent
74e393ba3e
commit
ff99770bd0
205 changed files with 19627 additions and 13215 deletions
133
scripts/test-installed-zupt.sh
Executable file
133
scripts/test-installed-zupt.sh
Executable file
|
|
@ -0,0 +1,133 @@
|
|||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Copyright (c) 2026 Cristian Cezar Moisés
|
||||
|
||||
set -Eeuo pipefail
|
||||
|
||||
umask 077
|
||||
export LC_ALL=C
|
||||
|
||||
die() {
|
||||
printf 'FAIL: %s\n' "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
pass() {
|
||||
printf 'PASS: %s\n' "$1"
|
||||
}
|
||||
|
||||
hash_tree() {
|
||||
local tree=$1
|
||||
(
|
||||
cd -- "$tree"
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
find . -type f -exec sha256sum {} \; | LC_ALL=C sort
|
||||
elif command -v shasum >/dev/null 2>&1; then
|
||||
find . -type f -exec shasum -a 256 {} \; | LC_ALL=C sort
|
||||
else
|
||||
die 'sha256sum or shasum is required'
|
||||
fi
|
||||
)
|
||||
}
|
||||
|
||||
# ZUPT_BIN is the public override. VAPTVUPT_BIN remains a compatibility
|
||||
# fallback for existing automation during the package-name transition.
|
||||
candidate=${1:-${ZUPT_BIN:-${VAPTVUPT_BIN:-zupt}}}
|
||||
if [[ $candidate == */* ]]; then
|
||||
[[ -x $candidate ]] || die "executable not found: $candidate"
|
||||
binary=$(cd -- "$(dirname -- "$candidate")" && pwd -P)/$(basename -- "$candidate")
|
||||
else
|
||||
binary=$(command -v -- "$candidate" || true)
|
||||
[[ -n $binary ]] || die "executable not found on PATH: $candidate"
|
||||
fi
|
||||
|
||||
test_root=$(mktemp -d "${TMPDIR:-/tmp}/zupt-installed.XXXXXX")
|
||||
trap 'chmod -R u+rwX "$test_root" 2>/dev/null || true; rm -rf -- "$test_root"' EXIT HUP INT TERM
|
||||
|
||||
input=$test_root/input
|
||||
plain_out=$test_root/plain-out
|
||||
password_out=$test_root/password-out
|
||||
escape_out=$test_root/escape-out
|
||||
outside=$test_root/outside
|
||||
mkdir -p "$input/subdir" "$plain_out" "$password_out" "$escape_out" "$outside"
|
||||
|
||||
printf 'ZUPT installed smoke test\nsecond line\n' > "$input/text file.txt"
|
||||
printf 'conteúdo UTF-8\n' > "$input/subdir/café-安全.txt"
|
||||
: > "$input/empty file"
|
||||
dd if=/dev/urandom of="$input/subdir/random.bin" bs=4096 count=8 2>/dev/null
|
||||
printf 'do-not-overwrite\n' > "$outside/sentinel"
|
||||
|
||||
"$binary" --version > "$test_root/version.log" 2>&1
|
||||
grep -q '^zupt ' "$test_root/version.log" || die "--version did not identify zupt"
|
||||
pass '--version'
|
||||
|
||||
"$binary" --help > "$test_root/help.log" 2>&1
|
||||
grep -q '^Usage:' "$test_root/help.log" || die "--help did not contain Usage"
|
||||
pass '--help'
|
||||
|
||||
if "$binary" --definitely-invalid-option > "$test_root/invalid.log" 2>&1; then
|
||||
die 'invalid option returned success'
|
||||
fi
|
||||
pass 'invalid option returns failure'
|
||||
|
||||
plain_archive=$test_root/plain.zupt
|
||||
"$binary" compress "$plain_archive" "$input" > "$test_root/plain-compress.log" 2>&1
|
||||
"$binary" test "$plain_archive" > "$test_root/plain-test.log" 2>&1
|
||||
"$binary" extract -o "$plain_out" "$plain_archive" > "$test_root/plain-extract.log" 2>&1
|
||||
extracted_markers=()
|
||||
while IFS= read -r -d '' marker; do
|
||||
extracted_markers[${#extracted_markers[@]}]=$marker
|
||||
done < <(find "$plain_out" -type f -name 'text file.txt' -print0)
|
||||
[[ ${#extracted_markers[@]} -eq 1 ]] || die 'extracted tree is missing or ambiguous'
|
||||
extracted_input=$(dirname -- "${extracted_markers[0]}")
|
||||
[[ -f $extracted_input/subdir/café-安全.txt && -f $extracted_input/empty\ file ]] || \
|
||||
die 'extracted tree is incomplete'
|
||||
diff -r -- "$input" "$extracted_input" > "$test_root/plain-diff.log" || die 'plain round-trip differs'
|
||||
|
||||
hash_tree "$input" > "$test_root/original.sha256"
|
||||
hash_tree "$extracted_input" > "$test_root/extracted.sha256"
|
||||
cmp -- "$test_root/original.sha256" "$test_root/extracted.sha256" || die 'round-trip SHA-256 manifests differ'
|
||||
pass 'text, random, empty, nested, spaces and UTF-8 round-trip'
|
||||
|
||||
password='ZUPT-test-password-2026!'
|
||||
password_archive=$test_root/password.zupt
|
||||
"$binary" compress -p "$password" "$password_archive" "$input/text file.txt" > "$test_root/password-compress.log" 2>&1
|
||||
"$binary" test -p "$password" "$password_archive" > "$test_root/password-test.log" 2>&1
|
||||
"$binary" extract -p "$password" -o "$password_out" "$password_archive" > "$test_root/password-extract.log" 2>&1
|
||||
password_markers=()
|
||||
while IFS= read -r -d '' marker; do
|
||||
password_markers[${#password_markers[@]}]=$marker
|
||||
done < <(find "$password_out" -type f -name 'text file.txt' -print0)
|
||||
[[ ${#password_markers[@]} -eq 1 ]] || die 'password extraction is missing or ambiguous'
|
||||
cmp -- "$input/text file.txt" "${password_markers[0]}" || die 'password round-trip differs'
|
||||
if "$binary" extract -p 'incorrect-password' -o "$test_root/wrong-password-out" "$password_archive" > "$test_root/wrong-password.log" 2>&1; then
|
||||
die 'incorrect password returned success'
|
||||
fi
|
||||
pass 'password round-trip and incorrect-password rejection'
|
||||
|
||||
archive_size=$(wc -c < "$plain_archive")
|
||||
(( archive_size > 32 )) || die 'archive unexpectedly small'
|
||||
head -c "$((archive_size - 17))" "$plain_archive" > "$test_root/corrupt.zupt"
|
||||
if "$binary" test "$test_root/corrupt.zupt" > "$test_root/corrupt.log" 2>&1; then
|
||||
die 'truncated archive returned success'
|
||||
fi
|
||||
pass 'corrupt archive rejection'
|
||||
|
||||
archive_input_rel=${extracted_input#"$plain_out"/}
|
||||
[[ $archive_input_rel != "$extracted_input" && $archive_input_rel != /* ]] || \
|
||||
die 'cannot determine the archive extraction path'
|
||||
mkdir -p -- "$escape_out/$(dirname -- "$archive_input_rel")"
|
||||
ln -s -- "$outside" "$escape_out/$archive_input_rel"
|
||||
"$binary" extract -o "$escape_out" "$plain_archive" > "$test_root/escape.log" 2>&1 || true
|
||||
[[ $(<"$outside/sentinel") == 'do-not-overwrite' ]] || die 'extraction overwrote outside sentinel'
|
||||
[[ ! -e "$outside/text file.txt" && ! -e "$outside/subdir" ]] || die 'extraction escaped through a destination symlink'
|
||||
pass 'no write outside extraction destination'
|
||||
|
||||
if [[ $(id -u) -eq 0 ]]; then
|
||||
printf 'SKIP: unprivileged execution (test process is root)\n'
|
||||
else
|
||||
[[ -r $plain_archive && -x $binary ]] || die 'unprivileged process cannot read archive or execute binary'
|
||||
pass 'execution as an unprivileged user'
|
||||
fi
|
||||
|
||||
printf 'PASS: installed ZUPT functional test suite\n'
|
||||
Loading…
Reference in a new issue