aboutsummaryrefslogtreecommitdiffstats
path: root/main/musl/0011-fix-FILE-buffer-underflow-in-ungetwc.patch
blob: 78c716121af727632382a28c0c035842b43e621f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
From 6ed791e768d83b40ed56c99dbb1ed72c1e49aae7 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Tue, 26 Apr 2016 15:26:40 -0400
Subject: [PATCH] fix FILE buffer underflow in ungetwc

commit 7e816a6487932cbb3cb71d94b609e50e81f4e5bf (version 1.1.11
release cycle) moved the code that performs wchar_t to multibyte
conversion across code that used the resulting length in bytes,
thereby breaking the unget buffer space check in ungetwc and
clobbering up to three bytes below the start of the buffer.

for allocated FILEs (all read-enabled FILEs except stdin), the
underflow clobbers at most the FILE-specific locale pointer. no stores
are performed through this pointer, but subsequent loads may result in
a crash or mismatching encoding rule (UTF-8 multibyte vs byte-based).

for stdin, the buffer lies in .bss and the underflow may clobber
another object. in practice, for libc.so the adjacent object seems to
be stderr's buffer, which is completely unused, but this could vary
with linking options, or when static linking.

applications which do not attempt to use more than one character of
ungetwc pushback, or which do not use ungetwc, are not affected.
---
 src/stdio/ungetwc.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/stdio/ungetwc.c b/src/stdio/ungetwc.c
index 80d6e20..9edf366 100644
--- a/src/stdio/ungetwc.c
+++ b/src/stdio/ungetwc.c
@@ -8,7 +8,7 @@
 wint_t ungetwc(wint_t c, FILE *f)
 {
 	unsigned char mbc[MB_LEN_MAX];
-	int l=1;
+	int l;
 	locale_t *ploc = &CURRENT_LOCALE, loc = *ploc;
 
 	FLOCK(f);
@@ -17,8 +17,8 @@ wint_t ungetwc(wint_t c, FILE *f)
 	*ploc = f->locale;
 
 	if (!f->rpos) __toread(f);
-	if (!f->rpos || f->rpos < f->buf - UNGET + l || c == WEOF ||
-	    (!isascii(c) && (l = wctomb((void *)mbc, c)) < 0)) {
+	if (!f->rpos || c == WEOF || (l = wcrtomb((void *)mbc, c, 0)) < 0 ||
+	    f->rpos < f->buf - UNGET + l) {
 		FUNLOCK(f);
 		*ploc = loc;
 		return WEOF;
-- 
2.8.2