Commit: patch 9.2.0672: corrupted text property causes internal error

0 views
Skip to first unread message

Christian Brabandt

unread,
Jun 18, 2026, 3:15:13 PM (12 hours ago) Jun 18
to vim...@googlegroups.com
patch 9.2.0672: corrupted text property causes internal error

Commit: https://github.com/vim/vim/commit/ec526e3a5c8aa287849c3e12b7654e527a59475b
Author: Hirohito Higashi <h.eas...@gmail.com>
Date: Thu Jun 18 18:55:52 2026 +0000

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) <nor...@anthropic.com>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/testdir/test_textprop2.vim b/src/testdir/test_textprop2.vim
index 48387d1c0..fdebf794a 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 858d8dbce..e13e44b94 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 ba2f392d1..af26854ac 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,
/**/
Reply all
Reply to author
Forward
0 new messages