Module Name:    src
Committed By:   rillig
Date:           Tue Dec 22 06:48:33 UTC 2020

Modified Files:
        src/usr.bin/make: parse.c

Log Message:
make(1): prevent undefined behavior in loadfile_mmap

Reading a file without a trailing newline had resulted in an
out-of-bounds write, in the common case where the file is loaded via
mmap.


To generate a diff of this commit:
cvs rdiff -u -r1.509 -r1.510 src/usr.bin/make/parse.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/make/parse.c
diff -u src/usr.bin/make/parse.c:1.509 src/usr.bin/make/parse.c:1.510
--- src/usr.bin/make/parse.c:1.509	Mon Dec 21 02:09:34 2020
+++ src/usr.bin/make/parse.c	Tue Dec 22 06:48:33 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: parse.c,v 1.509 2020/12/21 02:09:34 rillig Exp $	*/
+/*	$NetBSD: parse.c,v 1.510 2020/12/22 06:48:33 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -117,7 +117,7 @@
 #include "pathnames.h"
 
 /*	"@(#)parse.c	8.3 (Berkeley) 3/19/94"	*/
-MAKE_RCSID("$NetBSD: parse.c,v 1.509 2020/12/21 02:09:34 rillig Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.510 2020/12/22 06:48:33 rillig Exp $");
 
 /* types and constants */
 
@@ -2687,10 +2687,22 @@ ParseRawLine(IFile *curFile, char **out_
 		if (ch == '\\') {
 			if (firstBackslash == NULL)
 				firstBackslash = p;
+			/*
+			 * FIXME: In opt-file.mk, this command succeeds:
+			 *	printf '%s' 'V=v\' | make -r -f -
+			 * Using an intermediate file fails though:
+			 *	printf '%s' 'V=v\' > backslash
+			 *	make -r -f backslash
+			 *
+			 * In loadedfile_mmap, the trailing newline is not
+			 * added in every case, only if the file ends at a
+			 * page boundary.
+			 */
 			if (p[1] == '\n')
 				curFile->lineno++;
 			p += 2;
 			line_end = p;
+			assert(p <= curFile->buf_end);
 			continue;
 		}
 
@@ -2831,6 +2843,12 @@ ParseGetLine(GetLineMode mode)
 		}
 
 		/* We now have a line of data */
+		/*
+		 * FIXME: undefined behavior since line_end points right
+		 * after the allocated buffer. This becomes apparent when
+		 * using a strict malloc implementation that adds canaries
+		 * before and after the allocated space.
+		 */
 		*line_end = '\0';
 
 		if (mode == GLM_FOR_BODY)

Reply via email to