varname-empty.mk revision 1.9
11.9Srillig# $NetBSD: varname-empty.mk,v 1.9 2021/04/04 10:13:09 rillig Exp $ 21.1Srillig# 31.1Srillig# Tests for the special variable with the empty name. 41.1Srillig# 51.6Srillig# There is no variable named "" at all, and this fact is used a lot in 61.6Srillig# variable expressions of the form ${:Ufallback}. These expressions are 71.6Srillig# based on the variable named "" and use the :U modifier to assign a 81.6Srillig# fallback value to the expression (but not to the variable). 91.6Srillig# 101.6Srillig# This form of expressions is used to implement value substitution in the 111.6Srillig# .for loops. Another use case is in a variable assignment of the form 121.6Srillig# ${:Uvarname}=value, which allows for characters in the variable name that 131.6Srillig# would otherwise be interpreted by the parser, such as whitespace, ':', 141.6Srillig# '=', '$', backslash. 151.6Srillig# 161.6Srillig# The only places where a variable is assigned a value are Var_Set and 171.6Srillig# Var_Append, and these places protect the variable named "" from being 181.6Srillig# defined. This is different from read-only variables, as that flag can 191.7Srillig# only apply to variables that are defined. The variable named "" must 201.7Srillig# never be defined though. 211.6Srillig# 221.7Srillig# See also: 231.7Srillig# The special variables @F or ^D, in var-class-local.mk 241.1Srillig 251.2Srillig# Until 2020-08-22 it was possible to assign a value to the variable with 261.7Srillig# the empty name, leading to all kinds of unexpected effects in .for loops 271.7Srillig# and other places that assume that ${:Ufallback} expands to "fallback". 281.7Srillig# The bug in Var_Set was that only expanded variables had been checked for 291.7Srillig# the empty name, but not the direct assignments with an empty name. 301.3Srillig?= default 311.4Srillig= assigned # undefined behavior until 2020-08-22 321.3Srillig+= appended 331.3Srillig:= subst 341.5Srillig!= echo 'shell-output' 351.7Srillig.if ${:Ufallback} != "fallback" 361.7Srillig. error 371.7Srillig.endif 381.7Srillig 391.7Srillig${:U}= assigned indirectly 401.7Srillig.if ${:Ufallback} != "fallback" 411.7Srillig. error 421.7Srillig.endif 431.7Srillig 441.8Srillig${:U}+= appended indirectly 451.8Srillig.if ${:Ufallback} != "fallback" 461.8Srillig. error 471.8Srillig.endif 481.8Srillig 491.8Srillig.MAKEFLAGS: -d0 501.8Srillig 511.7Srillig# Before 2020-08-22, the simple assignment operator '=' after an empty 521.9Srillig# variable name had an off-by-one bug in Parse_Var. The code that was 531.7Srillig# supposed to "skip to operator character" started its search _after_ the 541.7Srillig# assignment operator, assuming that the variable name would be at least 551.7Srillig# one character long. It then looked for the next occurrence of a '=', which 561.7Srillig# could be several lines away or not occur at all. While looking for the 571.7Srillig# '=', some whitespace was nulled out, leading to out-of-bounds write. 581.7Srillig= assigned # undefined behavior until 2020-08-22 591.1Srillig 601.1Srillig# The .for loop expands the expression ${i} to ${:U1}, ${:U2} and so on. 611.1Srillig# This only works if the variable with the empty name is guaranteed to 621.1Srillig# be undefined. 631.1Srillig.for i in 1 2 3 641.1SrilligNUMBERS+= ${i} 651.1Srillig.endfor 661.1Srillig 671.1Srilligall: 681.5Srillig @echo out: ${:Ufallback} 691.5Srillig @echo out: ${NUMBERS} 70