diff options
Diffstat (limited to 'unit-tests/varname-empty.mk')
-rwxr-xr-x | unit-tests/varname-empty.mk | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/unit-tests/varname-empty.mk b/unit-tests/varname-empty.mk index b4ce05c3017b..fd9aa05b6057 100755 --- a/unit-tests/varname-empty.mk +++ b/unit-tests/varname-empty.mk @@ -1,18 +1,54 @@ -# $NetBSD: varname-empty.mk,v 1.5 2020/08/22 21:22:24 rillig Exp $ +# $NetBSD: varname-empty.mk,v 1.7 2020/10/23 17:53:01 rillig Exp $ # # Tests for the special variable with the empty name. # -# The variable "" is not supposed to be assigned any value. -# This is because it is heavily used in the .for loop expansion, -# as well as to generate arbitrary strings, as in ${:Ufallback}. +# There is no variable named "" at all, and this fact is used a lot in +# variable expressions of the form ${:Ufallback}. These expressions are +# based on the variable named "" and use the :U modifier to assign a +# fallback value to the expression (but not to the variable). +# +# This form of expressions is used to implement value substitution in the +# .for loops. Another use case is in a variable assignment of the form +# ${:Uvarname}=value, which allows for characters in the variable name that +# would otherwise be interpreted by the parser, such as whitespace, ':', +# '=', '$', backslash. +# +# The only places where a variable is assigned a value are Var_Set and +# Var_Append, and these places protect the variable named "" from being +# defined. This is different from read-only variables, as that flag can +# only apply to variables that are defined. The variable named "" must +# never be defined though. +# +# See also: +# The special variables @F or ^D, in var-class-local.mk # Until 2020-08-22 it was possible to assign a value to the variable with -# the empty name, leading to all kinds of unexpected effects. +# the empty name, leading to all kinds of unexpected effects in .for loops +# and other places that assume that ${:Ufallback} expands to "fallback". +# The bug in Var_Set was that only expanded variables had been checked for +# the empty name, but not the direct assignments with an empty name. ?= default = assigned # undefined behavior until 2020-08-22 += appended := subst != echo 'shell-output' +.if ${:Ufallback} != "fallback" +. error +.endif + +${:U}= assigned indirectly +.if ${:Ufallback} != "fallback" +. error +.endif + +# Before 2020-08-22, the simple assignment operator '=' after an empty +# variable name had an off-by-one bug in Parse_DoVar. The code that was +# supposed to "skip to operator character" started its search _after_ the +# assignment operator, assuming that the variable name would be at least +# one character long. It then looked for the next occurrence of a '=', which +# could be several lines away or not occur at all. While looking for the +# '=', some whitespace was nulled out, leading to out-of-bounds write. += assigned # undefined behavior until 2020-08-22 # The .for loop expands the expression ${i} to ${:U1}, ${:U2} and so on. # This only works if the variable with the empty name is guaranteed to |