diff options
author | ache <ache@FreeBSD.org> | 2016-09-05 02:00:35 +0000 |
---|---|---|
committer | ache <ache@FreeBSD.org> | 2016-09-05 02:00:35 +0000 |
commit | 1607ddf6f3616915773c73484c679fb7778fdb9f (patch) | |
tree | 4e83a90593aa5d0175104fa10b0a8e9aeb366c7d /lib/libc | |
parent | d319cd96df894f881c5b334a2d1db5665bd76f56 (diff) | |
download | FreeBSD-src-1607ddf6f3616915773c73484c679fb7778fdb9f.zip FreeBSD-src-1607ddf6f3616915773c73484c679fb7778fdb9f.tar.gz |
MFC r305241
fgetwc(3) may set both __SEOF and __SERR at once (in case of incomplete
sequence near EOF), so we can't just check for
(wc == WEOF && !__sfeof(fp)) and must relay on __sferror(fp) with
__SERR clearing/restoring.
Diffstat (limited to 'lib/libc')
-rw-r--r-- | lib/libc/stdio/fgetwln.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/lib/libc/stdio/fgetwln.c b/lib/libc/stdio/fgetwln.c index 34a80a0..037657c 100644 --- a/lib/libc/stdio/fgetwln.c +++ b/lib/libc/stdio/fgetwln.c @@ -47,11 +47,16 @@ fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t locale) { wint_t wc; size_t len; + int savserr; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); + savserr = fp->_flags & __SERR; + fp->_flags &= ~__SERR; + len = 0; while ((wc = __fgetwc(fp, locale)) != WEOF) { #define GROW 512 @@ -64,7 +69,12 @@ fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t locale) if (wc == L'\n') break; } - if (len == 0 || (wc == WEOF && !__sfeof(fp))) + /* fgetwc(3) may set both __SEOF and __SERR at once. */ + if (__sferror(fp)) + goto error; + + fp->_flags |= savserr; + if (len == 0) goto error; FUNLOCKFILE(fp); |