Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/bash/std/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,8 @@ std_register_cleanup_path "$workspace"

Cleanup paths are removed with `rm -rf --` from a shared `EXIT` trap. Empty
paths, root paths, and current/parent directory traversal components are
rejected before registration.
rejected before registration. When one call mixes safe and unsafe paths, safe
paths are registered, unsafe paths are rejected, and the helper returns nonzero.

For custom cleanup, register a function name:

Expand Down
23 changes: 14 additions & 9 deletions lib/bash/std/lib_std.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1245,16 +1245,19 @@ __std_is_safe_cleanup_path__() {
#
# std_register_cleanup_path - Registers files or directories for removal at shell exit.
#
# Paths are removed with `rm -rf --` from the shared EXIT trap. Empty paths, root
# paths, and paths containing current/parent directory traversal components are
# rejected to avoid broad accidental deletion.
# Paths are removed with `rm -rf --` from the shared EXIT trap. Empty paths,
# root paths, and paths containing current/parent directory traversal components
# are rejected to avoid broad accidental deletion. Safe paths in the same call
# are still registered, and the function returns nonzero if any path was
# rejected.
#
# Usage:
# workspace="$(mktemp -d)"
# std_register_cleanup_path "$workspace"
#
std_register_cleanup_path() {
local path existing_path
local already_registered had_valid_path=0 status=0

if (($# == 0)); then
log_warn "std_register_cleanup_path: No paths provided."
Expand All @@ -1264,12 +1267,12 @@ std_register_cleanup_path() {
for path; do
if ! __std_is_safe_cleanup_path__ "$path"; then
log_error "std_register_cleanup_path: refusing to register unsafe cleanup path '$path'."
return 1
status=1
continue
fi
done

for path; do
local already_registered=0
had_valid_path=1
already_registered=0
for existing_path in "${__std_cleanup_paths[@]}"; do
if [[ "$existing_path" == "$path" ]]; then
already_registered=1
Expand All @@ -1279,8 +1282,10 @@ std_register_cleanup_path() {
((already_registered)) || __std_cleanup_paths+=("$path")
done

__std_install_cleanup_dispatcher__
return 0
if ((had_valid_path)); then
__std_install_cleanup_dispatcher__
fi
return "$status"
}

######################################################## TEMP FILES ####################################################
Expand Down
18 changes: 18 additions & 0 deletions lib/bash/std/tests/lib_std.bats
Original file line number Diff line number Diff line change
Expand Up @@ -1218,6 +1218,24 @@ EOF
[[ "$(cat "$stderr_file")" == *"std_register_cleanup_path: refusing to register unsafe cleanup path"* ]]
}

@test "cleanup path registration keeps valid paths from mixed batches" {
local target_file="$TEST_TMPDIR/cleanup-valid-file.txt"
local target_dir="$TEST_TMPDIR/cleanup-valid-dir"
local stderr_file="$TEST_TMPDIR/cleanup-mixed.err"
local rc=0

printf 'sample\n' > "$target_file"
mkdir -p "$target_dir"

std_register_cleanup_path "$target_file" "/" "$target_dir" 2>"$stderr_file" || rc=$?

[ "$rc" -eq 1 ]
[[ "$(cat "$stderr_file")" == *"std_register_cleanup_path: refusing to register unsafe cleanup path '/'"* ]]
[[ " ${__std_cleanup_paths[*]} " == *" $target_file "* ]]
[[ " ${__std_cleanup_paths[*]} " == *" $target_dir "* ]]
[[ " ${__std_cleanup_paths[*]} " != *" / "* ]]
}

@test "std_make_temp_file creates a file under TMPDIR and cleans it up" {
local script="$TEST_TMPDIR/temp-file.sh"
local temp_root="$TEST_TMPDIR/temp-root"
Expand Down
Loading