diff options
author | 2019-03-12 11:59:24 +0000 | |
---|---|---|
committer | 2019-03-12 11:59:24 +0000 | |
commit | 7c92ba0ff878243e2dd07f13ac954dca496f722c (patch) | |
tree | fcb58e5db2107a41bd2be87f968f77355018c74e /usr.bin/less | |
parent | Merge copy/pasted code to export STP states via ioctl into a function. (diff) | |
download | wireguard-openbsd-7c92ba0ff878243e2dd07f13ac954dca496f722c.tar.xz wireguard-openbsd-7c92ba0ff878243e2dd07f13ac954dca496f722c.zip |
Clean up UTF-8 handling in backc():
Use wchar_t instead of LWCHAR and mbtowc(3) instead of step_char().
Play it safe and handle all error cases, even in the arguably unlikely
case that linebuf[] contains UTF-8 encoding errors.
Reset mbtowc(3) internal state after failure for portability,
also in one place where mbtowc(3) was already introduced earlier.
OK nicm@
Diffstat (limited to 'usr.bin/less')
-rw-r--r-- | usr.bin/less/line.c | 46 |
1 files changed, 38 insertions, 8 deletions
diff --git a/usr.bin/less/line.c b/usr.bin/less/line.c index acc9e604ce7..01c7ede581d 100644 --- a/usr.bin/less/line.c +++ b/usr.bin/less/line.c @@ -437,23 +437,51 @@ pwidth(wchar_t ch, int a, wchar_t prev_ch) static int backc(void) { - LWCHAR prev_ch; - char *p = linebuf + curr; - LWCHAR ch = step_char(&p, -1, linebuf + lmargin); - int width; + wchar_t ch, prev_ch; + int i, len, width; + + i = curr - 1; + if (utf_mode) { + while (i >= lmargin && IS_UTF8_TRAIL(linebuf[i])) + i--; + } + if (i < lmargin) + return (0); + if (utf_mode) { + len = mbtowc(&ch, linebuf + i, curr - i); + if (len == -1 || i + len < curr) { + (void)mbtowc(NULL, NULL, MB_CUR_MAX); + return (0); + } + } else + ch = linebuf[i]; /* This assumes that there is no '\b' in linebuf. */ while (curr > lmargin && column > lmargin && (!(attr[curr - 1] & (AT_ANSI|AT_BINARY)))) { - curr = p - linebuf; - prev_ch = step_char(&p, -1, linebuf + lmargin); + curr = i--; + if (utf_mode) { + while (i >= lmargin && IS_UTF8_TRAIL(linebuf[i])) + i--; + } + if (i < lmargin) + prev_ch = L'\0'; + else if (utf_mode) { + len = mbtowc(&prev_ch, linebuf + i, curr - i); + if (len == -1 || i + len < curr) { + (void)mbtowc(NULL, NULL, MB_CUR_MAX); + prev_ch = L'\0'; + } + } else + prev_ch = linebuf[i]; width = pwidth(ch, attr[curr], prev_ch); column -= width; if (width > 0) return (1); + if (prev_ch == L'\0') + return (0); ch = prev_ch; } - return (0); } @@ -536,8 +564,10 @@ store_char(LWCHAR ch, char a, char *rep, off_t pos) break; if (i >= 0) { w = mbtowc(&prev_ch, linebuf + i, curr - i); - if (w == -1 || i + w < curr) + if (w == -1 || i + w < curr) { + (void)mbtowc(NULL, NULL, MB_CUR_MAX); prev_ch = L' '; + } } else prev_ch = L' '; } else |