]> git.ipfire.org Git - thirdparty/git.git/commitdiff
utf8: fix returning negative string width
authorPatrick Steinhardt <ps@pks.im>
Thu, 1 Dec 2022 14:47:00 +0000 (15:47 +0100)
committerJunio C Hamano <gitster@pobox.com>
Fri, 9 Dec 2022 05:26:21 +0000 (14:26 +0900)
The `utf8_strnwidth()` function calls `utf8_width()` in a loop and adds
its returned width to the end result. `utf8_width()` can return `-1`
though in case it reads a control character, which means that the
computed string width is going to be wrong. In the worst case where
there are more control characters than non-control characters, we may
even return a negative string width.

Fix this bug by treating control characters as having zero width.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
t/t4205-log-pretty-formats.sh
utf8.c

index c88b64d08b602ad9cb3410ffcb4117fad5b7e0eb..e3905baa3c473b8ffc3bed6654ca747a2608374b 100755 (executable)
@@ -899,6 +899,12 @@ test_expect_success SIZE_T_IS_64BIT 'log --pretty with overflowing wrapping dire
        test_cmp expect error
 '
 
+test_expect_success 'log --pretty with padding and preceding control chars' '
+       printf "\20\20   0" >expect &&
+       git log -1 --pretty="format:%x10%x10%>|(4)%x30" >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success EXPENSIVE,SIZE_T_IS_64BIT 'log --pretty with huge commit message' '
        # We only assert that this command does not crash. This needs to be
        # executed with the address sanitizer to demonstrate failure.
diff --git a/utf8.c b/utf8.c
index 504e517c341b8382531f6f7dd0b28b2c2fa0cd30..6a21fd6a7b0253ae73165024aae355f5f55f83bd 100644 (file)
--- a/utf8.c
+++ b/utf8.c
@@ -212,11 +212,15 @@ int utf8_strnwidth(const char *string, size_t len, int skip_ansi)
        const char *orig = string;
 
        while (string && string < orig + len) {
-               int skip;
+               int glyph_width, skip;
+
                while (skip_ansi &&
                       (skip = display_mode_esc_sequence_len(string)) != 0)
                        string += skip;
-               width += utf8_width(&string, NULL);
+
+               glyph_width = utf8_width(&string, NULL);
+               if (glyph_width > 0)
+                       width += glyph_width;
        }
        return string ? width : len;
 }