Skip to content

Prevent a segfault in createProcess on Mac #296

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 31, 2023
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
4 changes: 3 additions & 1 deletion cbits/posix/find_executable.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,12 @@ static bool is_executable(char *working_dir, const char *path) {
* found.
*/
static char *find_in_search_path(char *working_dir, char *search_path, const char *filename) {
int workdir_len = strlen(working_dir);
const int filename_len = strlen(filename);
char *tokbuf;
char *path = strtok_r(search_path, ":", &tokbuf);
if (!working_dir)
working_dir = ".";
int workdir_len = strlen(working_dir);
while (path != NULL) {
// N.B. gcc 6.3.0, used by Debian 9, inexplicably warns that `path`
// may not be initialised with -Wall. Silence this warning. See #210.
Expand Down
28 changes: 28 additions & 0 deletions test/main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ main = do
testInterruptWith
testDoubleWait
testKillDoubleWait
testCreateProcess
putStrLn ">>> Tests passed successfully"

run :: String -> IO () -> IO ()
Expand Down Expand Up @@ -251,6 +252,33 @@ testKillDoubleWait = unless isWindows $ do
("INT", True) -> checkFirst "INT" False res
_ -> checkFirst sig delegate res

-- Test that createProcess doesn't segfault on Mac with a cwd of Nothing
testCreateProcess :: IO ()
testCreateProcess = run "createProcess with cwd = Nothing" $ do
let env = CreateProcess
{ child_group = Nothing
, child_user = Nothing
, close_fds = False
, cmdspec = RawCommand "env" []
, create_group = True
, create_new_console = False
, cwd = Nothing
, delegate_ctlc = False
, detach_console = False
, env = Just [("PATH", "/bin:/usr/bin")]
, new_session = False
, std_err = Inherit
, std_in = Inherit
, std_out = Inherit
, use_process_jobs = False
}
(_, _, _, p) <- createProcess env
res <- try $ waitForProcess p
case res of
Left e -> error $ "waitForProcess threw: " ++ show (e :: SomeException)
Right ExitSuccess -> return ()
Right exitCode -> error $ "unexpected exit code: " ++ show exitCode

withCurrentDirectory :: FilePath -> IO a -> IO a
withCurrentDirectory new inner = do
orig <- getCurrentDirectory
Expand Down