]> xenbits.xensource.com Git - people/royger/freebsd.git/commitdiff
libc __sfvwrite(): roll back FILE buffer pointer on fflush error
authorKonstantin Belousov <kib@FreeBSD.org>
Sun, 6 Mar 2022 08:59:39 +0000 (10:59 +0200)
committerMark Johnston <markj@FreeBSD.org>
Mon, 14 Mar 2022 15:47:24 +0000 (11:47 -0400)
__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 <pmc@citylink.dinoex.sub.org>
Approved by: re (gjb)
Reviewed by: markj
Sponsored by: The FreeBSD Foundation
Fixes: 86a16ada1ea608408cec370171d9f59353e97c77

(cherry picked from commit bafaa70b6f9098d83d074968c8e6747ecec1e118)
(cherry picked from commit 647f02d68a60b66d063a15feed3c817966114d52)

lib/libc/stdio/fvwrite.c

index 50b32b8eca6e10a34d53cd552a59df50aecd61c4..2a161859afa9a6cedcb36419bb72de90a4c457dd 100644 (file)
@@ -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)