Wed Jul 29 20:33:38 2020 UTC ()
make(1): fix segfault when evaluating ${::=value}

The bug had been in the handling of the SysV modifier for many years, but
it had not been triggered since the "parsing position for the next
modifier" had been initialized to a non-NULL pointer.

In var.v r1.350, this pointer had been initialized to NULL instead since
every ApplyModifier function must set it in every case where it returns
anything except "default_case".

There might have been a slight chance of tricking make to output a wrong
error message, but nothing worse.


(rillig)
diff -r1.354 -r1.355 src/usr.bin/make/var.c
diff -r1.8 -r1.9 src/usr.bin/make/unit-tests/moderrs.exp
diff -r1.7 -r1.8 src/usr.bin/make/unit-tests/moderrs.mk

cvs diff -r1.354 -r1.355 src/usr.bin/make/var.c (expand / switch to context diff)
--- src/usr.bin/make/var.c 2020/07/29 19:48:33 1.354
+++ src/usr.bin/make/var.c 2020/07/29 20:33:38 1.355
@@ -1,4 +1,4 @@
-/*	$NetBSD: var.c,v 1.354 2020/07/29 19:48:33 rillig Exp $	*/
+/*	$NetBSD: var.c,v 1.355 2020/07/29 20:33:38 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
  */
 
 #ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: var.c,v 1.354 2020/07/29 19:48:33 rillig Exp $";
+static char rcsid[] = "$NetBSD: var.c,v 1.355 2020/07/29 20:33:38 rillig Exp $";
 #else
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 static char sccsid[] = "@(#)var.c	8.3 (Berkeley) 3/19/94";
 #else
-__RCSID("$NetBSD: var.c,v 1.354 2020/07/29 19:48:33 rillig Exp $");
+__RCSID("$NetBSD: var.c,v 1.355 2020/07/29 20:33:38 rillig Exp $");
 #endif
 #endif /* not lint */
 #endif
@@ -2575,7 +2575,7 @@
 static Boolean
 ApplyModifier_To(const char *mod, ApplyModifiersState *st)
 {
-    st->next = mod + 1;	/* make sure it is set */
+    st->next = mod + 1;		/* make sure it is set */
     if (mod[1] == st->endc || mod[1] == ':')
 	return FALSE;		/* Found ":t<endc>" or ":t:". */
 
@@ -2818,8 +2818,10 @@
 
     GNode *v_ctxt;		/* context where v belongs */
 
-    if (st->v->name[0] == 0)
+    if (st->v->name[0] == 0) {
+	st->next = mod + 1;
 	return 'b';
+    }
 
     v_ctxt = st->ctxt;
     char *sv_name = NULL;
@@ -3117,6 +3119,7 @@
 	}
 	st.newVal = var_Error;
 	char modifier = *p;
+	st.next = NULL;	/* fail fast if an ApplyModifier forgets to set this */
 	switch (modifier) {
 	case ':':
 	    {

cvs diff -r1.8 -r1.9 src/usr.bin/make/unit-tests/moderrs.exp (expand / switch to context diff)
--- src/usr.bin/make/unit-tests/moderrs.exp 2020/07/29 19:48:33 1.8
+++ src/usr.bin/make/unit-tests/moderrs.exp 2020/07/29 20:33:38 1.9
@@ -117,6 +117,8 @@
 mod-assign-parse:
 make: Unknown modifier ':'
 
+make: Bad modifier `:' for 
+value}
 make: Unclosed substitution for ASSIGN (} missing)
 
 mod-remember-parse:

cvs diff -r1.7 -r1.8 src/usr.bin/make/unit-tests/moderrs.mk (expand / switch to context diff)
--- src/usr.bin/make/unit-tests/moderrs.mk 2020/07/29 19:48:33 1.7
+++ src/usr.bin/make/unit-tests/moderrs.mk 2020/07/29 20:33:38 1.8
@@ -1,4 +1,4 @@
-# $Id: moderrs.mk,v 1.7 2020/07/29 19:48:33 rillig Exp $
+# $Id: moderrs.mk,v 1.8 2020/07/29 20:33:38 rillig Exp $
 #
 # various modifier error tests
 
@@ -151,9 +151,7 @@
 mod-assign-parse:
 	@echo $@:
 	@echo ${ASSIGN::x}	# 'x' is an unknown assignment operator
-# disabled for now; segfaults on NetBSD-8.0-x86_64 in Var_Parse line 3636:
-# *lengthPtr = tstr - str + (*tstr ? 1 : 0);
-#	@echo ${::=value}	# trying to set the empty variable
+	@echo ${::=value}	# trying to set the empty variable
 	@echo ${ASSIGN::=value	# missing closing brace
 
 mod-remember-parse: