Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libc/stdio Avoid undefined behavior in fread(3)



details:   https://anonhg.NetBSD.org/src/rev/01764d8c0f68
branches:  trunk
changeset: 1007562:01764d8c0f68
user:      kamil <kamil%NetBSD.org@localhost>
date:      Sat Feb 22 22:02:46 2020 +0000

description:
Avoid undefined behavior in fread(3)

On the first call to fread(3), just after fopen(3) the internal buffers
are empty. This means that _r and _p (among others) are zeroed.

Passing NULL to the 2nd argument of memcpy(3) for the zero length is
undefined. Calling _p += 0 triggers LLVM UBSan (NULL pointer arithmetic).
Calling _p += 0, p += 0 and resid -= 0 has no effect.

Replace the "fp->_r = 0;" logic with a short circuit jump to __srefill()
that sets _r internally and refills the FILE buffers.

No functional change from an end user point of view, except skipping a few
dummy operations on the first call, for a FILE pointer, to fread(3).

diffstat:

 lib/libc/stdio/fread.c |  13 +++++++++----
 1 files changed, 9 insertions(+), 4 deletions(-)

diffs (42 lines):

diff -r 756a6f103813 -r 01764d8c0f68 lib/libc/stdio/fread.c
--- a/lib/libc/stdio/fread.c    Sat Feb 22 21:59:30 2020 +0000
+++ b/lib/libc/stdio/fread.c    Sat Feb 22 22:02:46 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fread.c,v 1.22 2012/03/15 18:22:30 christos Exp $      */
+/*     $NetBSD: fread.c,v 1.23 2020/02/22 22:02:46 kamil Exp $ */
 
 /*-
  * Copyright (c) 1990, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)fread.c    8.2 (Berkeley) 12/11/93";
 #else
-__RCSID("$NetBSD: fread.c,v 1.22 2012/03/15 18:22:30 christos Exp $");
+__RCSID("$NetBSD: fread.c,v 1.23 2020/02/22 22:02:46 kamil Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -68,16 +68,21 @@
        _DIAGASSERT(buf != NULL);
 
        FLOCKFILE(fp);
-       if (fp->_r < 0)
-               fp->_r = 0;
        total = resid;
        p = buf;
+
+       if (fp->_r <= 0) {
+               /* Nothing to read on enter, refill the buffers. */
+               goto refill;
+       }
+
        while (resid > (size_t)(r = fp->_r)) {
                (void)memcpy(p, fp->_p, (size_t)r);
                fp->_p += r;
                /* fp->_r = 0 ... done in __srefill */
                p += r;
                resid -= r;
+refill:
                if (__srefill(fp)) {
                        /* no more input: return partial result */
                        FUNLOCKFILE(fp);



Home | Main Index | Thread Index | Old Index