Module Name:    src
Committed By:   rillig
Date:           Fri Sep 25 05:56:59 UTC 2020

Modified Files:
        src/distrib/sets/lists/tests: mi
        src/usr.bin/make/unit-tests: Makefile
Added Files:
        src/usr.bin/make/unit-tests: varparse-undef-partial.exp
            varparse-undef-partial.mk

Log Message:
make(1): add test for partial expansion of undefined variables


To generate a diff of this commit:
cvs rdiff -u -r1.927 -r1.928 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.148 -r1.149 src/usr.bin/make/unit-tests/Makefile
cvs rdiff -u -r0 -r1.1 src/usr.bin/make/unit-tests/varparse-undef-partial.exp \
    src/usr.bin/make/unit-tests/varparse-undef-partial.mk

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

Modified files:

Index: src/distrib/sets/lists/tests/mi
diff -u src/distrib/sets/lists/tests/mi:1.927 src/distrib/sets/lists/tests/mi:1.928
--- src/distrib/sets/lists/tests/mi:1.927	Wed Sep 23 03:33:54 2020
+++ src/distrib/sets/lists/tests/mi	Fri Sep 25 05:56:59 2020
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.927 2020/09/23 03:33:54 rillig Exp $
+# $NetBSD: mi,v 1.928 2020/09/25 05:56:59 rillig Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -5172,6 +5172,8 @@
 ./usr/tests/usr.bin/make/unit-tests/varname.mk					tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/make/unit-tests/varparse-dynamic.exp			tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/make/unit-tests/varparse-dynamic.mk				tests-usr.bin-tests	compattestfile,atf
+./usr/tests/usr.bin/make/unit-tests/varparse-undef-partial.exp			tests-usr.bin-tests	compattestfile,atf
+./usr/tests/usr.bin/make/unit-tests/varparse-undef-partial.mk			tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/make/unit-tests/varquote.exp				tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/make/unit-tests/varquote.mk					tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/make/unit-tests/varshell.exp				tests-usr.bin-tests	compattestfile,atf

Index: src/usr.bin/make/unit-tests/Makefile
diff -u src/usr.bin/make/unit-tests/Makefile:1.148 src/usr.bin/make/unit-tests/Makefile:1.149
--- src/usr.bin/make/unit-tests/Makefile:1.148	Wed Sep 23 07:54:08 2020
+++ src/usr.bin/make/unit-tests/Makefile	Fri Sep 25 05:56:59 2020
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.148 2020/09/23 07:54:08 rillig Exp $
+# $NetBSD: Makefile,v 1.149 2020/09/25 05:56:59 rillig Exp $
 #
 # Unit tests for make(1)
 #
@@ -347,6 +347,7 @@ TESTS+=		varname-makeflags
 TESTS+=		varname-pwd
 TESTS+=		varname-vpath
 TESTS+=		varparse-dynamic
+TESTS+=		varparse-undef-partial
 TESTS+=		varquote
 TESTS+=		varshell
 

Added files:

Index: src/usr.bin/make/unit-tests/varparse-undef-partial.exp
diff -u /dev/null src/usr.bin/make/unit-tests/varparse-undef-partial.exp:1.1
--- /dev/null	Fri Sep 25 05:56:59 2020
+++ src/usr.bin/make/unit-tests/varparse-undef-partial.exp	Fri Sep 25 05:56:59 2020
@@ -0,0 +1 @@
+exit status 0
Index: src/usr.bin/make/unit-tests/varparse-undef-partial.mk
diff -u /dev/null src/usr.bin/make/unit-tests/varparse-undef-partial.mk:1.1
--- /dev/null	Fri Sep 25 05:56:59 2020
+++ src/usr.bin/make/unit-tests/varparse-undef-partial.mk	Fri Sep 25 05:56:59 2020
@@ -0,0 +1,64 @@
+# $NetBSD: varparse-undef-partial.mk,v 1.1 2020/09/25 05:56:59 rillig Exp $
+
+# When an undefined variable is expanded in a ':=' assignment, only the
+# initial '$' of the variable expression is skipped by the parser, while
+# the remaining expression is evaluated.  In edge cases this can lead to
+# a completely different interpretation of the partially expanded text.
+
+LIST=	${DEF} ${UNDEF} ${VAR.${PARAM}} end
+DEF=	defined
+PARAM=	:Q
+
+# The expression ${VAR.{PARAM}} refers to the variable named "VAR.:Q",
+# with the ":Q" being part of the name.  This variable is not defined,
+# therefore the initial '$' of that whole expression is skipped by the
+# parser (see Var_Subst, the Buf_AddByte in the else branch) and the rest
+# of the expression is expanded as usual.
+#
+# The resulting variable expression is ${VAR.:Q}, which means that the
+# interpretation of the ":Q" has changed from being part of the variable
+# name to being a variable modifier.  This is a classical code injection.
+EVAL:=	${LIST}
+.if ${EVAL} != "defined   end"
+.  error ${EVAL}
+.endif
+
+# Define the possible outcomes, to see which of them gets expanded.
+VAR.=		var-dot without parameter
+${:UVAR.\:Q}=	var-dot with parameter :Q
+
+# At this point, the variable "VAR." is defined, therefore the expression
+# ${VAR.:Q} is expanded as usual.
+.if ${EVAL} != "defined  var-dot\\ without\\ parameter end"
+.  error ${EVAL}
+.endif
+
+# In contrast to the previous line, evaluating the original LIST again now
+# produces a different result since the ":Q" has already been inserted
+# literally into the expression.  The variable named "VAR.:Q" is defined,
+# therefore it is resolved as usual.  The ":Q" is interpreted as part of the
+# variable name, as would be expected from reading the variable expression.
+EVAL:=	${LIST}
+.if ${EVAL} != "defined  var-dot with parameter :Q end"
+.  error ${EVAL}
+.endif
+
+# It's difficult to decide what the best behavior is in this situation.
+# Should the whole expression be skipped for now, or should the inner
+# subexpressions be expanded already?
+#
+# Example 1:
+# CFLAGS:=	${CFLAGS:N-W*} ${COPTS.${COMPILER}}
+#
+# The variable COMPILER typically contains an identifier and the variable is
+# not modified later.  In this practical case, it does not matter whether the
+# expression is expanded early, or whether the whole ${COPTS.${COMPILER}} is
+# expanded as soon as the variable COPTS.${COMPILER} becomes defined.  The
+# expression ${COMPILER} would be expanded several times, but in this simple
+# scenario there would not be any side effects.
+#
+# TODO: Add a practical example where early/lazy expansion actually makes a
+# difference.
+
+all:
+	@:

Reply via email to