Skip to content

Commit da1620b

Browse files
committed
DOC: configuration: explain quotes and spaces in conditional blocks
Conditional blocks inherit the same tokenizer and argument parser as the rest of the configuration, but are also silently concatenated around groups of spaces and tabs. This can lead to subtle failures for configs containing spaces around commas and parenthesis, where a string comparison might silently fail for example. Let's better document this particular case. Thanks to Valentine for analysing and reporting the problem. This can be backported to 2.4.
1 parent 962d5e0 commit da1620b

File tree

1 file changed

+48
-0
lines changed

1 file changed

+48
-0
lines changed

doc/configuration.txt

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,54 @@ expression made of any combination of:
10561056
- expressions combined with a logical OR ('||'), which will be evaluated
10571057
from right to left until one returns true
10581058

1059+
The same line tokenizer and argument parser are used as for the rest of the
1060+
configuration language. Words are split around consecutive series of one or
1061+
more unquoted spaces or tabs, and are reassembled together using a single space
1062+
to delimit them before evaluation, in order to save the user from having to
1063+
quote the entire line. But this also means that spaces surrounding commas or
1064+
parenthesis are definitely part of the value, which is not always expected.
1065+
For example, the expression below:
1066+
1067+
.if defined( HAPROXY_MWORKER )
1068+
1069+
will test for the existence of variable " HAPROXY_MWORKER " (with spaces),
1070+
and this one:
1071+
1072+
.if streq("$ENABLE_SSL", 1)
1073+
1074+
will compare the environment variable "ENABLE_SSL" to the value " 1" (with a
1075+
single leading space). The reason is the line is first split into words like
1076+
this:
1077+
1078+
.if streq("$ENABLE_SSL", 1)
1079+
|---|--------------------| |--|
1080+
1 2 3
1081+
1082+
then the weak quoting is applied and environment variable "$ENABLE_SSL" is
1083+
resolved (let's say for example that ENABLE_SSL=0), and finally the words are
1084+
reassembled into a single string by placing a single space between the words:
1085+
1086+
.if streq(0, 1)
1087+
|---|-------|--|
1088+
1 2 3
1089+
1090+
and only then it is parsed as a single expression. The space that was inserted
1091+
between the comma and "1" is still part of the argument value, making this
1092+
argument " 1":
1093+
1094+
.if streq(0, 1)
1095+
|---|-----|-|--|
1096+
\ \ \ \_ argument2: " 1"
1097+
\ \ \___ argument1: "0"
1098+
\ \_______ function: "streq"
1099+
\___________ directive: ".if"
1100+
1101+
It's visible here that even if ENABLE_SSL had been equal to "1", it wouldn't
1102+
have matched " 1" since the string would differ by one space.
1103+
1104+
Note: as explained in section "2.2. Quoting and escaping", a good rule of thumb
1105+
is to never insert unneeded spaces inside expressions.
1106+
10591107
Note that like in other languages, the AND operator has precedence over the OR
10601108
operator, so that "A && B || C && D" evalues as "(A && B) || (C && D)".
10611109

0 commit comments

Comments
 (0)