mirror of
https://github.com/neovim/neovim.git
synced 2024-12-19 18:55:14 -07:00
vim-patch:9.0.1477: crash when recovering from corrupted swap file (#23273)
Problem: Crash when recovering from corrupted swap file.
Solution: Check for a valid page count. (closes vim/vim#12275)
b67ba03d3e
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
parent
431b152726
commit
77ff25b1d9
@ -300,7 +300,12 @@ bhdr_T *mf_get(memfile_T *mfp, blocknr_T nr, unsigned page_count)
|
||||
|
||||
// could check here if the block is in the free list
|
||||
|
||||
hp = mf_alloc_bhdr(mfp, page_count);
|
||||
if (page_count > 0) {
|
||||
hp = mf_alloc_bhdr(mfp, page_count);
|
||||
}
|
||||
if (hp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hp->bh_bnum = nr;
|
||||
hp->bh_flags = 0;
|
||||
|
@ -121,6 +121,10 @@ struct pointer_block {
|
||||
// followed by empty space until end of page
|
||||
};
|
||||
|
||||
// Value for pb_count_max.
|
||||
#define PB_COUNT_MAX(mfp) \
|
||||
(uint16_t)((mfp->mf_page_size - offsetof(PTR_BL, pb_pointer)) / sizeof(PTR_EN))
|
||||
|
||||
// A data block is a leaf in the tree.
|
||||
//
|
||||
// The text of the lines is at the end of the block. The text of the first line
|
||||
@ -244,6 +248,9 @@ typedef enum {
|
||||
# include "memline.c.generated.h"
|
||||
#endif
|
||||
|
||||
static char e_warning_pointer_block_corrupted[]
|
||||
= N_("E1364: Warning: Pointer block corrupted");
|
||||
|
||||
#if __has_feature(address_sanitizer)
|
||||
# define ML_GET_ALLOC_LINES
|
||||
#endif
|
||||
@ -986,6 +993,19 @@ void ml_recover(bool checkext)
|
||||
} else { // there is a block
|
||||
pp = hp->bh_data;
|
||||
if (pp->pb_id == PTR_ID) { // it is a pointer block
|
||||
bool ptr_block_error = false;
|
||||
if (pp->pb_count_max != PB_COUNT_MAX(mfp)) {
|
||||
ptr_block_error = true;
|
||||
pp->pb_count_max = PB_COUNT_MAX(mfp);
|
||||
}
|
||||
if (pp->pb_count > pp->pb_count_max) {
|
||||
ptr_block_error = true;
|
||||
pp->pb_count = pp->pb_count_max;
|
||||
}
|
||||
if (ptr_block_error) {
|
||||
emsg(_(e_warning_pointer_block_corrupted));
|
||||
}
|
||||
|
||||
// check line count when using pointer block first time
|
||||
if (idx == 0 && line_count != 0) {
|
||||
for (int i = 0; i < (int)pp->pb_count; i++) {
|
||||
@ -2752,8 +2772,7 @@ static bhdr_T *ml_new_ptr(memfile_T *mfp)
|
||||
PTR_BL *pp = hp->bh_data;
|
||||
pp->pb_id = PTR_ID;
|
||||
pp->pb_count = 0;
|
||||
pp->pb_count_max
|
||||
= (uint16_t)((mfp->mf_page_size - offsetof(PTR_BL, pb_pointer)) / sizeof(PTR_EN));
|
||||
pp->pb_count_max = PB_COUNT_MAX(mfp);
|
||||
|
||||
return hp;
|
||||
}
|
||||
|
@ -259,6 +259,14 @@ func Test_recover_corrupted_swap_file()
|
||||
call assert_equal(['???EMPTY BLOCK'], getline(1, '$'))
|
||||
bw!
|
||||
|
||||
" set the number of pointers in a pointer block to a large value
|
||||
let b = copy(save_b)
|
||||
let b[4098:4099] = 0zFFFF
|
||||
call writefile(b, sn)
|
||||
call assert_fails('recover Xfile1', 'E1364:')
|
||||
call assert_equal('Xfile1', @%)
|
||||
bw!
|
||||
|
||||
" set the block number in a pointer entry to a negative number
|
||||
let b = copy(save_b)
|
||||
if system_64bit
|
||||
|
Loading…
Reference in New Issue
Block a user