Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20230529183341.198911-1-izbyshev@ispras.ru>
Date: Mon, 29 May 2023 21:33:41 +0300
From: Alexey Izbyshev <izbyshev@...ras.ru>
To: musl@...ts.openwall.com
Subject: [PATCH] mbsrtowcs: fix wrong *src update in case of EILSEQ with non-initial mbstate_t

If mbsrtowcs is called with non-initial conversion state, it resumes
from the point where normally the first byte of a multibyte sequence has
already been consumed. If the multibyte sequence can't be completed, s is
decremented with the intention to point it to the start of that
sequence, but in this case it ends up equal to src-1.

Fix that by remembering the start of the last (sub)sequence that we
tried to convert instead of decrementing s. Do this only if ws is not
NULL, since we don't update *src otherwise.
---
 src/multibyte/mbsrtowcs.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/src/multibyte/mbsrtowcs.c b/src/multibyte/mbsrtowcs.c
index 9b2f2dfb..cbab539d 100644
--- a/src/multibyte/mbsrtowcs.c
+++ b/src/multibyte/mbsrtowcs.c
@@ -7,12 +7,13 @@
 
 size_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbstate_t *restrict st)
 {
-	const unsigned char *s = (const void *)*src;
+	const unsigned char *s = (const void *)*src, *s0;
 	size_t wn0 = wn;
 	unsigned c = 0;
 
 	if (st && (c = *(unsigned *)st)) {
 		if (ws) {
+			s0 = s;
 			*(unsigned *)st = 0;
 			goto resume;
 		} else {
@@ -55,13 +56,13 @@ size_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbs
 		if (*s-SA > SB-SA) break;
 		c = bittab[*s++-SA];
 resume0:
-		if (OOB(c,*s)) { s--; break; }
+		if (OOB(c,*s)) break;
 		s++;
 		if (c&(1U<<25)) {
-			if (*s-0x80u >= 0x40) { s-=2; break; }
+			if (*s-0x80u >= 0x40) break;
 			s++;
 			if (c&(1U<<19)) {
-				if (*s-0x80u >= 0x40) { s-=3; break; }
+				if (*s-0x80u >= 0x40) break;
 				s++;
 			}
 		}
@@ -89,16 +90,17 @@ resume0:
 			wn--;
 			continue;
 		}
+		s0 = s;
 		if (*s-SA > SB-SA) break;
 		c = bittab[*s++-SA];
 resume:
-		if (OOB(c,*s)) { s--; break; }
+		if (OOB(c,*s)) break;
 		c = (c<<6) | *s++-0x80;
 		if (c&(1U<<31)) {
-			if (*s-0x80u >= 0x40) { s-=2; break; }
+			if (*s-0x80u >= 0x40) break;
 			c = (c<<6) | *s++-0x80;
 			if (c&(1U<<31)) {
-				if (*s-0x80u >= 0x40) { s-=3; break; }
+				if (*s-0x80u >= 0x40) break;
 				c = (c<<6) | *s++-0x80;
 			}
 		}
@@ -115,6 +117,6 @@ resume:
 		return wn0-wn;
 	}
 	errno = EILSEQ;
-	if (ws) *src = (const void *)s;
+	if (ws) *src = (const void *)s0;
 	return -1;
 }
-- 
2.39.2

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.