0
0
mirror of https://github.com/vim/vim.git synced 2025-10-16 07:24:23 -04:00

patch 9.0.1494: crash when recovering from corrupted swap file

Problem:    Crash when recovering from corrupted swap file.
Solution:   Bail out when the line index looks wrong. (closes #12276)
This commit is contained in:
Bram Moolenaar
2023-04-27 21:13:12 +01:00
parent 4e1ca0d9a6
commit bf1b713202
3 changed files with 46 additions and 12 deletions

View File

@@ -1637,14 +1637,13 @@ ml_recover(int checkext)
else else
{ {
/* /*
* it is a data block * It is a data block.
* Append all the lines in this block * Append all the lines in this block.
*/ */
has_error = FALSE; has_error = FALSE;
/*
* check length of block // Check the length of the block.
* if wrong, use length in pointer block // If wrong, use the length given in the pointer block.
*/
if (page_count * mfp->mf_page_size != dp->db_txt_end) if (page_count * mfp->mf_page_size != dp->db_txt_end)
{ {
ml_append(lnum++, (char_u *)_("??? from here until ???END lines may be messed up"), ml_append(lnum++, (char_u *)_("??? from here until ???END lines may be messed up"),
@@ -1654,13 +1653,12 @@ ml_recover(int checkext)
dp->db_txt_end = page_count * mfp->mf_page_size; dp->db_txt_end = page_count * mfp->mf_page_size;
} }
// make sure there is a NUL at the end of the block // Make sure there is a NUL at the end of the block so we
// don't go over the end when copying text.
*((char_u *)dp + dp->db_txt_end - 1) = NUL; *((char_u *)dp + dp->db_txt_end - 1) = NUL;
/* // Check the number of lines in the block.
* check number of lines in block // If wrong, use the count in the data block.
* if wrong, use count in data block
*/
if (line_count != dp->db_line_count) if (line_count != dp->db_line_count)
{ {
ml_append(lnum++, (char_u *)_("??? from here until ???END lines may have been inserted/deleted"), ml_append(lnum++, (char_u *)_("??? from here until ???END lines may have been inserted/deleted"),
@@ -1669,17 +1667,36 @@ ml_recover(int checkext)
has_error = TRUE; has_error = TRUE;
} }
int did_questions = FALSE;
for (i = 0; i < dp->db_line_count; ++i) for (i = 0; i < dp->db_line_count; ++i)
{ {
if ((char_u *)&(dp->db_index[i])
>= (char_u *)dp + dp->db_txt_start)
{
// line count must be wrong
++error;
ml_append(lnum++,
(char_u *)_("??? lines may be missing"),
(colnr_T)0, TRUE);
break;
}
txt_start = (dp->db_index[i] & DB_INDEX_MASK); txt_start = (dp->db_index[i] & DB_INDEX_MASK);
if (txt_start <= (int)HEADER_SIZE if (txt_start <= (int)HEADER_SIZE
|| txt_start >= (int)dp->db_txt_end) || txt_start >= (int)dp->db_txt_end)
{ {
p = (char_u *)"???";
++error; ++error;
// avoid lots of lines with "???"
if (did_questions)
continue;
did_questions = TRUE;
p = (char_u *)"???";
} }
else else
{
did_questions = FALSE;
p = (char_u *)dp + txt_start; p = (char_u *)dp + txt_start;
}
ml_append(lnum++, p, (colnr_T)0, TRUE); ml_append(lnum++, p, (colnr_T)0, TRUE);
} }
if (has_error) if (has_error)

View File

@@ -293,6 +293,21 @@ func Test_recover_corrupted_swap_file()
\ '???END'], getline(1, '$')) \ '???END'], getline(1, '$'))
bw! bw!
" set the number of lines in the data block to a large value
let b = copy(save_b)
if system_64bit
let b[8208:8215] = 0z00FFFFFF.FFFFFF00
else
let b[8208:8211] = 0z00FFFF00
endif
call writefile(b, sn)
call assert_fails('recover Xfile1', 'E312:')
call assert_equal('Xfile1', @%)
call assert_equal(['??? from here until ???END lines may have been inserted/deleted',
\ '', '???', '??? lines may be missing',
\ '???END'], getline(1, '$'))
bw!
" use an invalid text start for the lines in a data block " use an invalid text start for the lines in a data block
let b = copy(save_b) let b = copy(save_b)
if system_64bit if system_64bit

View File

@@ -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 */
/**/
1494,
/**/ /**/
1493, 1493,
/**/ /**/