nstr_parse_val() interprets argument "" as (empty) identifier, then
returns a pointer right beyond the end of the string.
The argument points into player->argbuf[]. If another argument
follows the conditional, it gets appended to the conditional. Else,
whatever's left there from previous commands gets appended. If the
argument is at the very end of player->argbuf[], we parse beyond the
buffer, until we run into a syntax error, or a zero byte.
Since player->argbuf[] is followed by a bunch of pointers, a syntax
error is almost certain. If we somehow manage to parse all the
pointers and player->lasttime, the runaway parse will end at
player->btused, because that's definitely zero when conditionals get
parsed.
np = &dummy;
/* left operand */
+ if (!*cond) {
+ pr("%s -- %scondition expected\n", str, i ? "another " : "");
+ return -1;
+ }
tail = nstr_parse_val(cond, &np->lft);
lft_caidx = nstr_match_ca(&np->lft, ca);
++tail;
/* right operand */
+ if (!*tail) {
+ pr("%s -- operand expected\n", cond);
+ return -1;
+ }
tail = nstr_parse_val(tail, &np->rgt);
rgt_caidx = nstr_match_ca(&np->rgt, ca);
}
/* funny character, interpret as identifier */
- tail = str+1;
+ tail = CANT_HAPPEN(!*str) ? str : str + 1;
val->val_type = NSC_NOTYPE;
val->val_cat = NSC_ID;
val->val_as.str.base = str;