The branch main has been updated by des:

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

commit eb41613d22977798f41dd979e4e4ec0965711916
Author:     Dag-Erling Smørgrav <d...@freebsd.org>
AuthorDate: 2025-08-07 23:34:07 +0000
Commit:     Dag-Erling Smørgrav <d...@freebsd.org>
CommitDate: 2025-08-07 23:34:07 +0000

    indent: Fix buffer overflow
    
    The function used to create a backup of the input before starting work
    used a static buffer and did not check that the file name it constructed
    did not overflow.  Switch to using asprintf(), clean up the rest of the
    function, and update some comments that still referred to an earlier
    version of the code.
    
    MFC after:      1 week
    Sponsored by:   Klara, Inc.
    Reviewed by:    bnovkov
    Differential Revision:  https://reviews.freebsd.org/D51796
---
 usr.bin/indent/indent.c                 | 40 ++++++++++++++-------------------
 usr.bin/indent/tests/functional_test.sh | 18 +++++++++++++++
 2 files changed, 35 insertions(+), 23 deletions(-)

diff --git a/usr.bin/indent/indent.c b/usr.bin/indent/indent.c
index 4739e861fef9..3ea78e1f153e 100644
--- a/usr.bin/indent/indent.c
+++ b/usr.bin/indent/indent.c
@@ -83,7 +83,6 @@ const char *out_name = "Standard Output";     /* will always 
point to name
                                                 * of output file */
 const char *simple_backup_suffix = ".BAK";     /* Suffix to use for backup
                                                 * files */
-char        bakfile[MAXPATHLEN] = "";
 
 int
 main(int argc, char **argv)
@@ -1231,41 +1230,35 @@ check_type:
 }
 
 /*
- * copy input file to backup file if in_name is /blah/blah/blah/file, then
- * backup file will be ".Bfile" then make the backup file the input and
+ * copy input file to backup file then make the backup file the input and
  * original input file the output
  */
 static void
 bakcopy(void)
 {
-    int         n,
-                bakchn;
-    char        buff[8 * 1024];
-    const char *p;
-
-    /* construct file name .Bfile */
-    for (p = in_name; *p; p++);        /* skip to end of string */
-    while (p > in_name && *p != '/')   /* find last '/' */
-       p--;
-    if (*p == '/')
-       p++;
-    sprintf(bakfile, "%s%s", p, simple_backup_suffix);
+    static char buff[8 * 1024];
+    char *bakfile;
+    ssize_t len;
+    int bakfd;
+
+    /* generate the backup file name */
+    if (asprintf(&bakfile, "%s%s", in_name, simple_backup_suffix) < 0)
+       err(1, "%s%s", in_name, simple_backup_suffix);
 
     /* copy in_name to backup file */
-    bakchn = creat(bakfile, 0600);
-    if (bakchn < 0)
+    bakfd = open(bakfile, O_RDWR | O_CREAT | O_TRUNC, 0600);
+    if (bakfd < 0)
        err(1, "%s", bakfile);
-    while ((n = read(fileno(input), buff, sizeof(buff))) > 0)
-       if (write(bakchn, buff, n) != n)
+    while ((len = read(fileno(input), buff, sizeof(buff))) > 0)
+       if (write(bakfd, buff, len) != len)
            err(1, "%s", bakfile);
-    if (n < 0)
+    if (len < 0)
        err(1, "%s", in_name);
-    close(bakchn);
     fclose(input);
 
     /* re-open backup file as the input file */
-    input = fopen(bakfile, "r");
-    if (input == NULL)
+    input = fdopen(bakfd, "r");
+    if (input == NULL || fseek(input, 0, SEEK_SET) != 0)
        err(1, "%s", bakfile);
     /* now the original input file will be the output */
     output = fopen(in_name, "w");
@@ -1273,6 +1266,7 @@ bakcopy(void)
        unlink(bakfile);
        err(1, "%s", in_name);
     }
+    free(bakfile);
 }
 
 static void
diff --git a/usr.bin/indent/tests/functional_test.sh 
b/usr.bin/indent/tests/functional_test.sh
index 3f4431038234..9cfe5878f69d 100755
--- a/usr.bin/indent/tests/functional_test.sh
+++ b/usr.bin/indent/tests/functional_test.sh
@@ -3,6 +3,7 @@
 #
 # Copyright 2016 Dell EMC
 # All rights reserved.
+# Copyright (c) 2025 Klara, Inc.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are
@@ -56,9 +57,26 @@ add_legacy_testcase()
        atf_add_test_case ${tc%.[0-9]}
 }
 
+atf_test_case backup_suffix
+backup_suffix_body()
+{
+       local argmax=$(sysctl -n kern.argmax)
+       local suffix=$(jot -b .bak -s '' $((argmax/5)))
+       local code=$'int main() {}\n'
+
+       printf "${code}" >input.c
+
+       atf_check indent input.c
+       atf_check -o inline:"${code}" cat input.c.BAK
+
+       atf_check -s exit:1 -e match:"name too long"\
+           env SIMPLE_BACKUP_SUFFIX=${suffix} indent input.c
+}
+
 atf_init_test_cases()
 {
        for tc in $(find -s "${SRCDIR}" -name '*.[0-9]'); do
                add_legacy_testcase "${tc##*/}"
        done
+       atf_add_test_case backup_suffix
 }

Reply via email to