Patch 9.0.1477
Problem: Crash when recovering from corrupted swap file.
Solution: Check for a valid page count. (closes #12275)
Files: src/memfile.c, src/memline.c, src/errors.h,
src/testdir/test_recover.vim
*** ../vim-9.0.1476/src/memfile.c 2023-01-14 12:32:24.219984103 +0000
--- src/memfile.c 2023-04-22 20:39:53.820244408 +0100
***************
*** 431,437 ****
* If not, allocate a new block.
*/
hp = mf_release(mfp, page_count);
! if (hp == NULL && (hp = mf_alloc_bhdr(mfp, page_count)) == NULL)
return NULL;
hp->bh_bnum = nr;
--- 431,439 ----
* If not, allocate a new block.
*/
hp = mf_release(mfp, page_count);
! if (hp == NULL && page_count > 0)
! hp = mf_alloc_bhdr(mfp, page_count);
! if (hp == NULL)
return NULL;
hp->bh_bnum = nr;
***************
*** 812,820 ****
*/
if (hp->bh_page_count != page_count)
{
! vim_free(hp->bh_data);
! if ((hp->bh_data = alloc((size_t)mfp->mf_page_size * page_count))
! == NULL)
{
vim_free(hp);
return NULL;
--- 814,823 ----
*/
if (hp->bh_page_count != page_count)
{
! VIM_CLEAR(hp->bh_data);
! if (page_count > 0)
! hp->bh_data = alloc((size_t)mfp->mf_page_size * page_count);
! if (hp->bh_data == NULL)
{
vim_free(hp);
return NULL;
***************
*** 872,878 ****
}
/*
! * Allocate a block header and a block of memory for it
*/
static bhdr_T *
mf_alloc_bhdr(memfile_T *mfp, int page_count)
--- 875,881 ----
}
/*
! * Allocate a block header and a block of memory for it.
*/
static bhdr_T *
mf_alloc_bhdr(memfile_T *mfp, int page_count)
***************
*** 882,889 ****
if ((hp = ALLOC_ONE(bhdr_T)) == NULL)
return NULL;
! if ((hp->bh_data = alloc((size_t)mfp->mf_page_size * page_count))
! == NULL)
{
vim_free(hp); // not enough memory
return NULL;
--- 885,891 ----
if ((hp = ALLOC_ONE(bhdr_T)) == NULL)
return NULL;
! if ((hp->bh_data = alloc((size_t)mfp->mf_page_size * page_count)) == NULL)
{
vim_free(hp); // not enough memory
return NULL;
***************
*** 893,899 ****
}
/*
! * Free a block header and the block of memory for it
*/
static void
mf_free_bhdr(bhdr_T *hp)
--- 895,901 ----
}
/*
! * Free a block header and the block of memory for it.
*/
static void
mf_free_bhdr(bhdr_T *hp)
***************
*** 903,909 ****
}
/*
! * insert entry *hp in the free list
*/
static void
mf_ins_free(memfile_T *mfp, bhdr_T *hp)
--- 905,911 ----
}
/*
! * Insert entry *hp in the free list.
*/
static void
mf_ins_free(memfile_T *mfp, bhdr_T *hp)
*** ../vim-9.0.1476/src/memline.c 2023-02-01 13:11:11.714991151 +0000
--- src/memline.c 2023-04-22 21:01:59.296312442 +0100
***************
*** 98,103 ****
--- 98,106 ----
// 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.
*
***************
*** 1525,1530 ****
--- 1528,1547 ----
pp = (PTR_BL *)(hp->bh_data);
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
if (idx == 0 && line_count != 0)
{
***************
*** 4162,4170 ****
pp = (PTR_BL *)(hp->bh_data);
pp->pb_id = PTR_ID;
pp->pb_count = 0;
! pp->pb_count_max =
! (short_u)((mfp->mf_page_size - offsetof(PTR_BL, pb_pointer))
! / sizeof(PTR_EN));
return hp;
}
--- 4179,4185 ----
pp = (PTR_BL *)(hp->bh_data);
pp->pb_id = PTR_ID;
pp->pb_count = 0;
! pp->pb_count_max = PB_COUNT_MAX(mfp);
return hp;
}
*** ../vim-9.0.1476/src/errors.h 2023-04-13 19:15:50.027391986 +0100
--- src/errors.h 2023-04-22 20:59:04.348375914 +0100
***************
*** 3459,3461 ****
--- 3459,3463 ----
EXTERN char e_incomplete_type[]
INIT(= N_("E1363: Incomplete type"));
#endif
+ EXTERN char e_warning_pointer_block_corrupted[]
+ INIT(= N_("E1364: Warning: Pointer block corrupted"));
*** ../vim-9.0.1476/src/testdir/test_recover.vim 2022-11-17
15:23:48.458617558 +0000
--- src/testdir/test_recover.vim 2023-04-22 21:10:52.468573068 +0100
***************
*** 249,254 ****
--- 249,262 ----
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
*** ../vim-9.0.1476/src/version.c 2023-04-22 15:35:08.861815544 +0100
--- src/version.c 2023-04-22 20:30:31.356016527 +0100
***************
*** 697,698 ****
--- 697,700 ----
{ /* Add new patch number below this line */
+ /**/
+ 1477,
/**/
--
INSPECTOR END OF FILM: Move along. There's nothing to see! Keep moving!
[Suddenly he notices the cameras.]
INSPECTOR END OF FILM: (to Camera) All right, put that away sonny.
[He walks over to it and puts his hand over the lens.]
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
/// Bram Moolenaar -- [email protected] -- 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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/20230422201457.35FED1C074F%40moolenaar.net.