⬢ DragonFlyBSD Kernel Audit
DF-5706 / fix.diff
← back to finding ↓ download raw
--- a/sys/libkern/memcchr.c
+++ b/sys/libkern/memcchr.c
@@ -74,33 +74,33 @@
 	/* Don't perform memory I/O when passing a zero-length buffer. */
 	if (n == 0)
 		return (NULL);
 
-	/*
-	 * First determine whether there is a character unequal to `c'
-	 * in the first word.  As this word may contain bytes before
-	 * `begin', we may execute this loop spuriously.
-	 */
-	lp = (const unsigned long *)((uintptr_t)begin & ~LONGPTR_MASK);
 	end = (const unsigned char *)begin + n;
-	if (*lp++ != word)
-		for (p = begin; p < (const unsigned char *)lp;)
-			TESTBYTE;
 
-	/* Now compare the data one word at a time. */
-	for (; (const unsigned char *)lp < end; lp++) {
+	/* Compare bytewise until word aligned: no loads below begin. */
+	for (p = begin; p < end && ((uintptr_t)p & LONGPTR_MASK);)
+		TESTBYTE;
+
+	/* Compare one word at a time while the whole word is in range. */
+	for (lp = (const unsigned long *)p;
+	    (const unsigned char *)(lp + 1) <= end; lp++) {
 		if (*lp != word) {
 			p = (const unsigned char *)lp;
 			TESTBYTE;
 			TESTBYTE;
 			TESTBYTE;
 #if LONG_BIT >= 64
 			TESTBYTE;
 			TESTBYTE;
 			TESTBYTE;
 			TESTBYTE;
 #endif
 			goto done;
 		}
 	}
 
+	/* Trailing bytes: no loads past end. */
+	for (p = (const unsigned char *)lp; p < end;)
+		TESTBYTE;
+
 	return (NULL);