From f660d7f0b6f2e5fcee6f47328a1862d6ae76af07 Mon Sep 17 00:00:00 2001 From: "powwow@askgustav.com" Date: Sat, 18 Feb 2017 23:09:19 +0100 Subject: more robust multibyte character handling diff --git a/tty.c b/tty.c index 5e4ff7a..57aa5b6 100644 --- a/tty.c +++ b/tty.c @@ -875,11 +875,37 @@ int tty_printf __P ((const char *format, ...)) } static char tty_in_buf[MB_LEN_MAX + 1]; -static int tty_in_buf_used = 0; +static size_t tty_in_buf_used = 0; int tty_has_chars __P ((void)) { - return !!tty_in_buf_used; + return tty_in_buf_used != 0; +} + +static int safe_mbtowc __P3 (wchar_t *,pwc, char *,s, size_t *,n) +{ + static mbstate_t ps; + + size_t r; + +again: + r = mbrtowc(pwc, s, *n, &ps); + if (r == (size_t)-2) { + /* incomplete character */ + *n = 0; + return -1; + } + if (r == (size_t)-1 && errno == EILSEQ) { + /* invalid character */ + --*n; + memmove(s, s + 1, *n); + goto again; + } + if (r == 0 && n > 0 && s[0] == 0) { + *pwc = L'\0'; + r = 1; + } + return r; } int tty_read __P ((char *buf, size_t count)) @@ -888,9 +914,9 @@ int tty_read __P ((char *buf, size_t count)) int converted; wchar_t wc; int did_read = 0, should_read = 0; - + if (count && tty_in_buf_used) { - converted = mbtowc(&wc, tty_in_buf, tty_in_buf_used); + converted = safe_mbtowc(&wc, tty_in_buf, &tty_in_buf_used); if (converted >= 0) goto another; } @@ -907,7 +933,7 @@ int tty_read __P ((char *buf, size_t count)) tty_in_buf_used += did_read; - converted = mbtowc(&wc, tty_in_buf, tty_in_buf_used); + converted = safe_mbtowc(&wc, tty_in_buf, &tty_in_buf_used); if (converted < 0) break; @@ -927,7 +953,7 @@ int tty_read __P ((char *buf, size_t count)) if (count == 0) break; - converted = mbtowc(&wc, tty_in_buf, tty_in_buf_used); + converted = safe_mbtowc(&wc, tty_in_buf, &tty_in_buf_used); if (converted >= 0 && tty_in_buf_used) goto another; -- cgit v0.10.2