1 # $NetBSD: varname-empty.mk,v 1.7 2020/10/23 17:53:01 rillig Exp $
3 # Tests for the special variable with the empty name.
5 # There is no variable named "" at all, and this fact is used a lot in
6 # variable expressions of the form ${:Ufallback}. These expressions are
7 # based on the variable named "" and use the :U modifier to assign a
8 # fallback value to the expression (but not to the variable).
10 # This form of expressions is used to implement value substitution in the
11 # .for loops. Another use case is in a variable assignment of the form
12 # ${:Uvarname}=value, which allows for characters in the variable name that
13 # would otherwise be interpreted by the parser, such as whitespace, ':',
14 # '=', '$', backslash.
16 # The only places where a variable is assigned a value are Var_Set and
17 # Var_Append, and these places protect the variable named "" from being
18 # defined. This is different from read-only variables, as that flag can
19 # only apply to variables that are defined. The variable named "" must
20 # never be defined though.
23 # The special variables @F or ^D, in var-class-local.mk
25 # Until 2020-08-22 it was possible to assign a value to the variable with
26 # the empty name, leading to all kinds of unexpected effects in .for loops
27 # and other places that assume that ${:Ufallback} expands to "fallback".
28 # The bug in Var_Set was that only expanded variables had been checked for
29 # the empty name, but not the direct assignments with an empty name.
31 = assigned # undefined behavior until 2020-08-22
34 != echo 'shell-output'
35 .if ${:Ufallback} != "fallback"
39 ${:U}= assigned indirectly
40 .if ${:Ufallback} != "fallback"
44 # Before 2020-08-22, the simple assignment operator '=' after an empty
45 # variable name had an off-by-one bug in Parse_DoVar. The code that was
46 # supposed to "skip to operator character" started its search _after_ the
47 # assignment operator, assuming that the variable name would be at least
48 # one character long. It then looked for the next occurrence of a '=', which
49 # could be several lines away or not occur at all. While looking for the
50 # '=', some whitespace was nulled out, leading to out-of-bounds write.
51 = assigned # undefined behavior until 2020-08-22
53 # The .for loop expands the expression ${i} to ${:U1}, ${:U2} and so on.
54 # This only works if the variable with the empty name is guaranteed to
61 @echo out: ${:Ufallback}