After read errors, fgetln(3) sometimes succeeded (returning non-NULL)
authorschwarze <schwarze@openbsd.org>
Thu, 25 Aug 2016 19:21:33 +0000 (19:21 +0000)
committerschwarze <schwarze@openbsd.org>
Thu, 25 Aug 2016 19:21:33 +0000 (19:21 +0000)
and failed (setting errno and ferror(3)) both at the same time.
That's a bad idea in general, and here in particular since
returning partial lines was neither reliable (sometimes, you
got NULL anyway) nor predictable (almost always, the line would
be truncated long before the actual read error).
Instead, on read failure, fail properly and always return NULL.
Issue found in a discussion with Andrey Chernov <ache at freebsd dot org>
who finally agreed to move FreeBSD into the same direction.
The fix is joint work with and OK by millert@.

lib/libc/stdio/fgetln.c

index ae2eb10..a5ea1b3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: fgetln.c,v 1.14 2015/08/31 02:53:57 guenther Exp $ */
+/*     $OpenBSD: fgetln.c,v 1.15 2016/08/25 19:21:33 schwarze Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *     The Regents of the University of California.  All rights reserved.
@@ -115,8 +115,11 @@ fgetln(FILE *fp, size_t *lenp)
                (void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
                    len - off);
                off = len;
-               if (__srefill(fp))
-                       break;  /* EOF or error: return partial line */
+               if (__srefill(fp)) {
+                       if (fp->_flags & __SEOF)
+                               break;
+                       goto error;
+               }
                if ((p = memchr((void *)fp->_p, '\n', fp->_r)) == NULL)
                        continue;