musl: handle wcsnrtombs destination buffer overflow (CVE-2020-28928)
[openwrt/openwrt.git] / toolchain / musl / patches / 700-wcsnrtombs-cve-2020-28928.diff
1 diff --git a/src/multibyte/wcsnrtombs.c b/src/multibyte/wcsnrtombs.c
2 index 676932b5..95e25e70 100644
3 --- a/src/multibyte/wcsnrtombs.c
4 +++ b/src/multibyte/wcsnrtombs.c
5 @@ -1,41 +1,33 @@
6 #include <wchar.h>
7 +#include <limits.h>
8 +#include <string.h>
9
10 size_t wcsnrtombs(char *restrict dst, const wchar_t **restrict wcs, size_t wn, size_t n, mbstate_t *restrict st)
11 {
12 - size_t l, cnt=0, n2;
13 - char *s, buf[256];
14 const wchar_t *ws = *wcs;
15 - const wchar_t *tmp_ws;
16 -
17 - if (!dst) s = buf, n = sizeof buf;
18 - else s = dst;
19 -
20 - while ( ws && n && ( (n2=wn)>=n || n2>32 ) ) {
21 - if (n2>=n) n2=n;
22 - tmp_ws = ws;
23 - l = wcsrtombs(s, &ws, n2, 0);
24 - if (!(l+1)) {
25 - cnt = l;
26 - n = 0;
27 + size_t cnt = 0;
28 + if (!dst) n=0;
29 + while (ws && wn) {
30 + char tmp[MB_LEN_MAX];
31 + size_t l = wcrtomb(n<MB_LEN_MAX ? tmp : dst, *ws, 0);
32 + if (l==-1) {
33 + cnt = -1;
34 break;
35 }
36 - if (s != buf) {
37 - s += l;
38 + if (dst) {
39 + if (n<MB_LEN_MAX) {
40 + if (l>n) break;
41 + memcpy(dst, tmp, l);
42 + }
43 + dst += l;
44 n -= l;
45 }
46 - wn = ws ? wn - (ws - tmp_ws) : 0;
47 - cnt += l;
48 - }
49 - if (ws) while (n && wn) {
50 - l = wcrtomb(s, *ws, 0);
51 - if ((l+1)<=1) {
52 - if (!l) ws = 0;
53 - else cnt = l;
54 + if (!*ws) {
55 + ws = 0;
56 break;
57 }
58 - ws++; wn--;
59 - /* safe - this loop runs fewer than sizeof(buf) times */
60 - s+=l; n-=l;
61 + ws++;
62 + wn--;
63 cnt += l;
64 }
65 if (dst) *wcs = ws;