comparison src/fileio.c @ 32503:5d07e7e9580f v9.0.1583

patch 9.0.1583: get E304 when using 'cryptmethod' "xchacha20v2" Commit: https://github.com/vim/vim/commit/3a2a60ce4a8e73594bca16814672fcc243d093ac Author: Bram Moolenaar <Bram@vim.org> Date: Sat May 27 18:02:55 2023 +0100 patch 9.0.1583: get E304 when using 'cryptmethod' "xchacha20v2" 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)
author Bram Moolenaar <Bram@vim.org>
date Sat, 27 May 2023 19:15:04 +0200
parents 3d4e28569a6d
children a4b5a6a95005
comparison
equal deleted inserted replaced
32502:b1bb97d879b6 32503:5d07e7e9580f
123 linenr_T lines_to_skip, 123 linenr_T lines_to_skip,
124 linenr_T lines_to_read, 124 linenr_T lines_to_read,
125 exarg_T *eap, // can be NULL! 125 exarg_T *eap, // can be NULL!
126 int flags) 126 int flags)
127 { 127 {
128 int retval = FAIL; // jump to "theend" instead of returning
128 int fd = 0; 129 int fd = 0;
129 int newfile = (flags & READ_NEW); 130 int newfile = (flags & READ_NEW);
130 int check_readonly; 131 int check_readonly;
131 int filtering = (flags & READ_FILTER); 132 int filtering = (flags & READ_FILTER);
132 int read_stdin = (flags & READ_STDIN); 133 int read_stdin = (flags & READ_STDIN);
237 && fname != NULL 238 && fname != NULL
238 && vim_strchr(p_cpo, CPO_FNAMER) != NULL 239 && vim_strchr(p_cpo, CPO_FNAMER) != NULL
239 && !(flags & READ_DUMMY)) 240 && !(flags & READ_DUMMY))
240 { 241 {
241 if (set_rw_fname(fname, sfname) == FAIL) 242 if (set_rw_fname(fname, sfname) == FAIL)
242 return FAIL; 243 goto theend;
243 } 244 }
244 245
245 // Remember the initial values of curbuf, curbuf->b_ffname and 246 // Remember the initial values of curbuf, curbuf->b_ffname and
246 // curbuf->b_fname to detect whether they are altered as a result of 247 // curbuf->b_fname to detect whether they are altered as a result of
247 // executing nasty autocommands. Also check if "fname" and "sfname" 248 // executing nasty autocommands. Also check if "fname" and "sfname"
287 if (newfile) 288 if (newfile)
288 { 289 {
289 if (apply_autocmds_exarg(EVENT_BUFREADCMD, NULL, sfname, 290 if (apply_autocmds_exarg(EVENT_BUFREADCMD, NULL, sfname,
290 FALSE, curbuf, eap)) 291 FALSE, curbuf, eap))
291 { 292 {
292 int status = OK; 293 retval = OK;
293 #ifdef FEAT_EVAL 294 #ifdef FEAT_EVAL
294 if (aborting()) 295 if (aborting())
295 status = FAIL; 296 retval = FAIL;
296 #endif 297 #endif
297 // The BufReadCmd code usually uses ":read" to get the text and 298 // The BufReadCmd code usually uses ":read" to get the text and
298 // perhaps ":file" to change the buffer name. But we should 299 // perhaps ":file" to change the buffer name. But we should
299 // consider this to work like ":edit", thus reset the 300 // consider this to work like ":edit", thus reset the
300 // BF_NOTEDITED flag. Then ":write" will work to overwrite the 301 // BF_NOTEDITED flag. Then ":write" will work to overwrite the
301 // same file. 302 // same file.
302 if (status == OK) 303 if (retval == OK)
303 curbuf->b_flags &= ~BF_NOTEDITED; 304 curbuf->b_flags &= ~BF_NOTEDITED;
304 return status; 305 goto theend;
305 } 306 }
306 } 307 }
307 else if (apply_autocmds_exarg(EVENT_FILEREADCMD, sfname, sfname, 308 else if (apply_autocmds_exarg(EVENT_FILEREADCMD, sfname, sfname,
308 FALSE, NULL, eap)) 309 FALSE, NULL, eap))
310 {
309 #ifdef FEAT_EVAL 311 #ifdef FEAT_EVAL
310 return aborting() ? FAIL : OK; 312 retval = aborting() ? FAIL : OK;
311 #else 313 #else
312 return OK; 314 retval = OK;
313 #endif 315 #endif
316 goto theend;
317 }
314 318
315 curbuf->b_op_start = orig_start; 319 curbuf->b_op_start = orig_start;
316 320
317 if (flags & READ_NOFILE) 321 if (flags & READ_NOFILE)
322 {
318 // Return NOTDONE instead of FAIL so that BufEnter can be triggered 323 // Return NOTDONE instead of FAIL so that BufEnter can be triggered
319 // and other operations don't fail. 324 // and other operations don't fail.
320 return NOTDONE; 325 retval = NOTDONE;
326 goto theend;
327 }
321 } 328 }
322 329
323 if ((shortmess(SHM_OVER) || curbuf->b_help) && p_verbose == 0) 330 if ((shortmess(SHM_OVER) || curbuf->b_help) && p_verbose == 0)
324 msg_scroll = FALSE; // overwrite previous file message 331 msg_scroll = FALSE; // overwrite previous file message
325 else 332 else
333 if (namelen >= MAXPATHL) 340 if (namelen >= MAXPATHL)
334 { 341 {
335 filemess(curbuf, fname, (char_u *)_("Illegal file name"), 0); 342 filemess(curbuf, fname, (char_u *)_("Illegal file name"), 0);
336 msg_end(); 343 msg_end();
337 msg_scroll = msg_save; 344 msg_scroll = msg_save;
338 return FAIL; 345 goto theend;
339 } 346 }
340 347
341 // If the name ends in a path separator, we can't open it. Check here, 348 // If the name ends in a path separator, we can't open it. Check here,
342 // because reading the file may actually work, but then creating the 349 // because reading the file may actually work, but then creating the
343 // swap file may destroy it! Reported on MS-DOS and Win 95. 350 // swap file may destroy it! Reported on MS-DOS and Win 95.
344 if (after_pathsep(fname, fname + namelen)) 351 if (after_pathsep(fname, fname + namelen))
345 { 352 {
346 filemess(curbuf, fname, (char_u *)_(msg_is_a_directory), 0); 353 filemess(curbuf, fname, (char_u *)_(msg_is_a_directory), 0);
347 msg_end(); 354 msg_end();
348 msg_scroll = msg_save; 355 msg_scroll = msg_save;
349 return NOTDONE; 356 retval = NOTDONE;
357 goto theend;
350 } 358 }
351 } 359 }
352 360
353 if (!read_stdin && !read_buffer && !read_fifo) 361 if (!read_stdin && !read_buffer && !read_fifo)
354 { 362 {
365 && !(S_ISCHR(perm) && is_dev_fd_file(fname)) 373 && !(S_ISCHR(perm) && is_dev_fd_file(fname))
366 // ... or a character special file named /dev/fd/<n> 374 // ... or a character special file named /dev/fd/<n>
367 # endif 375 # endif
368 ) 376 )
369 { 377 {
370 int retval = FAIL;
371
372 if (S_ISDIR(perm)) 378 if (S_ISDIR(perm))
373 { 379 {
374 filemess(curbuf, fname, (char_u *)_(msg_is_a_directory), 0); 380 filemess(curbuf, fname, (char_u *)_(msg_is_a_directory), 0);
375 retval = NOTDONE; 381 retval = NOTDONE;
376 } 382 }
377 else 383 else
378 filemess(curbuf, fname, (char_u *)_("is not a file"), 0); 384 filemess(curbuf, fname, (char_u *)_("is not a file"), 0);
379 msg_end(); 385 msg_end();
380 msg_scroll = msg_save; 386 msg_scroll = msg_save;
381 return retval; 387 goto theend;
382 } 388 }
383 #endif 389 #endif
384 #if defined(MSWIN) 390 #if defined(MSWIN)
385 /* 391 /*
386 * MS-Windows allows opening a device, but we will probably get stuck 392 * MS-Windows allows opening a device, but we will probably get stuck
389 if (!p_odev && mch_nodetype(fname) == NODE_WRITABLE) 395 if (!p_odev && mch_nodetype(fname) == NODE_WRITABLE)
390 { 396 {
391 filemess(curbuf, fname, (char_u *)_("is a device (disabled with 'opendevice' option)"), 0); 397 filemess(curbuf, fname, (char_u *)_("is a device (disabled with 'opendevice' option)"), 0);
392 msg_end(); 398 msg_end();
393 msg_scroll = msg_save; 399 msg_scroll = msg_save;
394 return FAIL; 400 goto theend;
395 } 401 }
396 #endif 402 #endif
397 } 403 }
398 404
399 // Set default or forced 'fileformat' and 'binary'. 405 // Set default or forced 'fileformat' and 'binary'.
532 && (old_b_ffname != curbuf->b_ffname)) 538 && (old_b_ffname != curbuf->b_ffname))
533 || (using_b_fname 539 || (using_b_fname
534 && (old_b_fname != curbuf->b_fname))) 540 && (old_b_fname != curbuf->b_fname)))
535 { 541 {
536 emsg(_(e_autocommands_changed_buffer_or_buffer_name)); 542 emsg(_(e_autocommands_changed_buffer_or_buffer_name));
537 return FAIL; 543 goto theend;
538 } 544 }
539 } 545 }
540 if (dir_of_file_exists(fname)) 546 if (dir_of_file_exists(fname))
541 filemess(curbuf, sfname, 547 filemess(curbuf, sfname,
542 (char_u *)new_file_message(), 0); 548 (char_u *)new_file_message(), 0);
555 FALSE, curbuf, eap); 561 FALSE, curbuf, eap);
556 // remember the current fileformat 562 // remember the current fileformat
557 save_file_ff(curbuf); 563 save_file_ff(curbuf);
558 564
559 #if defined(FEAT_EVAL) 565 #if defined(FEAT_EVAL)
560 if (aborting()) // autocmds may abort script processing 566 if (!aborting()) // autocmds may abort script processing
561 return FAIL; 567 #endif
562 #endif 568 retval = OK; // a new file is not an error
563 return OK; // a new file is not an error 569 goto theend;
564 } 570 }
565 else 571 else
566 { 572 {
567 filemess(curbuf, sfname, (char_u *)( 573 filemess(curbuf, sfname, (char_u *)(
568 # ifdef EFBIG 574 # ifdef EFBIG
574 _("[Permission Denied]")), 0); 580 _("[Permission Denied]")), 0);
575 curbuf->b_p_ro = TRUE; // must use "w!" now 581 curbuf->b_p_ro = TRUE; // must use "w!" now
576 } 582 }
577 } 583 }
578 584
579 return FAIL; 585 goto theend;
580 } 586 }
581 587
582 /* 588 /*
583 * Only set the 'ro' flag for readonly files the first time they are 589 * Only set the 'ro' flag for readonly files the first time they are
584 * loaded. Help files always get readonly mode 590 * loaded. Help files always get readonly mode
612 || (using_b_fname && (old_b_fname != curbuf->b_fname)))) 618 || (using_b_fname && (old_b_fname != curbuf->b_fname))))
613 { 619 {
614 emsg(_(e_autocommands_changed_buffer_or_buffer_name)); 620 emsg(_(e_autocommands_changed_buffer_or_buffer_name));
615 if (!read_buffer) 621 if (!read_buffer)
616 close(fd); 622 close(fd);
617 return FAIL; 623 goto theend;
618 } 624 }
619 #ifdef UNIX 625 #ifdef UNIX
620 // Set swap file protection bits after creating it. 626 // Set swap file protection bits after creating it.
621 if (swap_mode > 0 && curbuf->b_ml.ml_mfp != NULL 627 if (swap_mode > 0 && curbuf->b_ml.ml_mfp != NULL
622 && curbuf->b_ml.ml_mfp->mf_fname != NULL) 628 && curbuf->b_ml.ml_mfp->mf_fname != NULL)
652 // If "Quit" selected at ATTENTION dialog, don't load the file 658 // If "Quit" selected at ATTENTION dialog, don't load the file
653 if (swap_exists_action == SEA_QUIT) 659 if (swap_exists_action == SEA_QUIT)
654 { 660 {
655 if (!read_buffer && !read_stdin) 661 if (!read_buffer && !read_stdin)
656 close(fd); 662 close(fd);
657 return FAIL; 663 goto theend;
658 } 664 }
659 665
660 ++no_wait_return; // don't wait for return yet 666 ++no_wait_return; // don't wait for return yet
661 667
662 /* 668 /*
713 if (aborting()) // autocmds may abort script processing 719 if (aborting()) // autocmds may abort script processing
714 { 720 {
715 --no_wait_return; 721 --no_wait_return;
716 msg_scroll = msg_save; 722 msg_scroll = msg_save;
717 curbuf->b_p_ro = TRUE; // must use "w!" now 723 curbuf->b_p_ro = TRUE; // must use "w!" now
718 return FAIL; 724 goto theend;
719 } 725 }
720 #endif 726 #endif
721 /* 727 /*
722 * Don't allow the autocommands to change the current buffer. 728 * Don't allow the autocommands to change the current buffer.
723 * Try to re-open the file. 729 * Try to re-open the file.
735 if (fd < 0) 741 if (fd < 0)
736 emsg(_(e_readpre_autocommands_made_file_unreadable)); 742 emsg(_(e_readpre_autocommands_made_file_unreadable));
737 else 743 else
738 emsg(_(e_readpre_autocommands_must_not_change_current_buffer)); 744 emsg(_(e_readpre_autocommands_must_not_change_current_buffer));
739 curbuf->b_p_ro = TRUE; // must use "w!" now 745 curbuf->b_p_ro = TRUE; // must use "w!" now
740 return FAIL; 746 goto theend;
741 } 747 }
742 } 748 }
743 749
744 // Autocommands may add lines to the file, need to check if it is empty 750 // Autocommands may add lines to the file, need to check if it is empty
745 wasempty = (curbuf->b_ml.ml_flags & ML_EMPTY); 751 wasempty = (curbuf->b_ml.ml_flags & ML_EMPTY);
2459 } 2465 }
2460 msg_scroll = msg_save; 2466 msg_scroll = msg_save;
2461 #ifdef FEAT_VIMINFO 2467 #ifdef FEAT_VIMINFO
2462 check_marks_read(); 2468 check_marks_read();
2463 #endif 2469 #endif
2464 return OK; // an interrupt isn't really an error 2470 retval = OK; // an interrupt isn't really an error
2471 goto theend;
2465 } 2472 }
2466 2473
2467 if (!filtering && !(flags & READ_DUMMY)) 2474 if (!filtering && !(flags & READ_DUMMY))
2468 { 2475 {
2469 msg_add_fname(curbuf, sfname); // fname in IObuff with quotes 2476 msg_add_fname(curbuf, sfname); // fname in IObuff with quotes
2694 FALSE, NULL, eap); 2701 FALSE, NULL, eap);
2695 if (msg_scrolled == n) 2702 if (msg_scrolled == n)
2696 msg_scroll = m; 2703 msg_scroll = m;
2697 # ifdef FEAT_EVAL 2704 # ifdef FEAT_EVAL
2698 if (aborting()) // autocmds may abort script processing 2705 if (aborting()) // autocmds may abort script processing
2699 return FAIL; 2706 goto theend;
2700 # endif 2707 # endif
2701 } 2708 }
2702 2709
2703 if (recoverymode && error) 2710 if (!(recoverymode && error))
2704 return FAIL; 2711 retval = OK;
2705 return OK; 2712
2713 theend:
2714 if (curbuf->b_ml.ml_mfp != NULL
2715 && curbuf->b_ml.ml_mfp->mf_dirty == MF_DIRTY_YES_NOSYNC)
2716 // OK to sync the swap file now
2717 curbuf->b_ml.ml_mfp->mf_dirty = MF_DIRTY_YES;
2718
2719 return retval;
2706 } 2720 }
2707 2721
2708 #if defined(OPEN_CHR_FILES) || defined(PROTO) 2722 #if defined(OPEN_CHR_FILES) || defined(PROTO)
2709 /* 2723 /*
2710 * Returns TRUE if the file name argument is of the form "/dev/fd/\d\+", 2724 * Returns TRUE if the file name argument is of the form "/dev/fd/\d\+",
2939 // Set the cryptmethod local to the buffer. 2953 // Set the cryptmethod local to the buffer.
2940 crypt_set_cm_option(curbuf, method); 2954 crypt_set_cm_option(curbuf, method);
2941 if (cryptkey == NULL && !*did_ask) 2955 if (cryptkey == NULL && !*did_ask)
2942 { 2956 {
2943 if (*curbuf->b_p_key) 2957 if (*curbuf->b_p_key)
2958 {
2944 cryptkey = curbuf->b_p_key; 2959 cryptkey = curbuf->b_p_key;
2960 crypt_check_swapfile_curbuf();
2961 }
2945 else 2962 else
2946 { 2963 {
2947 // When newfile is TRUE, store the typed key in the 'key' 2964 // When newfile is TRUE, store the typed key in the 'key'
2948 // option and don't free it. bf needs hash of the key saved. 2965 // option and don't free it. bf needs hash of the key saved.
2949 // Don't ask for the key again when first time Enter was hit. 2966 // Don't ask for the key again when first time Enter was hit.