Module Name:    src
Committed By:   rillig
Date:           Sun Jan  9 12:43:52 UTC 2022

Modified Files:
        src/usr.bin/make: for.c nonints.h parse.c

Log Message:
make: fix use-after-free in -dp mode (since yesterday)

In a .for loop that contains an unclosed .if directive,
Cond_restore_depth generates an error message.  If stack traces are
enabled using the option '-dp', the details of the .for loop are added
to the stack trace, but at that point, the ForLoop had already been
freed.  To reproduce:

make-2022.01.09.00.33.57 -r -f unit-tests/directive-for.mk -dp


To generate a diff of this commit:
cvs rdiff -u -r1.162 -r1.163 src/usr.bin/make/for.c
cvs rdiff -u -r1.235 -r1.236 src/usr.bin/make/nonints.h
cvs rdiff -u -r1.646 -r1.647 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/for.c
diff -u src/usr.bin/make/for.c:1.162 src/usr.bin/make/for.c:1.163
--- src/usr.bin/make/for.c:1.162	Sun Jan  9 00:33:57 2022
+++ src/usr.bin/make/for.c	Sun Jan  9 12:43:52 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: for.c,v 1.162 2022/01/09 00:33:57 rillig Exp $	*/
+/*	$NetBSD: for.c,v 1.163 2022/01/09 12:43:52 rillig Exp $	*/
 
 /*
  * Copyright (c) 1992, The Regents of the University of California.
@@ -58,7 +58,7 @@
 #include "make.h"
 
 /*	"@(#)for.c	8.1 (Berkeley) 6/6/93"	*/
-MAKE_RCSID("$NetBSD: for.c,v 1.162 2022/01/09 00:33:57 rillig Exp $");
+MAKE_RCSID("$NetBSD: for.c,v 1.163 2022/01/09 12:43:52 rillig Exp $");
 
 
 typedef struct ForLoop {
@@ -85,7 +85,7 @@ ForLoop_New(void)
 	return f;
 }
 
-static void
+void
 ForLoop_Free(ForLoop *f)
 {
 	while (f->vars.len > 0)
@@ -101,11 +101,16 @@ ForLoop_Free(ForLoop *f)
 char *
 ForLoop_Details(ForLoop *f)
 {
-	size_t i, n = f->vars.len;
-	const char **vars = f->vars.items;
-	const Substring *items = f->items.words + f->nextItem - n;
+	size_t i, n;
+	const char **vars;
+	const Substring *items;
 	Buffer buf;
 
+	n = f->vars.len;
+	vars = f->vars.items;
+	assert(f->nextItem >= n);
+	items = f->items.words + f->nextItem - n;
+
 	Buf_Init(&buf);
 	for (i = 0; i < n; i++) {
 		if (i > 0)
@@ -474,11 +479,8 @@ ForLoop_SubstBody(ForLoop *f, Buffer *bo
 bool
 For_NextIteration(ForLoop *f, Buffer *body)
 {
-	if (f->nextItem == f->items.len) {
-		/* No more iterations */
-		ForLoop_Free(f);
+	if (f->nextItem == f->items.len)
 		return false;
-	}
 
 	ForLoop_SubstBody(f, body);
 	DEBUG1(FOR, "For: loop body:\n%s", body->data);

Index: src/usr.bin/make/nonints.h
diff -u src/usr.bin/make/nonints.h:1.235 src/usr.bin/make/nonints.h:1.236
--- src/usr.bin/make/nonints.h:1.235	Sat Jan  8 23:52:26 2022
+++ src/usr.bin/make/nonints.h	Sun Jan  9 12:43:52 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: nonints.h,v 1.235 2022/01/08 23:52:26 rillig Exp $	*/
+/*	$NetBSD: nonints.h,v 1.236 2022/01/09 12:43:52 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -122,6 +122,7 @@ bool For_Accum(const char *, int *) MAKE
 void For_Run(int, int);
 bool For_NextIteration(struct ForLoop *, Buffer *);
 char *ForLoop_Details(struct ForLoop *);
+void ForLoop_Free(struct ForLoop *);
 
 /* job.c */
 void JobReapChild(pid_t, int, bool);

Index: src/usr.bin/make/parse.c
diff -u src/usr.bin/make/parse.c:1.646 src/usr.bin/make/parse.c:1.647
--- src/usr.bin/make/parse.c:1.646	Sun Jan  9 11:43:58 2022
+++ src/usr.bin/make/parse.c	Sun Jan  9 12:43:52 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: parse.c,v 1.646 2022/01/09 11:43:58 rillig Exp $	*/
+/*	$NetBSD: parse.c,v 1.647 2022/01/09 12:43:52 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -106,7 +106,7 @@
 #include "pathnames.h"
 
 /*	"@(#)parse.c	8.3 (Berkeley) 3/19/94"	*/
-MAKE_RCSID("$NetBSD: parse.c,v 1.646 2022/01/09 11:43:58 rillig Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.647 2022/01/09 12:43:52 rillig Exp $");
 
 /*
  * A file being read.
@@ -2253,6 +2253,8 @@ ParseEOF(void)
 
 	FStr_Done(&curFile->name);
 	Buf_Done(&curFile->buf);
+	if (curFile->forLoop != NULL)
+		ForLoop_Free(curFile->forLoop);
 	Vector_Pop(&includes);
 
 	if (includes.len == 0) {

Reply via email to