]> git.pond.sub.org Git - empserver/commitdiff
Fix read beyond end of conditional argument on missing operand
authorMarkus Armbruster <armbru@pond.sub.org>
Sun, 12 May 2013 09:55:42 +0000 (11:55 +0200)
committerMarkus Armbruster <armbru@pond.sub.org>
Sun, 12 May 2013 16:53:29 +0000 (18:53 +0200)
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.

src/lib/subs/nstr.c

index d94567b61c6764b1e91b33cfcd100b113d08b48d..7ffb5712f3b87d5021b73faa0b3ffae374b03a20 100644 (file)
@@ -77,6 +77,10 @@ nstr_comp(struct nscstr *np, int len, int type, char *str)
            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);
 
@@ -92,6 +96,10 @@ nstr_comp(struct nscstr *np, int len, int type, char *str)
        ++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);
 
@@ -313,7 +321,7 @@ nstr_parse_val(char *str, struct valstr *val)
     }
 
     /* 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;