Patch 9.0.1669
Problem:    Crash syncing swapfile in new buffer when using sodium crypt.
            (James McCoy)
Solution:   Add checks for sodium encryption. (Christian Brabandt,
            closes #12591, closes #12585)
Files:      src/crypt.c, src/proto/crypt.pro, src/memline.c, src/optionstr.c,
            src/testdir/test_crypt.vim


*** ../vim-9.0.1668/src/crypt.c 2023-05-27 18:02:50.188062442 +0100
--- src/crypt.c 2023-06-27 18:04:46.150672593 +0100
***************
*** 1267,1272 ****
--- 1267,1279 ----
  }
  
  # if defined(FEAT_SODIUM) || defined(PROTO)
+     void
+ crypt_sodium_lock_key(char_u *key)
+ {
+     if (sodium_init() >= 0)
+       sodium_mlock(key, STRLEN(key));
+ }
+ 
      int
  crypt_sodium_munlock(void *const addr, const size_t len)
  {
*** ../vim-9.0.1668/src/proto/crypt.pro 2023-05-27 18:02:50.188062442 +0100
--- src/proto/crypt.pro 2023-06-27 17:59:37.762828206 +0100
***************
*** 26,31 ****
--- 26,32 ----
  void crypt_check_current_method(void);
  char_u *crypt_get_key(int store, int twice);
  void crypt_append_msg(buf_T *buf);
+ void crypt_sodium_lock_key(char_u *key);
  int crypt_sodium_munlock(void *const addr, const size_t len);
  void crypt_sodium_randombytes_buf(void *const buf, const size_t size);
  int crypt_sodium_init(void);
*** ../vim-9.0.1668/src/memline.c       2023-06-26 18:48:05.343295466 +0100
--- src/memline.c       2023-06-27 18:41:14.683651172 +0100
***************
*** 425,430 ****
--- 425,448 ----
  
  #if defined(FEAT_CRYPT) || defined(PROTO)
  /*
+  * Swapfile encryption is not supported by XChaCha20.  If this crypt method is
+  * used then disable the swapfile, to avoid plain text being written to disk,
+  * and return TRUE.
+  * Otherwise return FALSE.
+  */
+     static int
+ crypt_may_close_swapfile(buf_T *buf, char_u *key, int method)
+ {
+     if (crypt_method_is_sodium(method) && *key != NUL)
+     {
+       mf_close_file(buf, TRUE);
+       buf->b_p_swf = FALSE;
+       return TRUE;
+     }
+     return FALSE;
+ }
+ 
+ /*
   * Prepare encryption for "buf" for the current key and method.
   */
      static void
***************
*** 440,450 ****
        // Generate a seed and store it in the memfile.
        sha2_seed(buf->b_ml.ml_mfp->mf_seed, MF_SEED_LEN, NULL, 0);
      }
! #ifdef FEAT_SODIUM
      else if (crypt_method_is_sodium(method_nr))
!       crypt_sodium_randombytes_buf(buf->b_ml.ml_mfp->mf_seed,
!               MF_SEED_LEN);
! #endif
  }
  
  /*
--- 458,467 ----
        // Generate a seed and store it in the memfile.
        sha2_seed(buf->b_ml.ml_mfp->mf_seed, MF_SEED_LEN, NULL, 0);
      }
! # ifdef FEAT_SODIUM
      else if (crypt_method_is_sodium(method_nr))
!       crypt_sodium_randombytes_buf(buf->b_ml.ml_mfp->mf_seed, MF_SEED_LEN);
! # endif
  }
  
  /*
***************
*** 501,516 ****
        return;  // no memfile yet, nothing to do
      old_method = crypt_method_nr_from_name(old_cm);
  
!     // Swapfile encryption is not supported by XChaCha20, therefore disable 
the
!     // swapfile to avoid plain text being written to disk.
!     if (crypt_method_is_sodium(crypt_get_method_nr(buf))
!                                                      && *buf->b_p_key != NUL)
!     {
!       // close the swapfile
!       mf_close_file(buf, TRUE);
!       buf->b_p_swf = FALSE;
        return;
!     }
  
      // First make sure the swapfile is in a consistent state, using the old
      // key and method.
--- 518,527 ----
        return;  // no memfile yet, nothing to do
      old_method = crypt_method_nr_from_name(old_cm);
  
! #ifdef FEAT_CRYPT
!     if (crypt_may_close_swapfile(buf, buf->b_p_key, crypt_get_method_nr(buf)))
        return;
! #endif
  
      // First make sure the swapfile is in a consistent state, using the old
      // key and method.
***************
*** 2494,2499 ****
--- 2505,2516 ----
                || buf->b_ml.ml_mfp->mf_fd < 0)
            continue;                       // no file
  
+ #ifdef FEAT_CRYPT
+       if (crypt_may_close_swapfile(buf, buf->b_p_key,
+                                                    crypt_get_method_nr(buf)))
+           continue;
+ #endif
+ 
        ml_flush_line(buf);                 // flush buffered line
                                            // flush locked block
        (void)ml_find_line(buf, (linenr_T)0, ML_FLUSH);
***************
*** 2551,2556 ****
--- 2568,2577 ----
            emsg(_(e_cannot_preserve_there_is_no_swap_file));
        return;
      }
+ #ifdef FEAT_CRYPT
+     if (crypt_may_close_swapfile(buf, buf->b_p_key, crypt_get_method_nr(buf)))
+       return;
+ #endif
  
      // We only want to stop when interrupted here, not when interrupted
      // before.
***************
*** 5571,5576 ****
--- 5592,5600 ----
      if (*key == NUL)
        return NULL;
  
+     if (crypt_may_close_swapfile(buf, key, method_nr))
+       return NULL;
+ 
      if (method_nr == CRYPT_M_ZIP)
      {
        // For PKzip: Append the offset to the key, so that we use a different
*** ../vim-9.0.1668/src/optionstr.c     2023-05-31 17:12:07.888535653 +0100
--- src/optionstr.c     2023-06-27 18:47:54.791198972 +0100
***************
*** 1174,1179 ****
--- 1174,1183 ----
                *curbuf->b_p_cm == NUL ? p_cm : curbuf->b_p_cm);
        changed_internal();
      }
+ # ifdef FEAT_SODIUM
+     if (crypt_method_is_sodium(crypt_get_method_nr(curbuf)))
+        crypt_sodium_lock_key(args->os_newval.string);
+ # endif
  
      return NULL;
  }
*** ../vim-9.0.1668/src/testdir/test_crypt.vim  2023-05-27 18:02:50.192062438 
+0100
--- src/testdir/test_crypt.vim  2023-06-27 18:54:25.317284072 +0100
***************
*** 105,111 ****
    exe buf .. 'bwipe!'
    call assert_true(filereadable('Xfoo'))
  
!   let buf = RunVimInTerminal('--cmd "set ch=3 cm=xchacha20v2 key=foo" Xfoo', 
#{rows: 10})
    call g:TermWait(buf, g:RunningWithValgrind() ? 1000 : 50)
    call StopVimInTerminal(buf)
  
--- 105,111 ----
    exe buf .. 'bwipe!'
    call assert_true(filereadable('Xfoo'))
  
!   let buf = RunVimInTerminal('--cmd "set ch=3 cm=xchacha20v2 key=foo" Xfoo', 
#{wait_for_ruler: 0, rows: 10})
    call g:TermWait(buf, g:RunningWithValgrind() ? 1000 : 50)
    call StopVimInTerminal(buf)
  
***************
*** 392,395 ****
--- 392,415 ----
    call delete('Xtest1.txt')
  endfunc
  
+ func Test_crypt_set_key_segfault()
+   CheckFeature sodium
+ 
+   defer delete('Xtest2.txt')
+   new Xtest2.txt
+   call setline(1, 'nothing')
+   set cryptmethod=xchacha20
+   set key=foobar
+   w
+   new Xtest3
+   put ='other content'
+   setl modified
+   sil! preserve
+   bwipe!
+ 
+   set cryptmethod&
+   set key=
+   bwipe!
+ endfunc
+ 
  " vim: shiftwidth=2 sts=2 expandtab
*** ../vim-9.0.1668/src/version.c       2023-06-26 22:05:33.291658094 +0100
--- src/version.c       2023-06-27 18:54:53.513136357 +0100
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     1669,
  /**/

-- 
If you're sending someone Styrofoam, what do you pack it in?

 /// Bram Moolenaar -- b...@moolenaar.net -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
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 on the web visit 
https://groups.google.com/d/msgid/vim_dev/20230627175804.2668B1C054C%40moolenaar.net.

Raspunde prin e-mail lui