Module Name:    src
Committed By:   rillig
Date:           Sat Dec 19 22:10:18 UTC 2020

Modified Files:
        src/usr.bin/make: var.c
        src/usr.bin/make/unit-tests: directive-undef.exp directive-undef.mk

Log Message:
make(1): error out if .undef has not exactly 1 argument


To generate a diff of this commit:
cvs rdiff -u -r1.736 -r1.737 src/usr.bin/make/var.c
cvs rdiff -u -r1.3 -r1.4 src/usr.bin/make/unit-tests/directive-undef.exp
cvs rdiff -u -r1.7 -r1.8 src/usr.bin/make/unit-tests/directive-undef.mk

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/var.c
diff -u src/usr.bin/make/var.c:1.736 src/usr.bin/make/var.c:1.737
--- src/usr.bin/make/var.c:1.736	Sat Dec 19 20:47:24 2020
+++ src/usr.bin/make/var.c	Sat Dec 19 22:10:17 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: var.c,v 1.736 2020/12/19 20:47:24 rillig Exp $	*/
+/*	$NetBSD: var.c,v 1.737 2020/12/19 22:10:17 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -131,7 +131,7 @@
 #include "metachar.h"
 
 /*	"@(#)var.c	8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: var.c,v 1.736 2020/12/19 20:47:24 rillig Exp $");
+MAKE_RCSID("$NetBSD: var.c,v 1.737 2020/12/19 22:10:17 rillig Exp $");
 
 /* A string that may need to be freed after use. */
 typedef struct FStr {
@@ -531,18 +531,39 @@ Var_Delete(const char *name, GNode *ctxt
 	Var_DeleteVar(name, ctxt);
 }
 
+/*
+ * Undefine a single variable from the global scope.  The argument is
+ * expanded once.
+ */
 void
 Var_Undef(char *arg)
 {
+	/*
+	 * The argument must consist of exactly 1 word.  Accepting more than
+	 * 1 word would have required to split the argument into several
+	 * words, and such splitting is already done subtly different in many
+	 * other places of make.
+	 *
+	 * Using Str_Words to split the words, followed by Var_Subst to expand
+	 * each variable name once would make it impossible to undefine
+	 * variables whose names contain space characters or unbalanced
+	 * quotes or backslashes in arbitrary positions.
+	 *
+	 * Using Var_Subst on the whole argument and splitting the words
+	 * afterwards using Str_Words would make it impossible to undefine
+	 * variables whose names contain space characters.
+	 */
 	char *cp = arg;
 
 	for (; !ch_isspace(*cp) && *cp != '\0'; cp++)
 		continue;
+	if (cp == arg || *cp != '\0') {
+		Parse_Error(PARSE_FATAL,
+		    "The .undef directive requires exactly 1 argument");
+	}
 	*cp = '\0';
 
 	Var_Delete(arg, VAR_GLOBAL);
-	/* TODO: undefine all variables, not only the first */
-	/* TODO: use Str_Words, like everywhere else */
 }
 
 static Boolean

Index: src/usr.bin/make/unit-tests/directive-undef.exp
diff -u src/usr.bin/make/unit-tests/directive-undef.exp:1.3 src/usr.bin/make/unit-tests/directive-undef.exp:1.4
--- src/usr.bin/make/unit-tests/directive-undef.exp:1.3	Sun Dec 13 01:07:54 2020
+++ src/usr.bin/make/unit-tests/directive-undef.exp	Sat Dec 19 22:10:18 2020
@@ -1 +1,5 @@
-exit status 0
+make: "directive-undef.mk" line 14: The .undef directive requires exactly 1 argument
+make: "directive-undef.mk" line 24: The .undef directive requires exactly 1 argument
+make: Fatal errors encountered -- cannot continue
+make: stopped in unit-tests
+exit status 1

Index: src/usr.bin/make/unit-tests/directive-undef.mk
diff -u src/usr.bin/make/unit-tests/directive-undef.mk:1.7 src/usr.bin/make/unit-tests/directive-undef.mk:1.8
--- src/usr.bin/make/unit-tests/directive-undef.mk:1.7	Sat Dec 19 20:35:39 2020
+++ src/usr.bin/make/unit-tests/directive-undef.mk	Sat Dec 19 22:10:18 2020
@@ -1,4 +1,4 @@
-# $NetBSD: directive-undef.mk,v 1.7 2020/12/19 20:35:39 rillig Exp $
+# $NetBSD: directive-undef.mk,v 1.8 2020/12/19 22:10:18 rillig Exp $
 #
 # Tests for the .undef directive.
 #
@@ -16,9 +16,39 @@
 .  warning $1$2$3
 .endif
 
-# Without any arguments, .undef tries to delete the variable with the empty
-# name, which never exists; see varname-empty.mk.
-.undef				# oops: missing argument
+
+# Without any arguments, until var.c 1.736 from 2020-12-19, .undef tried
+# to delete the variable with the empty name, which never exists; see
+# varname-empty.mk.  Since var.c 1.737 from 2020-12-19, .undef complains
+# about a missing argument.
+.undef
+
+
+# Trying to delete the variable with the empty name is ok, it just won't
+# ever do anything since that variable is never defined.
+.undef ${:U}
+
+
+# The argument of .undef is a single word, delimited by whitespace, without
+# any possibility of escaping or having variable expressions containing
+# spaces.  This word is then expanded exactly once, and the expanded string
+# is the single variable name.  This allows variable names to contain spaces,
+# as well as unbalanced single and double quotes.
+1=		1
+2=		2
+3=		3
+${:U1 2 3}=	one two three
+VARNAMES=	1 2 3
+.undef ${VARNAMES}		# undefines the variable "1 2 3"
+.if defined(${:U1 2 3})
+.  error
+.endif
+.if ${1}${2}${3} != "123"	# these are still defined
+.  error
+.endif
+.undef 1
+.undef 2
+.undef 3
 
 
 # It must be possible to undefine variables whose name includes spaces.

Reply via email to