run-command: avoid `close(-1)` in `start_command()` error paths

When `start_command()` fails to set up a pipe partway through, it rolls back by closing the pipe ends it has already opened. For descriptors supplied by the caller rather than allocated locally, that rollback tested `if (cmd->in)` / `if (cmd->out)` before calling close(). The CHILD_PROCESS_INIT default of -1 ("no descriptor") is non-zero and so passes the test, meaning a caller that sets cmd->no_stdin or cmd->no_stdout without supplying a real fd ends up triggering close(-1) on the error path. The stdin-pipe failure branch a few lines above already uses the right idiom, `if (cmd->out > 0)`, which rejects both the -1 sentinel and 0 (the parent's own standard streams). Apply it to the three remaining rollback sites. Reported by Coverity as CID 1049722 ("Argument cannot be negative"). Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Schindelin committed Jul 5, 2026 at 08:24 UTC c3f89beb733a260866ec9c163615bce59e77481b
1 file changed +3 -3
run-command.c
+3 -3
@@ -706,7 +706,7 @@ int start_command(struct child_process *cmd)
706 failed_errno = errno;
707 if (need_in)
708 close_pair(fdin);
709 - else if (cmd->in)
709 + else if (cmd->in > 0)
710 close(cmd->in);
711 str = "standard output";
712 goto fail_pipe;
@@ -720,11 +720,11 @@ int start_command(struct child_process *cmd)
720 failed_errno = errno;
721 if (need_in)
722 close_pair(fdin);
723 - else if (cmd->in)
723 + else if (cmd->in > 0)
724 close(cmd->in);
725 if (need_out)
726 close_pair(fdout);
727 - else if (cmd->out)
727 + else if (cmd->out > 0)
728 close(cmd->out);
729 str = "standard error";
730 fail_pipe: