Patch 9.0.1583

4 views
Skip to first unread message

Bram Moolenaar

unread,
May 27, 2023, 1:03:34 PM5/27/23
to vim...@googlegroups.com

Patch 9.0.1583
Problem: Get E304 when using 'cryptmethod' "xchacha20v2". (Steve Mynott)
Solution: Add 4th crypt method to block zero ID check. Avoid syncing a swap
file before reading the file. (closes #12433)
Files: src/memfile.c, src/memline.c, src/crypt.c, src/proto/crypt.pro,
src/structs.h, src/buffer.c, src/fileio.c,
src/testdir/test_crypt.vim


*** ../vim-9.0.1582/src/memfile.c 2023-04-22 21:14:21.585140551 +0100
--- src/memfile.c 2023-05-27 16:28:42.056761913 +0100
***************
*** 150,156 ****
mfp->mf_free_first = NULL; // free list is empty
mfp->mf_used_first = NULL; // used list is empty
mfp->mf_used_last = NULL;
! mfp->mf_dirty = FALSE;
mfp->mf_used_count = 0;
mf_hash_init(&mfp->mf_hash);
mf_hash_init(&mfp->mf_trans);
--- 150,156 ----
mfp->mf_free_first = NULL; // free list is empty
mfp->mf_used_first = NULL; // used list is empty
mfp->mf_used_last = NULL;
! mfp->mf_dirty = MF_DIRTY_NO;
mfp->mf_used_count = 0;
mf_hash_init(&mfp->mf_hash);
mf_hash_init(&mfp->mf_trans);
***************
*** 224,230 ****
if (mfp->mf_fd < 0)
return FAIL;

! mfp->mf_dirty = TRUE;
return OK;
}

--- 224,230 ----
if (mfp->mf_fd < 0)
return FAIL;

! mfp->mf_dirty = MF_DIRTY_YES;
return OK;
}

***************
*** 386,392 ****
}
}
hp->bh_flags = BH_LOCKED | BH_DIRTY; // new block is always dirty
! mfp->mf_dirty = TRUE;
hp->bh_page_count = page_count;
mf_ins_used(mfp, hp);
mf_ins_hash(mfp, hp);
--- 386,392 ----
}
}
hp->bh_flags = BH_LOCKED | BH_DIRTY; // new block is always dirty
! mfp->mf_dirty = MF_DIRTY_YES;
hp->bh_page_count = page_count;
mf_ins_used(mfp, hp);
mf_ins_hash(mfp, hp);
***************
*** 483,489 ****
if (dirty)
{
flags |= BH_DIRTY;
! mfp->mf_dirty = TRUE;
}
hp->bh_flags = flags;
if (infile)
--- 483,490 ----
if (dirty)
{
flags |= BH_DIRTY;
! if (mfp->mf_dirty != MF_DIRTY_YES_NOSYNC)
! mfp->mf_dirty = MF_DIRTY_YES;
}
hp->bh_flags = flags;
if (infile)
***************
*** 528,536 ****
bhdr_T *hp;
int got_int_save = got_int;

! if (mfp->mf_fd < 0) // there is no file, nothing to do
{
! mfp->mf_dirty = FALSE;
return FAIL;
}

--- 529,538 ----
bhdr_T *hp;
int got_int_save = got_int;

! if (mfp->mf_fd < 0)
{
! // there is no file, nothing to do
! mfp->mf_dirty = MF_DIRTY_NO;
return FAIL;
}

***************
*** 576,582 ****
* In case of an error this flag is also set, to avoid trying all the time.
*/
if (hp == NULL || status == FAIL)
! mfp->mf_dirty = FALSE;

if ((flags & MFS_FLUSH) && *p_sws != NUL)
{
--- 578,584 ----
* In case of an error this flag is also set, to avoid trying all the time.
*/
if (hp == NULL || status == FAIL)
! mfp->mf_dirty = MF_DIRTY_NO;

if ((flags & MFS_FLUSH) && *p_sws != NUL)
{
***************
*** 675,681 ****
for (hp = mfp->mf_used_last; hp != NULL; hp = hp->bh_prev)
if (hp->bh_bnum > 0)
hp->bh_flags |= BH_DIRTY;
! mfp->mf_dirty = TRUE;
}

/*
--- 677,683 ----
for (hp = mfp->mf_used_last; hp != NULL; hp = hp->bh_prev)
if (hp->bh_bnum > 0)
hp->bh_flags |= BH_DIRTY;
! mfp->mf_dirty = MF_DIRTY_YES;
}

/*
*** ../vim-9.0.1582/src/memline.c 2023-04-27 21:13:09.184215933 +0100
--- src/memline.c 2023-05-27 16:29:35.588799270 +0100
***************
*** 64,70 ****
#define BLOCK0_ID1_C0 'c' // block 0 id 1 'cm' 0
#define BLOCK0_ID1_C1 'C' // block 0 id 1 'cm' 1
#define BLOCK0_ID1_C2 'd' // block 0 id 1 'cm' 2
! // BLOCK0_ID1_C3 and BLOCK0_ID1_C4 are for libsodium enctyption. However, for
// these the swapfile is disabled, thus they will not be used. Added for
// consistency anyway.
#define BLOCK0_ID1_C3 'S' // block 0 id 1 'cm' 3
--- 64,70 ----
#define BLOCK0_ID1_C0 'c' // block 0 id 1 'cm' 0
#define BLOCK0_ID1_C1 'C' // block 0 id 1 'cm' 1
#define BLOCK0_ID1_C2 'd' // block 0 id 1 'cm' 2
! // BLOCK0_ID1_C3 and BLOCK0_ID1_C4 are for libsodium encryption. However, for
// these the swapfile is disabled, thus they will not be used. Added for
// consistency anyway.
#define BLOCK0_ID1_C3 'S' // block 0 id 1 'cm' 3
***************
*** 807,812 ****
--- 807,814 ----
continue;
if (mf_open_file(mfp, fname) == OK) // consumes fname!
{
+ // don't sync yet in ml_sync_all()
+ mfp->mf_dirty = MF_DIRTY_YES_NOSYNC;
#if defined(MSWIN)
/*
* set full pathname for swap file now, because a ":!cd dir" may
***************
*** 939,945 ****
&& b0p->b0_id[1] != BLOCK0_ID1_C0
&& b0p->b0_id[1] != BLOCK0_ID1_C1
&& b0p->b0_id[1] != BLOCK0_ID1_C2
! && b0p->b0_id[1] != BLOCK0_ID1_C3)
)
return FAIL;
return OK;
--- 941,948 ----
&& b0p->b0_id[1] != BLOCK0_ID1_C0
&& b0p->b0_id[1] != BLOCK0_ID1_C1
&& b0p->b0_id[1] != BLOCK0_ID1_C2
! && b0p->b0_id[1] != BLOCK0_ID1_C3
! && b0p->b0_id[1] != BLOCK0_ID1_C4)
)
return FAIL;
return OK;
***************
*** 2513,2519 ****
need_check_timestamps = TRUE; // give message later
}
}
! if (buf->b_ml.ml_mfp->mf_dirty)
{
(void)mf_sync(buf->b_ml.ml_mfp, (check_char ? MFS_STOP : 0)
| (bufIsChanged(buf) ? MFS_FLUSH : 0));
--- 2516,2522 ----
need_check_timestamps = TRUE; // give message later
}
}
! if (buf->b_ml.ml_mfp->mf_dirty == MF_DIRTY_YES)
{
(void)mf_sync(buf->b_ml.ml_mfp, (check_char ? MFS_STOP : 0)
| (bufIsChanged(buf) ? MFS_FLUSH : 0));
*** ../vim-9.0.1582/src/crypt.c 2023-05-20 16:39:03.337433572 +0100
--- src/crypt.c 2023-05-27 17:48:30.240642842 +0100
***************
*** 525,531 ****
if (arg.cat_seed_len > 0)
arg.cat_seed = header + CRYPT_MAGIC_LEN + arg.cat_salt_len;
if (arg.cat_add_len > 0)
! arg.cat_add = header + CRYPT_MAGIC_LEN + arg.cat_salt_len + arg.cat_seed_len;

return crypt_create(method_nr, key, &arg);
}
--- 525,532 ----
if (arg.cat_seed_len > 0)
arg.cat_seed = header + CRYPT_MAGIC_LEN + arg.cat_salt_len;
if (arg.cat_add_len > 0)
! arg.cat_add = header + CRYPT_MAGIC_LEN
! + arg.cat_salt_len + arg.cat_seed_len;

return crypt_create(method_nr, key, &arg);
}
***************
*** 603,609 ****
if (arg.cat_seed_len > 0)
arg.cat_seed = *header + CRYPT_MAGIC_LEN + arg.cat_salt_len;
if (arg.cat_add_len > 0)
! arg.cat_add = *header + CRYPT_MAGIC_LEN + arg.cat_salt_len + arg.cat_seed_len;

// TODO: Should this be crypt method specific? (Probably not worth
// it). sha2_seed is pretty bad for large amounts of entropy, so make
--- 604,611 ----
if (arg.cat_seed_len > 0)
arg.cat_seed = *header + CRYPT_MAGIC_LEN + arg.cat_salt_len;
if (arg.cat_add_len > 0)
! arg.cat_add = *header + CRYPT_MAGIC_LEN
! + arg.cat_salt_len + arg.cat_seed_len;

// TODO: Should this be crypt method specific? (Probably not worth
// it). sha2_seed is pretty bad for large amounts of entropy, so make
***************
*** 795,804 ****
}
}

! #ifdef FEAT_SODIUM
! static void
crypt_check_swapfile_curbuf(void)
{
int method = crypt_get_method_nr(curbuf);
if (crypt_method_is_sodium(method))
{
--- 797,810 ----
}
}

! /*
! * If the crypt method for "curbuf" does not support encrypting the swap file
! * then disable the swap file.
! */
! void
crypt_check_swapfile_curbuf(void)
{
+ #ifdef FEAT_SODIUM
int method = crypt_get_method_nr(curbuf);
if (crypt_method_is_sodium(method))
{
***************
*** 809,816 ****
msg_scroll = TRUE;
msg(_("Note: Encryption of swapfile not supported, disabling swap file"));
}
- }
#endif

void
crypt_check_current_method(void)
--- 815,822 ----
msg_scroll = TRUE;
msg(_("Note: Encryption of swapfile not supported, disabling swap file"));
}
#endif
+ }

void
crypt_check_current_method(void)
***************
*** 863,871 ****
set_option_value_give_err((char_u *)"key", 0L, p1, OPT_LOCAL);
crypt_free_key(p1);
p1 = curbuf->b_p_key;
- #ifdef FEAT_SODIUM
crypt_check_swapfile_curbuf();
- #endif
}
break;
}
--- 869,875 ----
***************
*** 959,965 ****
sodium_free(sd_state);
return FAIL;
}
! if (state->method_nr == CRYPT_M_SOD2)
{
memcpy(arg->cat_add, &opslimit, sizeof(opslimit));
arg->cat_add += sizeof(opslimit);
--- 963,970 ----
sodium_free(sd_state);
return FAIL;
}
! // "cat_add" should not be NULL, check anyway for safety
! if (state->method_nr == CRYPT_M_SOD2 && arg->cat_add != NULL)
{
memcpy(arg->cat_add, &opslimit, sizeof(opslimit));
arg->cat_add += sizeof(opslimit);
*** ../vim-9.0.1582/src/proto/crypt.pro 2023-04-23 17:50:14.853935966 +0100
--- src/proto/crypt.pro 2023-05-27 17:41:05.316792383 +0100
***************
*** 22,27 ****
--- 22,28 ----
void crypt_decode_inplace(cryptstate_T *state, char_u *buf, size_t len, int last);
void crypt_free_key(char_u *key);
void crypt_check_method(int method);
+ void crypt_check_swapfile_curbuf(void);
void crypt_check_current_method(void);
char_u *crypt_get_key(int store, int twice);
void crypt_append_msg(buf_T *buf);
*** ../vim-9.0.1582/src/structs.h 2023-05-06 22:21:07.247211940 +0100
--- src/structs.h 2023-05-27 17:22:02.661070039 +0100
***************
*** 691,696 ****
--- 691,702 ----
int cmod_did_esilent; // incremented when emsg_silent is
} cmdmod_T;

+ typedef enum {
+ MF_DIRTY_NO = 0, // no dirty blocks
+ MF_DIRTY_YES, // there are dirty blocks
+ MF_DIRTY_YES_NOSYNC, // there are dirty blocks, do not sync yet
+ } mfdirty_T;
+
#define MF_SEED_LEN 8

struct memfile
***************
*** 712,718 ****
blocknr_T mf_neg_count; // number of negative blocks numbers
blocknr_T mf_infile_count; // number of pages in the file
unsigned mf_page_size; // number of bytes in a page
! int mf_dirty; // TRUE if there are dirty blocks
#ifdef FEAT_CRYPT
buf_T *mf_buffer; // buffer this memfile is for
char_u mf_seed[MF_SEED_LEN]; // seed for encryption
--- 718,724 ----
blocknr_T mf_neg_count; // number of negative blocks numbers
blocknr_T mf_infile_count; // number of pages in the file
unsigned mf_page_size; // number of bytes in a page
! mfdirty_T mf_dirty;
#ifdef FEAT_CRYPT
buf_T *mf_buffer; // buffer this memfile is for
char_u mf_seed[MF_SEED_LEN]; // seed for encryption
*** ../vim-9.0.1582/src/buffer.c 2023-05-23 18:00:53.947320728 +0100
--- src/buffer.c 2023-05-27 17:15:39.001590554 +0100
***************
*** 218,223 ****
--- 218,227 ----
return FAIL;
}

+ // Do not sync this buffer yet, may first want to read the file.
+ if (curbuf->b_ml.ml_mfp != NULL)
+ curbuf->b_ml.ml_mfp->mf_dirty = MF_DIRTY_YES_NOSYNC;
+
// The autocommands in readfile() may change the buffer, but only AFTER
// reading the file.
set_bufref(&old_curbuf, curbuf);
***************
*** 298,303 ****
--- 302,312 ----
retval = read_buffer(TRUE, eap, flags);
}

+ // Can now sync this buffer in ml_sync_all().
+ if (curbuf->b_ml.ml_mfp != NULL
+ && curbuf->b_ml.ml_mfp->mf_dirty == MF_DIRTY_YES_NOSYNC)
+ curbuf->b_ml.ml_mfp->mf_dirty = MF_DIRTY_YES;
+
// if first time loading this buffer, init b_chartab[]
if (curbuf->b_flags & BF_NEVERLOADED)
{
*** ../vim-9.0.1582/src/fileio.c 2023-04-23 17:50:14.853935966 +0100
--- src/fileio.c 2023-05-27 17:41:25.320790220 +0100
***************
*** 125,130 ****
--- 125,131 ----
exarg_T *eap, // can be NULL!
int flags)
{
+ int retval = FAIL; // jump to "theend" instead of returning
int fd = 0;
int newfile = (flags & READ_NEW);
int check_readonly;
***************
*** 239,245 ****
&& !(flags & READ_DUMMY))
{
if (set_rw_fname(fname, sfname) == FAIL)
! return FAIL;
}

// Remember the initial values of curbuf, curbuf->b_ffname and
--- 240,246 ----
&& !(flags & READ_DUMMY))
{
if (set_rw_fname(fname, sfname) == FAIL)
! goto theend;
}

// Remember the initial values of curbuf, curbuf->b_ffname and
***************
*** 289,323 ****
if (apply_autocmds_exarg(EVENT_BUFREADCMD, NULL, sfname,
FALSE, curbuf, eap))
{
! int status = OK;
#ifdef FEAT_EVAL
if (aborting())
! status = FAIL;
#endif
// The BufReadCmd code usually uses ":read" to get the text and
// perhaps ":file" to change the buffer name. But we should
// consider this to work like ":edit", thus reset the
// BF_NOTEDITED flag. Then ":write" will work to overwrite the
// same file.
! if (status == OK)
curbuf->b_flags &= ~BF_NOTEDITED;
! return status;
}
}
else if (apply_autocmds_exarg(EVENT_FILEREADCMD, sfname, sfname,
FALSE, NULL, eap))
#ifdef FEAT_EVAL
! return aborting() ? FAIL : OK;
#else
! return OK;
#endif

curbuf->b_op_start = orig_start;

if (flags & READ_NOFILE)
// Return NOTDONE instead of FAIL so that BufEnter can be triggered
// and other operations don't fail.
! return NOTDONE;
}

if ((shortmess(SHM_OVER) || curbuf->b_help) && p_verbose == 0)
--- 290,330 ----
if (apply_autocmds_exarg(EVENT_BUFREADCMD, NULL, sfname,
FALSE, curbuf, eap))
{
! retval = OK;
#ifdef FEAT_EVAL
if (aborting())
! retval = FAIL;
#endif
// The BufReadCmd code usually uses ":read" to get the text and
// perhaps ":file" to change the buffer name. But we should
// consider this to work like ":edit", thus reset the
// BF_NOTEDITED flag. Then ":write" will work to overwrite the
// same file.
! if (retval == OK)
curbuf->b_flags &= ~BF_NOTEDITED;
! goto theend;
}
}
else if (apply_autocmds_exarg(EVENT_FILEREADCMD, sfname, sfname,
FALSE, NULL, eap))
+ {
#ifdef FEAT_EVAL
! retval = aborting() ? FAIL : OK;
#else
! retval = OK;
#endif
+ goto theend;
+ }

curbuf->b_op_start = orig_start;

if (flags & READ_NOFILE)
+ {
// Return NOTDONE instead of FAIL so that BufEnter can be triggered
// and other operations don't fail.
! retval = NOTDONE;
! goto theend;
! }
}

if ((shortmess(SHM_OVER) || curbuf->b_help) && p_verbose == 0)
***************
*** 335,341 ****
filemess(curbuf, fname, (char_u *)_("Illegal file name"), 0);
msg_end();
msg_scroll = msg_save;
! return FAIL;
}

// If the name ends in a path separator, we can't open it. Check here,
--- 342,348 ----
filemess(curbuf, fname, (char_u *)_("Illegal file name"), 0);
msg_end();
msg_scroll = msg_save;
! goto theend;
}

// If the name ends in a path separator, we can't open it. Check here,
***************
*** 346,352 ****
filemess(curbuf, fname, (char_u *)_(msg_is_a_directory), 0);
msg_end();
msg_scroll = msg_save;
! return NOTDONE;
}
}

--- 353,360 ----
filemess(curbuf, fname, (char_u *)_(msg_is_a_directory), 0);
msg_end();
msg_scroll = msg_save;
! retval = NOTDONE;
! goto theend;
}
}

***************
*** 367,374 ****
# endif
)
{
- int retval = FAIL;
-
if (S_ISDIR(perm))
{
filemess(curbuf, fname, (char_u *)_(msg_is_a_directory), 0);
--- 375,380 ----
***************
*** 378,384 ****
filemess(curbuf, fname, (char_u *)_("is not a file"), 0);
msg_end();
msg_scroll = msg_save;
! return retval;
}
#endif
#if defined(MSWIN)
--- 384,390 ----
filemess(curbuf, fname, (char_u *)_("is not a file"), 0);
msg_end();
msg_scroll = msg_save;
! goto theend;
}
#endif
#if defined(MSWIN)
***************
*** 391,397 ****
filemess(curbuf, fname, (char_u *)_("is a device (disabled with 'opendevice' option)"), 0);
msg_end();
msg_scroll = msg_save;
! return FAIL;
}
#endif
}
--- 397,403 ----
filemess(curbuf, fname, (char_u *)_("is a device (disabled with 'opendevice' option)"), 0);
msg_end();
msg_scroll = msg_save;
! goto theend;
}
#endif
}
***************
*** 534,540 ****
&& (old_b_fname != curbuf->b_fname)))
{
emsg(_(e_autocommands_changed_buffer_or_buffer_name));
! return FAIL;
}
}
if (dir_of_file_exists(fname))
--- 540,546 ----
&& (old_b_fname != curbuf->b_fname)))
{
emsg(_(e_autocommands_changed_buffer_or_buffer_name));
! goto theend;
}
}
if (dir_of_file_exists(fname))
***************
*** 557,566 ****
save_file_ff(curbuf);

#if defined(FEAT_EVAL)
! if (aborting()) // autocmds may abort script processing
! return FAIL;
#endif
! return OK; // a new file is not an error
}
else
{
--- 563,572 ----
save_file_ff(curbuf);

#if defined(FEAT_EVAL)
! if (!aborting()) // autocmds may abort script processing
#endif
! retval = OK; // a new file is not an error
! goto theend;
}
else
{
***************
*** 576,582 ****
}
}

! return FAIL;
}

/*
--- 582,588 ----
}
}

! goto theend;
}

/*
***************
*** 614,620 ****
emsg(_(e_autocommands_changed_buffer_or_buffer_name));
if (!read_buffer)
close(fd);
! return FAIL;
}
#ifdef UNIX
// Set swap file protection bits after creating it.
--- 620,626 ----
emsg(_(e_autocommands_changed_buffer_or_buffer_name));
if (!read_buffer)
close(fd);
! goto theend;
}
#ifdef UNIX
// Set swap file protection bits after creating it.
***************
*** 654,660 ****
{
if (!read_buffer && !read_stdin)
close(fd);
! return FAIL;
}

++no_wait_return; // don't wait for return yet
--- 660,666 ----
{
if (!read_buffer && !read_stdin)
close(fd);
! goto theend;
}

++no_wait_return; // don't wait for return yet
***************
*** 715,721 ****
--no_wait_return;
msg_scroll = msg_save;
curbuf->b_p_ro = TRUE; // must use "w!" now
! return FAIL;
}
#endif
/*
--- 721,727 ----
--no_wait_return;
msg_scroll = msg_save;
curbuf->b_p_ro = TRUE; // must use "w!" now
! goto theend;
}
#endif
/*
***************
*** 737,743 ****
else
emsg(_(e_readpre_autocommands_must_not_change_current_buffer));
curbuf->b_p_ro = TRUE; // must use "w!" now
! return FAIL;
}
}

--- 743,749 ----
else
emsg(_(e_readpre_autocommands_must_not_change_current_buffer));
curbuf->b_p_ro = TRUE; // must use "w!" now
! goto theend;
}
}

***************
*** 2461,2467 ****
#ifdef FEAT_VIMINFO
check_marks_read();
#endif
! return OK; // an interrupt isn't really an error
}

if (!filtering && !(flags & READ_DUMMY))
--- 2467,2474 ----
#ifdef FEAT_VIMINFO
check_marks_read();
#endif
! retval = OK; // an interrupt isn't really an error
! goto theend;
}

if (!filtering && !(flags & READ_DUMMY))
***************
*** 2696,2708 ****
msg_scroll = m;
# ifdef FEAT_EVAL
if (aborting()) // autocmds may abort script processing
! return FAIL;
# endif
}

! if (recoverymode && error)
! return FAIL;
! return OK;
}

#if defined(OPEN_CHR_FILES) || defined(PROTO)
--- 2703,2722 ----
msg_scroll = m;
# ifdef FEAT_EVAL
if (aborting()) // autocmds may abort script processing
! goto theend;
# endif
}

! if (!(recoverymode && error))
! retval = OK;
!
! theend:
! if (curbuf->b_ml.ml_mfp != NULL
! && curbuf->b_ml.ml_mfp->mf_dirty == MF_DIRTY_YES_NOSYNC)
! // OK to sync the swap file now
! curbuf->b_ml.ml_mfp->mf_dirty = MF_DIRTY_YES;
!
! return retval;
}

#if defined(OPEN_CHR_FILES) || defined(PROTO)
***************
*** 2941,2947 ****
--- 2955,2964 ----
if (cryptkey == NULL && !*did_ask)
{
if (*curbuf->b_p_key)
+ {
cryptkey = curbuf->b_p_key;
+ crypt_check_swapfile_curbuf();
+ }
else
{
// When newfile is TRUE, store the typed key in the 'key'
*** ../vim-9.0.1582/src/testdir/test_crypt.vim 2023-04-25 15:27:23.355582228 +0100
--- src/testdir/test_crypt.vim 2023-05-27 17:47:35.220670356 +0100
***************
*** 1,5 ****
--- 1,6 ----
" Tests for encryption.

+ source shared.vim
source check.vim
CheckFeature cryptv

***************
*** 88,93 ****
--- 89,117 ----
call Crypt_uncrypt('xchacha20v2')
endfunc

+ func Test_crypt_sodium_v2_startup()
+ CheckFeature sodium
+ CheckRunVimInTerminal
+
+ let buf = RunVimInTerminal('--cmd "set cm=xchacha20v2" -x Xfoo', #{wait_for_ruler: 0, rows: 6})
+ call g:TermWait(buf, g:RunningWithValgrind() ? 1000 : 50)
+ call term_sendkeys(buf, "foo\<CR>foo\<CR>")
+ call term_sendkeys(buf, "ifoo\<Esc>")
+ call term_sendkeys(buf, "ZZ")
+ call TermWait(buf)
+
+ " Wait for Vim to write the file and exit. Then wipe out the terminal buffer.
+ call WaitForAssert({-> assert_equal("finished", term_getstatus(buf))})
+ 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)
+
+ call delete('Xfoo')
+ endfunc
+
func Uncrypt_stable(method, crypted_text, key, uncrypted_text)
split Xtest.txt
set bin noeol key= fenc=latin1
*** ../vim-9.0.1582/src/version.c 2023-05-27 14:10:04.319182880 +0100
--- src/version.c 2023-05-27 17:44:31.116746546 +0100
***************
*** 697,698 ****
--- 697,700 ----
{ /* Add new patch number below this line */
+ /**/
+ 1583,
/**/

--
From "know your smileys":
y:-) Bad toupee

/// Bram Moolenaar -- Br...@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 ///
Reply all
Reply to author
Forward
0 new messages