To: vim_dev@googlegroups.com Subject: Patch 9.0.1477 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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 -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///