diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2022-01-23 06:52:59 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2022-01-25 15:26:05 +0000 |
commit | 86a16ada1ea608408cec370171d9f59353e97c77 (patch) | |
tree | 0c5efdf3ebd866d7e199e5b7177231c142af3e99 | |
parent | 59d465e200bb7058dfdb183c061730c10dd5bc03 (diff) | |
download | src-86a16ada1ea608408cec370171d9f59353e97c77.tar.gz src-86a16ada1ea608408cec370171d9f59353e97c77.zip |
__sflush(): on write error, if nothing was written, reset FILE state back
otherwise the data is just dropped. Check for current position equal to
the buffer base at the entry of the function; if not equal, setvbuf()
was done from the write method and it is not our business to override
the decision.
PR: 76398
Reviewed by: markj
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D34007
-rw-r--r-- | lib/libc/stdio/fflush.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/lib/libc/stdio/fflush.c b/lib/libc/stdio/fflush.c index f7d2fbdc28e5..decc974907f4 100644 --- a/lib/libc/stdio/fflush.c +++ b/lib/libc/stdio/fflush.c @@ -105,8 +105,8 @@ __weak_reference(__fflush, fflush_unlocked); int __sflush(FILE *fp) { - unsigned char *p; - int n, t; + unsigned char *p, *old_p; + int n, t, old_w; t = fp->_flags; if ((t & __SWR) == 0) @@ -121,7 +121,9 @@ __sflush(FILE *fp) * Set these immediately to avoid problems with longjmp and to allow * exchange buffering (via setvbuf) in user write function. */ + old_p = fp->_p; fp->_p = p; + old_w = fp->_w; fp->_w = t & (__SLBF|__SNBF) ? 0 : fp->_bf._size; for (; n > 0; n -= t, p += t) { @@ -134,6 +136,9 @@ __sflush(FILE *fp) fp->_p += n; if ((fp->_flags & (__SLBF | __SNBF)) == 0) fp->_w -= n; + } else if (p == fp->_p) { /* cond. to handle setvbuf */ + fp->_p = old_p; + fp->_w = old_w; } fp->_flags |= __SERR; return (EOF); |