]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0939: mbyte: wrong cell count for an overlong UTF-8 sequence v9.2.0939
authorHirohito Higashi <h.east.727@gmail.com>
Tue, 11 Aug 2026 19:16:00 +0000 (19:16 +0000)
committerChristian Brabandt <cb@256bit.org>
Tue, 11 Aug 2026 19:16:00 +0000 (19:16 +0000)
Problem:  An overlong UTF-8 encoding of an unprintable ASCII character is
          displayed as <xx> but counted as two screen cells, so that the
          cursor ends up in the wrong position when editing the line.
Solution: Count four cells for an unprintable overlong sequence.

fixes:  #20988
closes: #21005

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/mbyte.c
src/testdir/test_utf8.vim
src/version.c

index 54ee229a1afd7cc43949dec9246c18f79632e055..e196f30cae75104ba1523ce20a3c5b634b7e345e 100644 (file)
@@ -1645,7 +1645,7 @@ utf_ptr2cells(
            return 4;
        // If the char is ASCII it must be an overlong sequence.
        if (c < 0x80)
-           return char2cells(c);
+           return vim_isprintc(c) ? char2cells(c) : 4;
        return utf_char2cells(c);
     }
     return 1;
@@ -1689,7 +1689,7 @@ utf_ptr2cells_len(char_u *p, int size)
            return 4;
        // If the char is ASCII it must be an overlong sequence.
        if (c < 0x80)
-           return char2cells(c);
+           return vim_isprintc(c) ? char2cells(c) : 4;
        return utf_char2cells(c);
     }
     return 1;
index a0cd5bd79ffbac251d265303579e44c52b00052f..3070d4cc4b8e3250c6ae09121be093bfedf913eb 100644 (file)
@@ -372,4 +372,20 @@ func Test_print_overlong()
   bwipe!
 endfunc
 
+" The cell count of an overlong encoded character must match what is drawn.
+func Test_overlong_utf8_cells()
+  call assert_equal(4, strdisplaywidth("\xc0\x81"))     " <01>
+  call assert_equal(4, strdisplaywidth("\xe0\x80\x81")) " <01>, three bytes
+  call assert_equal(4, strdisplaywidth("\xc1\xbf"))     " <7f>
+  call assert_equal(4, strdisplaywidth("\xc0\x89"))     " <09>, not a Tab
+
+  new
+  call setline(1, "\xc1\x81\xc0\x81\xc0\x80")
+  call assert_equal('A<01><00>', ScreenLines(1, 9)[0])
+  normal! $
+  call assert_equal(5, col('.'))
+  call assert_equal([6, 9], virtcol('.', v:true))
+  bwipe!
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index 48a1faf0fb1a57b7a5edf3ca84c4f6f7217e1515..6405f229e6b03ac11828a90b463762bed4a9d5a5 100644 (file)
@@ -763,6 +763,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    939,
 /**/
     938,
 /**/