summaryrefslogtreecommitdiffstats
path: root/usr.bin/less
diff options
context:
space:
mode:
authorschwarze <schwarze@openbsd.org>2019-03-12 11:59:24 +0000
committerschwarze <schwarze@openbsd.org>2019-03-12 11:59:24 +0000
commit7c92ba0ff878243e2dd07f13ac954dca496f722c (patch)
treefcb58e5db2107a41bd2be87f968f77355018c74e /usr.bin/less
parentMerge copy/pasted code to export STP states via ioctl into a function. (diff)
downloadwireguard-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.c46
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