mirror of
https://github.com/tw93/Mole.git
synced 2026-03-22 18:30:08 +00:00
fix(timeout): inherit helper state and pass checks
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
@@ -165,10 +166,8 @@ func validatePath(path string) error {
|
||||
return fmt.Errorf("path contains null bytes")
|
||||
}
|
||||
// Check for path traversal attempts (.. components).
|
||||
for _, component := range strings.Split(path, string(filepath.Separator)) {
|
||||
if component == ".." {
|
||||
return fmt.Errorf("path contains traversal components: %s", path)
|
||||
}
|
||||
if slices.Contains(strings.Split(path, string(filepath.Separator)), "..") {
|
||||
return fmt.Errorf("path contains traversal components: %s", path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -275,23 +275,22 @@ func getAPFSContainerFreeBytes(mountpoint string) (uint64, error) {
|
||||
}
|
||||
|
||||
const key = "<key>APFSContainerFree</key>"
|
||||
idx := strings.Index(out, key)
|
||||
if idx == -1 {
|
||||
_, rest, found := strings.Cut(out, key)
|
||||
if !found {
|
||||
return 0, fmt.Errorf("APFSContainerFree not found")
|
||||
}
|
||||
|
||||
rest := out[idx+len(key):]
|
||||
start := strings.Index(rest, "<integer>")
|
||||
if start == -1 {
|
||||
_, rest, found = strings.Cut(rest, "<integer>")
|
||||
if !found {
|
||||
return 0, fmt.Errorf("APFSContainerFree value not found")
|
||||
}
|
||||
rest = rest[start+len("<integer>"):]
|
||||
end := strings.Index(rest, "</integer>")
|
||||
if end == -1 {
|
||||
|
||||
value, _, found := strings.Cut(rest, "</integer>")
|
||||
if !found {
|
||||
return 0, fmt.Errorf("APFSContainerFree end tag not found")
|
||||
}
|
||||
|
||||
val, err := strconv.ParseUint(strings.TrimSpace(rest[:end]), 10, 64)
|
||||
val, err := strconv.ParseUint(strings.TrimSpace(value), 10, 64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to parse APFSContainerFree: %v", err)
|
||||
}
|
||||
|
||||
@@ -55,6 +55,11 @@ if [[ -z "${MO_TIMEOUT_INITIALIZED:-}" ]]; then
|
||||
echo "[TIMEOUT] Install coreutils for better reliability: brew install coreutils" >&2
|
||||
fi
|
||||
|
||||
# Export so child processes inherit detected values and skip re-detection.
|
||||
# Without this, children that inherit MO_TIMEOUT_INITIALIZED=1 skip the init
|
||||
# block but have empty bin vars, forcing the slow shell fallback.
|
||||
export MO_TIMEOUT_BIN
|
||||
export MO_TIMEOUT_PERL_BIN
|
||||
export MO_TIMEOUT_INITIALIZED=1
|
||||
fi
|
||||
|
||||
@@ -181,7 +186,10 @@ run_with_timeout() {
|
||||
"$@" &
|
||||
local cmd_pid=$!
|
||||
|
||||
# Start timeout killer in background
|
||||
# Start timeout killer in background.
|
||||
# Redirect all FDs to /dev/null so orphaned child processes (e.g. sleep $duration)
|
||||
# do not inherit open file descriptors from the caller and block output pipes
|
||||
# (notably bats output capture pipes that wait for all writers to close).
|
||||
(
|
||||
# Wait for timeout duration
|
||||
sleep "$duration"
|
||||
@@ -200,7 +208,7 @@ run_with_timeout() {
|
||||
kill -KILL -"$cmd_pid" 2> /dev/null || kill -KILL "$cmd_pid" 2> /dev/null || true
|
||||
fi
|
||||
fi
|
||||
) &
|
||||
) < /dev/null > /dev/null 2>&1 &
|
||||
local killer_pid=$!
|
||||
|
||||
# Wait for command to complete
|
||||
|
||||
Reference in New Issue
Block a user