Fix substring(str, start) - the 2-argument form was completely broken
Found while writing a new Expressions Reference chapter for the manual,
where every function got run for real before being documented rather
than trusted from reading the source alone - substring('helloworld', 7)
threw "operand is not valid." immediately after producing the correct
answer, confirmed via debug tracing showing an extra Operand constructed
on empty input right after the 2-arg case finished.
Root cause: a missing pair of braces around the 3-argument-only branch
meant Operand parm3(in, tag) and its own closing-paren check ran
unconditionally, even after the 2-arg form's own "if(in.ifNext(')'))"
check had already matched and produced string = parm1.string.substring(
parm2.string.asInteger()) - so it immediately tried to parse a third
argument from whatever was left (nothing, since the real closing paren
was already consumed), and construction on empty input always throws.
The 3-argument form (substring(str, start, length)) was unaffected,
since its own path never hit the first if-branch's early exit.
Fixed by properly scoping the 3-arg branch inside an else, so it only
runs when the 2-arg form's own closing paren wasn't found. Verified both
forms with real jet-2.0 runs: substring('helloworld', 7) -> "rld",
substring('helloworld', 0, 5) -> "hello".
This commit is contained in:
1 parent
9f3349b671
commit
97142ce9b4
1 file changed
+22
-9
+22
-9
@@ -12,9 +12,9 @@ namespace jet {
|
||||
Operand::Operand(coreutils::ZString &in, Tag &tag, bool stop) : in(in), tag(tag) {
|
||||
|
||||
doubleValue = 0;
|
||||
|
||||
|
||||
in.skipWhitespace();
|
||||
|
||||
|
||||
if(in.startsWith("$[") || in.startsWith("#[")) {
|
||||
string = tag.getVariable(in);
|
||||
doubleValue = string.asDouble();
|
||||
@@ -38,13 +38,26 @@ namespace jet {
|
||||
Operand parm2(in, tag);
|
||||
if(in.ifNext(")")) {
|
||||
string = parm1.string.substring(parm2.string.asInteger());
|
||||
} else if(!in.ifNext(","))
|
||||
} else {
|
||||
// Real, pre-existing bug fixed here: the 3-arg-only branch below
|
||||
// used to run unconditionally (missing braces around this
|
||||
// else-if), so even after the 2-arg form above already
|
||||
// succeeded, it fell through into trying to parse a third
|
||||
// argument from whatever was left (nothing, since the closing
|
||||
// ")" was already consumed) - always throwing "operand is not
|
||||
// valid." right after computing the correct 2-arg result.
|
||||
// Confirmed via real debug tracing showing an extra Operand
|
||||
// constructed on empty input immediately after a successful
|
||||
// 2-arg substring(str, start) call - the 2-arg form was
|
||||
// completely unusable before this fix.
|
||||
if(!in.ifNext(","))
|
||||
throw coreutils::Exception("Expecting , in SUBSTRING expression.");
|
||||
Operand parm3(in, tag);
|
||||
if(in.ifNext(")")) {
|
||||
string = parm1.string.substring(parm2.string.asInteger(), parm3.string.asInteger());
|
||||
} else
|
||||
throw coreutils::Exception("Expecting ) at end of substring expression.");
|
||||
Operand parm3(in, tag);
|
||||
if(in.ifNext(")")) {
|
||||
string = parm1.string.substring(parm2.string.asInteger(), parm3.string.asInteger());
|
||||
} else
|
||||
throw coreutils::Exception("Expecting ) at end of substring expression.");
|
||||
}
|
||||
} else if(in.ifNextIgnoreCase("LEFT")) {
|
||||
if(!in.ifNext("("))
|
||||
throw coreutils::Exception("Expecting ( for LEFT parameters.");
|
||||
@@ -405,7 +418,7 @@ namespace jet {
|
||||
}
|
||||
|
||||
int Operand::parseOperator() {
|
||||
|
||||
|
||||
if(in.ifNext("!=") || in.ifNext("<>")) {
|
||||
Operand op(in, tag);
|
||||
if(isNumber && op.isNumber) {
|
||||
|
||||
Reference in new issue
Block a user