From: Hirohito Higashi Date: Thu, 18 Jun 2026 18:55:52 +0000 (+0000) Subject: patch 9.2.0672: corrupted text property causes internal error X-Git-Tag: v9.2.0672^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ec526e3a5c8aa287849c3e12b7654e527a59475b;p=thirdparty%2Fvim.git patch 9.2.0672: corrupted text property causes internal error Problem: Restoring a crafted/corrupted persistent-undo file and then inspecting the line (e.g. prop_list()) reports the bad text property data as an internal error. On builds with ABORT_ON_INTERNAL_ERROR (the sanitizer CI job) this aborts the process even inside assert_fails(), so the test added in 9.2.0670 fails deterministically. Solution: The prop data only comes from an untrusted persistent-undo file, so detecting it is input validation, not an internal bug. Report it with a normal error (emsg) instead of iemsg, matching how other corrupted persistent files are reported. The out-of-bounds read is still prevented. closes: #20559 Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Christian Brabandt --- diff --git a/src/testdir/test_textprop2.vim b/src/testdir/test_textprop2.vim index 48387d1c04..fdebf794af 100644 --- a/src/testdir/test_textprop2.vim +++ b/src/testdir/test_textprop2.vim @@ -479,8 +479,9 @@ func Test_textprop_undo_bad_prop_count() call prop_type_add('Xtp', {}) call prop_add(2, 1, {'type': 'Xtp', 'length': 1}) - " this caused OOB read, now it triggers internal error - call assert_fails('call prop_list(1)', ['E340:', 'corrupted']) + " this caused OOB read, now it is rejected as a corrupted (untrusted) undo + " file with a catchable error instead of an internal error + call assert_fails('call prop_list(1)', 'E967:') call prop_type_delete('Xtp') bwipe! diff --git a/src/textprop.c b/src/textprop.c index 858d8dbcec..e13e44b946 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -99,7 +99,7 @@ um_goto_line(unpacked_memline_T *um, linenr_T lnum, int extra_props) // New format: [prop_count (uint16)][textprop_T...][vtext...] if (propdata_len < PROP_COUNT_SIZE + sizeof(textprop_T)) { - iemsg(e_text_property_info_corrupted); + emsg(e_text_property_info_corrupted); um->buf = NULL; return false; } @@ -111,7 +111,7 @@ um_goto_line(unpacked_memline_T *um, linenr_T lnum, int extra_props) mch_memmove(&prop_count, count_ptr, PROP_COUNT_SIZE); if (!text_prop_count_valid(prop_count, propdata_len)) { - iemsg(e_text_property_info_corrupted); + emsg(e_text_property_info_corrupted); um->buf = NULL; return false; } @@ -1237,13 +1237,13 @@ get_text_props(buf_T *buf, linenr_T lnum, char_u **props, int will_change) // prop_count is never zero. if (propdata_len < PROP_COUNT_SIZE + sizeof(textprop_T)) { - iemsg(e_text_property_info_corrupted); + emsg(e_text_property_info_corrupted); return 0; } mch_memmove(&prop_count, text + textlen, PROP_COUNT_SIZE); if (!text_prop_count_valid(prop_count, propdata_len)) { - iemsg(e_text_property_info_corrupted); + emsg(e_text_property_info_corrupted); return 0; } *props = text + textlen + PROP_COUNT_SIZE; diff --git a/src/version.c b/src/version.c index ba2f392d18..af26854acb 100644 --- a/src/version.c +++ b/src/version.c @@ -759,6 +759,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 672, /**/ 671, /**/