projects
/
musl
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
fix undefined behavior in getdelim via null pointer arithmetic and memcpy
[musl]
/
src
/
multibyte
/
wcsnrtombs.c
diff --git
a/src/multibyte/wcsnrtombs.c
b/src/multibyte/wcsnrtombs.c
index
70b0cac
..
95e25e7
100644
(file)
--- a/
src/multibyte/wcsnrtombs.c
+++ b/
src/multibyte/wcsnrtombs.c
@@
-1,51
+1,34
@@
-/*
- * This code was written by Rich Felker in 2010; no copyright is claimed.
- * This code is in the public domain. Attribution is appreciated but
- * unnecessary.
- */
-
-#include <stdlib.h>
-#include <inttypes.h>
#include <wchar.h>
#include <wchar.h>
-#include <errno.h>
-
-#include "internal.h"
+#include <limits.h>
+#include <string.h>
-size_t wcsnrtombs(char *
dst, const wchar_t **wcs, size_t wn, size_t n, mbstate_t *
st)
+size_t wcsnrtombs(char *
restrict dst, const wchar_t **restrict wcs, size_t wn, size_t n, mbstate_t *restrict
st)
{
{
- size_t l, cnt=0, n2;
- char *s, buf[256];
const wchar_t *ws = *wcs;
const wchar_t *ws = *wcs;
-
- if (!dst) s = buf, n = sizeof buf;
- else s = dst;
-
- while ( ws && n && ( (n2=wn)>=n || n2>32 ) ) {
- if (n2>=n) n2=n;
- wn -= n2;
- l = wcsrtombs(s, &ws, n2, 0);
- if (!(l+1)) {
- cnt = l;
- n = 0;
+ size_t cnt = 0;
+ if (!dst) n=0;
+ while (ws && wn) {
+ char tmp[MB_LEN_MAX];
+ size_t l = wcrtomb(n<MB_LEN_MAX ? tmp : dst, *ws, 0);
+ if (l==-1) {
+ cnt = -1;
break;
}
break;
}
- if (s != buf) {
- s += l;
+ if (dst) {
+ if (n<MB_LEN_MAX) {
+ if (l>n) break;
+ memcpy(dst, tmp, l);
+ }
+ dst += l;
n -= l;
}
n -= l;
}
- cnt += l;
- }
- if (ws) while (n && wn) {
- l = wcrtomb(s, *ws, 0);
- if ((l+1)<=1) {
- if (!l) ws = 0;
- else cnt = l;
+ if (!*ws) {
+ ws = 0;
break;
}
break;
}
- ws++; wn--;
- /* safe - this loop runs fewer than sizeof(buf) times */
- s+=l; n-=l;
- cnt++;
+ ws++;
+ wn--;
+ cnt += l;
}
if (dst) *wcs = ws;
return cnt;
}
if (dst) *wcs = ws;
return cnt;