The branch main has been updated by se:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=10af8e45a89818754b80315539e167ae49599f17

commit 10af8e45a89818754b80315539e167ae49599f17
Author:     Stefan Eßer <s...@freebsd.org>
AuthorDate: 2022-01-15 23:30:04 +0000
Commit:     Stefan Eßer <s...@freebsd.org>
CommitDate: 2022-01-15 23:43:56 +0000

    fread.c: fix undefined behavior
    
    A case of undefined behavior in __fread() has been detected by UBSAN
    and reported by Mark Millard:
    
    /usr/main-src/lib/libc/stdio/fread.c:133:10: runtime error: applying
    zero offset to null pointer
    SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior in
    /usr/main-src/lib/libc/stdio/fread.c:133:10
    
    While being benign (the NULL pointer is later passed to memcpy() with
    a length argument of 0), this issue causes in the order of 600 Kyua
    test cases to fail on systems running a world built with WITH_UBSAN
    and WITH_ASAN.
    
    The undefined behavior can be prevented by skipping operations that
    have no effect for r == 0. Mark Millard has suggested to only skip
    this code segment if fp->_p == NULL, but I have verified that for the
    case of r == 0 no further argument checking is performed on the
    addresses passed to memcpy() and thus no bugs are hidden from the
    sanitizers due to the simpler condition chosen.
    
    Reported by:    Mark Millard (mark...@yahoo.com)
    Tested by:      Mark Millard (mark...@yahoo.com)
    Differential Revision:  https://reviews.freebsd.org/D33903
    MFC after:      2 weeks
---
 lib/libc/stdio/fread.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/lib/libc/stdio/fread.c b/lib/libc/stdio/fread.c
index 11f8d13f0caf..cafe86fe7961 100644
--- a/lib/libc/stdio/fread.c
+++ b/lib/libc/stdio/fread.c
@@ -129,11 +129,13 @@ __fread(void * __restrict buf, size_t size, size_t count, 
FILE * __restrict fp)
        }
 
        while (resid > (r = fp->_r)) {
-               (void)memcpy((void *)p, (void *)fp->_p, (size_t)r);
-               fp->_p += r;
-               /* fp->_r = 0 ... done in __srefill */
-               p += r;
-               resid -= r;
+               if (r != 0) {
+                       (void)memcpy((void *)p, (void *)fp->_p, (size_t)r);
+                       fp->_p += r;
+                       /* fp->_r = 0 ... done in __srefill */
+                       p += r;
+                       resid -= r;
+               }
                if (__srefill(fp)) {
                        /* no more input: return partial result */
                        return ((total - resid) / size);

Reply via email to