Fix $[...] variable parsing to consume the entire bracket contents
renderVariableName() built the variable name by whitelisting an
identifier charset (letters/digits/._-) via getTokenInclude(), then
threw "invalid variable name." on the first character outside that set
- including a plain space. Real-world CGI form field names aren't
restricted to identifier characters (an HTML <input name="first name">
is completely valid), so $[:first name] failed outright instead of
looking up the field as sent.
Rewrote to exclude only the genuinely structural characters (']', ';',
and the start of a nested $[.../#[...substitution) via getTokenExclude,
so everything else between the brackets - spaces included - is consumed
as part of the name before any lookup happens, rather than stopping
early and erroring. This also let the separate ':' handling branch be
dropped entirely: since ':' is no longer excluded, it now flows through
the same sweep naturally (needed for both the CGI sigil name itself and
the "$[:name:2]" explicit-index suffix).
Verified live: $[:first name] against a real multipart CGI body with a
field literally named "first name" now resolves correctly (previously
threw before ever reaching the lookup). A stray, non-nested '$' or '#'
in a name is kept as literal text rather than erroring. Re-verified
existing sigils are unaffected - plain $[x], $[!x] (forced-global), and
tests/posttest.sh's ^session/:.name3 lookups all still resolve exactly
as before.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
aaed4cb4da
commit
6ac33601a0
1 file changed
+23
-8
@@ -472,20 +472,35 @@ namespace jet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Tag::renderVariableName(coreutils::ZString &variable, coreutils::MString &name, coreutils::MString &modifier) {
|
void Tag::renderVariableName(coreutils::ZString &variable, coreutils::MString &name, coreutils::MString &modifier) {
|
||||||
|
// Consumes everything between '[' (already eaten by the caller) and the
|
||||||
|
// matching ']' as the variable name, stopping early only for the
|
||||||
|
// genuinely structural bits: the ';' modifier separator and a nested
|
||||||
|
// $[...]/#[...] substitution. Real-world CGI field names are not
|
||||||
|
// restricted to identifier characters (an HTML form field can be named
|
||||||
|
// "first name", "cost$", etc.) - excluding only the structural
|
||||||
|
// characters (rather than whitelisting an identifier charset and
|
||||||
|
// throwing on anything else) means the full bracket contents are
|
||||||
|
// always consumed before a lookup happens, matching how a caller
|
||||||
|
// actually writing $[:field name] expects it to behave.
|
||||||
while(!variable.ifNext("]")) {
|
while(!variable.ifNext("]")) {
|
||||||
name << variable.getTokenInclude("?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-");
|
name << variable.getTokenExclude("];$#");
|
||||||
if(variable.ifNext(";")) {
|
if(variable.ifNext(";")) {
|
||||||
renderVariableName(variable, modifier, modifier);
|
renderVariableName(variable, modifier, modifier);
|
||||||
return;
|
return;
|
||||||
} else if(variable.ifNext(":")) {
|
|
||||||
name << ":";
|
|
||||||
} else if(variable.startsWith("$[") || variable.startsWith("#[")) {
|
} else if(variable.startsWith("$[") || variable.startsWith("#[")) {
|
||||||
name << getVariable(variable);
|
name << getVariable(variable);
|
||||||
} else if(variable.ifNext("]"))
|
} else if(variable.ifNext("]")) {
|
||||||
return;
|
return;
|
||||||
else if(!variable.ifNextInclude("?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-"))
|
} else if(variable.eod()) {
|
||||||
throw coreutils::Exception("invalid variable name.");
|
throw coreutils::Exception("unterminated variable reference - missing ']'.");
|
||||||
}
|
} else {
|
||||||
|
// A literal '$' or '#' that isn't the start of a nested
|
||||||
|
// substitution (getTokenExclude stopped on it defensively, since
|
||||||
|
// it can't look ahead past a single character) - keep it as
|
||||||
|
// ordinary name text and continue.
|
||||||
|
name << variable.nextChar();
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user