patch 9.1.1688: potential buffer overrun in bufwrite.c

Commit: 
https://github.com/vim/vim/commit/a19b019b8745f1c91e42c2b9440bddebfa67a17a
Author: John Marriott <basil...@internode.on.net>
Date:   Tue Aug 26 17:32:18 2025 +0200

    patch 9.1.1688: potential buffer overrun in bufwrite.c
    
    Problem:  potential buffer overrun in bufwrite.c
    Solution: Use a temporary variable (John Marriott)
    
    In my Windows 11 Pro 64-bit build MAXPATHL is 1024 and IOSIZE is 1025.
    In my Archlinux Linux 64-bit build MAXPATHL is 4096 and IOSIZE is 1025.
    
    In funuction buf_write():
    There is a check (line 713) that makes sure the length of fname is less
    than MAXPATHL. There is a call to STRCPY() (line 1208) which copies the
    string at fname into IObuff (which has size IOSIZE). For Unix builds
    fname is set to sfname which may or may not be shorter. However, if
    sfname is NULL sfname is set to fname.
    
    Therefore, in builds where MAXPATHL > IOSIZE (eg in my linux build), it
    is theoretically possible for the STRCPY() call to exceed the bounds of
    IObuff.
    
    This PR addresses this by copying fname into a local variable that has
    the same maximum size as fname.
    
    In addition:
    Given that the filename is unconditionally overwritten in the for loop,
    only copy the directory portion of fname. Move variable i closer to
    where it is used.
    
    closes: #18095
    
    Signed-off-by: John Marriott <basil...@internode.on.net>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/bufwrite.c b/src/bufwrite.c
index e88c7b838..342b5f36f 100644
--- a/src/bufwrite.c
+++ b/src/bufwrite.c
@@ -1173,8 +1173,6 @@ buf_write(
 #if defined(UNIX) || defined(MSWIN)
        else if ((bkc & BKC_AUTO))      // "auto"
        {
-           int         i;
-
 # ifdef UNIX
            // Don't rename the file when:
            // - it's a hard link
@@ -1201,18 +1199,24 @@ buf_write(
 #  endif
 # endif
            {
+               size_t  dirlen;
+               char_u  tmp_fname[MAXPATHL];
+               int     i;
+
                // Check if we can create a file and set the owner/group to
                // the ones from the original file.
                // First find a file name that doesn't exist yet (use some
                // arbitrary numbers).
-               STRCPY(IObuff, fname);
+               dirlen = (size_t)(gettail(fname) - fname);
+               vim_strncpy(tmp_fname, fname, dirlen);
                fd = -1;
                for (i = 4913; ; i += 123)
                {
-                   sprintf((char *)gettail(IObuff), "%d", i);
-                   if (mch_lstat((char *)IObuff, &st) < 0)
+                   vim_snprintf((char *)tmp_fname + dirlen,
+                       sizeof(tmp_fname) - dirlen, "%d", i);
+                   if (mch_lstat((char *)tmp_fname, &st) < 0)
                    {
-                       fd = mch_open((char *)IObuff,
+                       fd = mch_open((char *)tmp_fname,
                                    O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, perm);
                        if (fd < 0 && errno == EEXIST)
                            // If the same file name is created by another
@@ -1230,7 +1234,7 @@ buf_write(
 #  ifdef HAVE_FCHOWN
                    vim_ignored = fchown(fd, st_old.st_uid, st_old.st_gid);
 #  endif
-                   if (mch_stat((char *)IObuff, &st) < 0
+                   if (mch_stat((char *)tmp_fname, &st) < 0
                            || st.st_uid != st_old.st_uid
                            || st.st_gid != st_old.st_gid
                            || (long)st.st_mode != perm)
@@ -1239,7 +1243,7 @@ buf_write(
                    // Close the file before removing it, on MS-Windows we
                    // can't delete an open file.
                    close(fd);
-                   mch_remove(IObuff);
+                   mch_remove(tmp_fname);
 # ifdef MSWIN
                    // MS-Windows may trigger a virus scanner to open the
                    // file, we can't delete it then.  Keep trying for half a
@@ -1249,10 +1253,10 @@ buf_write(
 
                        for (try = 0; try < 10; ++try)
                        {
-                           if (mch_lstat((char *)IObuff, &st) < 0)
+                           if (mch_lstat((char *)tmp_fname, &st) < 0)
                                break;
                            ui_delay(50L, TRUE);  // wait 50 msec
-                           mch_remove(IObuff);
+                           mch_remove(tmp_fname);
                        }
                    }
 # endif
diff --git a/src/version.c b/src/version.c
index 309ddf7f7..390959c7e 100644
--- a/src/version.c
+++ b/src/version.c
@@ -724,6 +724,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1688,
 /**/
     1687,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1uqvr5-003WW5-TG%40256bit.org.

Raspunde prin e-mail lui