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).
This commit is contained in:
parent
e6cc2fd8f9
commit
6f201b686b
|
@ -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 @@ fread(void *buf, size_t size, size_t count, FILE *fp)
|
|||
_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);
|
||||
|
|
Loading…
Reference in New Issue