From c4081e1820761aa6daa71fd40084f168163c6a85 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 2 Jan 2026 22:25:32 +0000 Subject: [PATCH 1/3] Initial plan From eb217e8a8696e9940b9c6a8a9f5ebcdae0b0ffb2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 2 Jan 2026 22:41:25 +0000 Subject: [PATCH 2/3] Fix SC2317 false positive on return ||: when script is not sourced Co-authored-by: dotysan <5060170+dotysan@users.noreply.github.com> --- src/ShellCheck/Analytics.hs | 3 +++ src/ShellCheck/CFG.hs | 13 ++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/ShellCheck/Analytics.hs b/src/ShellCheck/Analytics.hs index a4e2186a4..822064726 100644 --- a/src/ShellCheck/Analytics.hs +++ b/src/ShellCheck/Analytics.hs @@ -5049,6 +5049,9 @@ prop_checkCommandIsUnreachable2 = verify checkCommandIsUnreachable "die() { exit prop_checkCommandIsUnreachable3 = verifyNot checkCommandIsUnreachable "foo; bar || exit; baz" prop_checkCommandIsUnreachable4 = verifyNot checkCommandIsUnreachable "f() { foo; }; # Maybe sourced" prop_checkCommandIsUnreachable5 = verify checkCommandIsUnreachable "f() { foo; }; exit # Not sourced" +prop_checkCommandIsUnreachable6 = verifyNot checkCommandIsUnreachable "return || :; echo 'reachable'" +prop_checkCommandIsUnreachable7 = verifyNot checkCommandIsUnreachable "return; echo 'reachable when not in function'" +prop_checkCommandIsUnreachable8 = verify checkCommandIsUnreachable "f() { return; echo unreachable; }" checkCommandIsUnreachable params t = case t of T_Pipeline {} -> sequence_ $ do diff --git a/src/ShellCheck/CFG.hs b/src/ShellCheck/CFG.hs index c235cb7d4..7d6e3d87b 100644 --- a/src/ShellCheck/CFG.hs +++ b/src/ShellCheck/CFG.hs @@ -983,13 +983,20 @@ handleCommand cmd vars args literalCmd = do handleReturn = do returnTarget <- reader cfReturnTarget - case returnTarget of - Nothing -> error $ pleaseReport "missing return target" - Just target -> do + isFunction <- reader cfIsFunction + case (returnTarget, isFunction) of + (Nothing, _) -> error $ pleaseReport "missing return target" + (Just target, True) -> do + -- In a function: return actually returns, making subsequent code unreachable ret <- newNode CFStructuralNode link ret target CFEFlow unreachable <- newNode CFUnreachable return $ Range ret unreachable + (Just _, False) -> do + -- Not in a function: return will fail and execution continues + -- Treat it like a regular command that sets exit code + ret <- newNodeRange $ CFSetExitCode (getId cmd) + return ret handleUnset (cmd NE.:| args) = do case () of From 0a186fd2e5f59164634680d372bb5479ef10e7df Mon Sep 17 00:00:00 2001 From: Curtis Doty Date: Fri, 2 Jan 2026 23:07:06 +0000 Subject: [PATCH 3/3] Add 2nd unit test variant --- src/ShellCheck/Analytics.hs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ShellCheck/Analytics.hs b/src/ShellCheck/Analytics.hs index 822064726..05b0fbd84 100644 --- a/src/ShellCheck/Analytics.hs +++ b/src/ShellCheck/Analytics.hs @@ -5049,9 +5049,10 @@ prop_checkCommandIsUnreachable2 = verify checkCommandIsUnreachable "die() { exit prop_checkCommandIsUnreachable3 = verifyNot checkCommandIsUnreachable "foo; bar || exit; baz" prop_checkCommandIsUnreachable4 = verifyNot checkCommandIsUnreachable "f() { foo; }; # Maybe sourced" prop_checkCommandIsUnreachable5 = verify checkCommandIsUnreachable "f() { foo; }; exit # Not sourced" -prop_checkCommandIsUnreachable6 = verifyNot checkCommandIsUnreachable "return || :; echo 'reachable'" -prop_checkCommandIsUnreachable7 = verifyNot checkCommandIsUnreachable "return; echo 'reachable when not in function'" -prop_checkCommandIsUnreachable8 = verify checkCommandIsUnreachable "f() { return; echo unreachable; }" +prop_checkCommandIsUnreachable6 = verifyNot checkCommandIsUnreachable "return || true; echo 'reachable'" +prop_checkCommandIsUnreachable7 = verifyNot checkCommandIsUnreachable "return 2>/dev/null ||:" +prop_checkCommandIsUnreachable8 = verifyNot checkCommandIsUnreachable "return; echo 'reachable when not in function'" +prop_checkCommandIsUnreachable9 = verify checkCommandIsUnreachable "f() { return; echo unreachable; }" checkCommandIsUnreachable params t = case t of T_Pipeline {} -> sequence_ $ do