The branch main has been updated by des:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=c3904a7de78ca1ca15fcdf4c09f9d4be7f6fe6f5

commit c3904a7de78ca1ca15fcdf4c09f9d4be7f6fe6f5
Author:     Dag-Erling Smørgrav <[email protected]>
AuthorDate: 2026-02-05 14:39:53 +0000
Commit:     Dag-Erling Smørgrav <[email protected]>
CommitDate: 2026-02-05 14:39:53 +0000

    diff: Fix pagination leak
    
    * Drop an unnecessary variable and rename pidfd to procd.
    
    * Rewinding stdout serves no purpose, so stop doing it.
    
    * Don't bother freeing memory or setting the global status right
      before erroring out.
    
    * Error out if dup(2) or dup2(2) fail.
    
    * In the unlikely case that our pipe is equal to stdout, we need to
      record that information so we don't close it when cleaning up.
    
    * Don't bother closing a descriptor before dup2(2)ing to it.
    
    * Don't forget to close the the process descriptor after reaping the
      child process.
    
    PR:             266592
    MFC after:      1 week
    Sponsored by:   Klara, Inc.
    Reviewed by:    kevans, markj
    Differential Revision:  https://reviews.freebsd.org/D55112
---
 usr.bin/diff/pr.c | 22 ++++++++++------------
 usr.bin/diff/pr.h |  2 +-
 2 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/usr.bin/diff/pr.c b/usr.bin/diff/pr.c
index f254fbab28b7..189e6b34649e 100644
--- a/usr.bin/diff/pr.c
+++ b/usr.bin/diff/pr.c
@@ -45,7 +45,6 @@ struct pr *
 start_pr(char *file1, char *file2)
 {
        int pfd[2];
-       int pr_pd;
        pid_t pid;
        char *header;
        struct pr *pr;
@@ -55,13 +54,10 @@ start_pr(char *file1, char *file2)
        xasprintf(&header, "%s %s %s", diffargs, file1, file2);
        signal(SIGPIPE, SIG_IGN);
        fflush(stdout);
-       rewind(stdout);
        if (pipe(pfd) == -1)
                err(2, "pipe");
-       switch ((pid = pdfork(&pr_pd, PD_CLOEXEC))) {
+       switch ((pid = pdfork(&pr->procd, PD_CLOEXEC))) {
        case -1:
-               status |= 2;
-               free(header);
                err(2, "No more processes");
        case 0:
                /* child */
@@ -73,15 +69,17 @@ start_pr(char *file1, char *file2)
                execl(_PATH_PR, _PATH_PR, "-h", header, (char *)0);
                _exit(127);
        default:
-               pr->pidfd = pr_pd;
                /* parent */
-               if (pfd[1] != STDOUT_FILENO) {
-                       pr->ostdout = dup(STDOUT_FILENO);
-                       dup2(pfd[1], STDOUT_FILENO);
+               if (pfd[1] == STDOUT_FILENO) {
+                       pr->ostdout = STDOUT_FILENO;
+               } else {
+                       if ((pr->ostdout = dup(STDOUT_FILENO)) < 0 ||
+                           dup2(pfd[1], STDOUT_FILENO) < 0) {
+                               err(2, "stdout");
+                       }
                        close(pfd[1]);
                }
                close(pfd[0]);
-               rewind(stdout);
                free(header);
        }
        return (pr);
@@ -98,14 +96,14 @@ stop_pr(struct pr *pr)
 
        fflush(stdout);
        if (pr->ostdout != STDOUT_FILENO) {
-               close(STDOUT_FILENO);
                dup2(pr->ostdout, STDOUT_FILENO);
                close(pr->ostdout);
        }
-       while (pdwait(pr->pidfd, &wstatus, WEXITED, NULL, NULL) == -1) {
+       while (pdwait(pr->procd, &wstatus, WEXITED, NULL, NULL) == -1) {
                if (errno != EINTR)
                        err(2, "pdwait");
        }
+       close(pr->procd);
        free(pr);
        if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != 0)
                errx(2, "pr exited abnormally");
diff --git a/usr.bin/diff/pr.h b/usr.bin/diff/pr.h
index b2ff7e5d6798..e6abad4466a6 100644
--- a/usr.bin/diff/pr.h
+++ b/usr.bin/diff/pr.h
@@ -26,7 +26,7 @@
 
 struct pr {
        int ostdout;
-       int pidfd;
+       int procd;
 };
 
 struct pr *start_pr(char *file1, char *file2);

Reply via email to