mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 9.0.1477: crash when recovering from corrupted swap file
Problem: Crash when recovering from corrupted swap file. Solution: Check for a valid page count. (closes #12275)
This commit is contained in:
@@ -3459,3 +3459,5 @@ EXTERN char e_cannot_use_non_null_object[]
|
|||||||
EXTERN char e_incomplete_type[]
|
EXTERN char e_incomplete_type[]
|
||||||
INIT(= N_("E1363: Incomplete type"));
|
INIT(= N_("E1363: Incomplete type"));
|
||||||
#endif
|
#endif
|
||||||
|
EXTERN char e_warning_pointer_block_corrupted[]
|
||||||
|
INIT(= N_("E1364: Warning: Pointer block corrupted"));
|
||||||
|
@@ -431,7 +431,9 @@ mf_get(memfile_T *mfp, blocknr_T nr, int page_count)
|
|||||||
* If not, allocate a new block.
|
* If not, allocate a new block.
|
||||||
*/
|
*/
|
||||||
hp = mf_release(mfp, page_count);
|
hp = mf_release(mfp, page_count);
|
||||||
if (hp == NULL && (hp = mf_alloc_bhdr(mfp, page_count)) == NULL)
|
if (hp == NULL && page_count > 0)
|
||||||
|
hp = mf_alloc_bhdr(mfp, page_count);
|
||||||
|
if (hp == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
hp->bh_bnum = nr;
|
hp->bh_bnum = nr;
|
||||||
@@ -812,9 +814,10 @@ mf_release(memfile_T *mfp, int page_count)
|
|||||||
*/
|
*/
|
||||||
if (hp->bh_page_count != page_count)
|
if (hp->bh_page_count != page_count)
|
||||||
{
|
{
|
||||||
vim_free(hp->bh_data);
|
VIM_CLEAR(hp->bh_data);
|
||||||
if ((hp->bh_data = alloc((size_t)mfp->mf_page_size * page_count))
|
if (page_count > 0)
|
||||||
== NULL)
|
hp->bh_data = alloc((size_t)mfp->mf_page_size * page_count);
|
||||||
|
if (hp->bh_data == NULL)
|
||||||
{
|
{
|
||||||
vim_free(hp);
|
vim_free(hp);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -872,7 +875,7 @@ mf_release_all(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate a block header and a block of memory for it
|
* Allocate a block header and a block of memory for it.
|
||||||
*/
|
*/
|
||||||
static bhdr_T *
|
static bhdr_T *
|
||||||
mf_alloc_bhdr(memfile_T *mfp, int page_count)
|
mf_alloc_bhdr(memfile_T *mfp, int page_count)
|
||||||
@@ -882,8 +885,7 @@ mf_alloc_bhdr(memfile_T *mfp, int page_count)
|
|||||||
if ((hp = ALLOC_ONE(bhdr_T)) == NULL)
|
if ((hp = ALLOC_ONE(bhdr_T)) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if ((hp->bh_data = alloc((size_t)mfp->mf_page_size * page_count))
|
if ((hp->bh_data = alloc((size_t)mfp->mf_page_size * page_count)) == NULL)
|
||||||
== NULL)
|
|
||||||
{
|
{
|
||||||
vim_free(hp); // not enough memory
|
vim_free(hp); // not enough memory
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -893,7 +895,7 @@ mf_alloc_bhdr(memfile_T *mfp, int page_count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Free a block header and the block of memory for it
|
* Free a block header and the block of memory for it.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
mf_free_bhdr(bhdr_T *hp)
|
mf_free_bhdr(bhdr_T *hp)
|
||||||
@@ -903,7 +905,7 @@ mf_free_bhdr(bhdr_T *hp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* insert entry *hp in the free list
|
* Insert entry *hp in the free list.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
mf_ins_free(memfile_T *mfp, bhdr_T *hp)
|
mf_ins_free(memfile_T *mfp, bhdr_T *hp)
|
||||||
|
@@ -98,6 +98,9 @@ struct pointer_block
|
|||||||
// followed by empty space until end of page
|
// followed by empty space until end of page
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Value for pb_count_max.
|
||||||
|
#define PB_COUNT_MAX(mfp) (short_u)(((mfp)->mf_page_size - offsetof(PTR_BL, pb_pointer)) / sizeof(PTR_EN))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A data block is a leaf in the tree.
|
* A data block is a leaf in the tree.
|
||||||
*
|
*
|
||||||
@@ -1525,6 +1528,20 @@ ml_recover(int checkext)
|
|||||||
pp = (PTR_BL *)(hp->bh_data);
|
pp = (PTR_BL *)(hp->bh_data);
|
||||||
if (pp->pb_id == PTR_ID) // it is a pointer block
|
if (pp->pb_id == PTR_ID) // it is a pointer block
|
||||||
{
|
{
|
||||||
|
int 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
|
// check line count when using pointer block first time
|
||||||
if (idx == 0 && line_count != 0)
|
if (idx == 0 && line_count != 0)
|
||||||
{
|
{
|
||||||
@@ -4162,9 +4179,7 @@ ml_new_ptr(memfile_T *mfp)
|
|||||||
pp = (PTR_BL *)(hp->bh_data);
|
pp = (PTR_BL *)(hp->bh_data);
|
||||||
pp->pb_id = PTR_ID;
|
pp->pb_id = PTR_ID;
|
||||||
pp->pb_count = 0;
|
pp->pb_count = 0;
|
||||||
pp->pb_count_max =
|
pp->pb_count_max = PB_COUNT_MAX(mfp);
|
||||||
(short_u)((mfp->mf_page_size - offsetof(PTR_BL, pb_pointer))
|
|
||||||
/ sizeof(PTR_EN));
|
|
||||||
|
|
||||||
return hp;
|
return hp;
|
||||||
}
|
}
|
||||||
|
@@ -249,6 +249,14 @@ func Test_recover_corrupted_swap_file()
|
|||||||
call assert_equal(['???EMPTY BLOCK'], getline(1, '$'))
|
call assert_equal(['???EMPTY BLOCK'], getline(1, '$'))
|
||||||
bw!
|
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
|
" set the block number in a pointer entry to a negative number
|
||||||
let b = copy(save_b)
|
let b = copy(save_b)
|
||||||
if system_64bit
|
if system_64bit
|
||||||
|
@@ -695,6 +695,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1477,
|
||||||
/**/
|
/**/
|
||||||
1476,
|
1476,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user