From 7c7a1c25297a8f08f987b69e5f2df767a97ce382 Mon Sep 17 00:00:00 2001 From: Daveswo <969dwi@gmail.com> Date: Tue, 18 Aug 2026 01:10:40 -0400 Subject: [PATCH] Fix 50-thefuck.sh: wrap in timeout, found by 1000-case fuzz test hanging on unmatched inputs --- contrib/fx/sources.d/50-thefuck.sh | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/contrib/fx/sources.d/50-thefuck.sh b/contrib/fx/sources.d/50-thefuck.sh index 04cbd78..05514ae 100755 --- a/contrib/fx/sources.d/50-thefuck.sh +++ b/contrib/fx/sources.d/50-thefuck.sh @@ -3,7 +3,18 @@ # --yes decides *and executes* its own suggestion, so by the time this # candidate is shown it may have already run once via thefuck -- treat # it as informational, not a dry-run. +# +# Wrapped in `timeout`: thefuck has no fast-fail path when no rule +# matches -- fuzz-testing this source found it hanging past 3s on a +# majority of unmatched inputs (well beyond its own ~325ms best-case +# startup cost measured earlier). Every other source in this directory +# either runs in single-digit milliseconds or is itself already +# timeout-wrapped (70/80's HTTP calls); this one wasn't, so a single +# bad input could block the whole fx() pipeline indefinitely. Capped +# at 5s -- generous enough for a real correction (~2.8s measured +# earlier for the git-push case) without being unbounded. command -v thefuck >/dev/null 2>&1 || exit 0 +command -v timeout >/dev/null 2>&1 || exit 0 cmd="$1" [ -n "$cmd" ] || exit 0 -thefuck --yes "$cmd" 2>/dev/null | tr -d '\342\200\213' | tail -1 +timeout 5 thefuck --yes "$cmd" 2>/dev/null | tr -d '\342\200\213' | tail -1