From bafaa70b6f9098d83d074968c8e6747ecec1e118 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 6 Mar 2022 10:59:39 +0200 Subject: [PATCH] libc __sfvwrite(): roll back FILE buffer pointer on fflush error __sfvwrite() advances the pointer before calling fflush. If fflush() fails, it is not enough to roll back inside it, because we cannot know how much was advanced by the caller. Reported by: Peter Reviewed by: markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Fixes: 86a16ada1ea608408cec370171d9f59353e97c77 --- lib/libc/stdio/fvwrite.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/libc/stdio/fvwrite.c b/lib/libc/stdio/fvwrite.c index 50b32b8eca6e..2a161859afa9 100644 --- a/lib/libc/stdio/fvwrite.c +++ b/lib/libc/stdio/fvwrite.c @@ -54,6 +54,7 @@ int __sfvwrite(FILE *fp, struct __suio *uio) { size_t len; + unsigned char *old_p; char *p; struct __siov *iov; int w, s; @@ -137,8 +138,12 @@ __sfvwrite(FILE *fp, struct __suio *uio) COPY(w); /* fp->_w -= w; */ /* unneeded */ fp->_p += w; - if (__fflush(fp)) + old_p = fp->_p; + if (__fflush(fp) == EOF) { + if (old_p == fp->_p) + fp->_p -= w; goto err; + } } else if (len >= (w = fp->_bf._size)) { /* write directly */ w = _swrite(fp, p, w); @@ -177,8 +182,12 @@ __sfvwrite(FILE *fp, struct __suio *uio) COPY(w); /* fp->_w -= w; */ fp->_p += w; - if (__fflush(fp)) + old_p = fp->_p; + if (__fflush(fp) == EOF) { + if (old_p == fp->_p) + fp->_p -= w; goto err; + } } else if (s >= (w = fp->_bf._size)) { w = _swrite(fp, p, w); if (w <= 0)