Mercurial > hg-old > index.cgi
diff lwlib/lw_expr.c @ 431:d7d7e4dca3e7
Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
author | lost@l-w.ca |
---|---|
date | Sun, 24 Oct 2010 20:05:15 -0600 |
parents | 652eee8f0c82 |
children | 22bbb716dea6 |
line wrap: on
line diff
--- a/lwlib/lw_expr.c Sun Oct 24 19:06:00 2010 -0600 +++ b/lwlib/lw_expr.c Sun Oct 24 20:05:15 2010 -0600 @@ -35,6 +35,10 @@ static lw_expr_fn2_t *evaluate_var = NULL; static lw_expr_fn3_t *parse_term = NULL; +/* Q&D to break out of infinite recursion */ +static int level = 0; +static int bailing = 0; + int lw_expr_istype(lw_expr_t e, int t) { if (e -> type == t) @@ -337,6 +341,9 @@ if (E1 == E2) return 1; + if (!E1 || !E2) + return 0; + if (!(E1 -> type == E2 -> type && E1 -> value == E2 -> value)) return 0; @@ -453,6 +460,8 @@ // not a times - have to assume it's the operand list // with a "1 *" in front if it + if (!e1 -> operands -> next) + return 0; if (e1 -> operands -> next -> next) return 0; if (!lw_expr_compare(e1 -> operands -> next -> p, e2)) @@ -477,7 +486,29 @@ return 1; } -void lw_expr_simplify(lw_expr_t E, void *priv); +int lw_expr_contains(lw_expr_t E, lw_expr_t E1) +{ + struct lw_expr_opers *o; + + // NULL expr contains nothing :) + if (!E) + return 0; + + if (E1 -> type != lw_expr_type_var && E1 -> type != lw_expr_type_special) + return 0; + + if (lw_expr_compare(E, E1)) + return 1; + + for (o = E -> operands; o; o = o -> next) + { + if (lw_expr_contains(o -> p, E1)) + return 1; + } + return 0; +} + +void lw_expr_simplify_l(lw_expr_t E, void *priv); void lw_expr_simplify_go(lw_expr_t E, void *priv) { @@ -518,6 +549,8 @@ lw_expr_t te; te = evaluate_special(E -> value, E -> value2, priv); + if (lw_expr_contains(te, E)) + lw_expr_destroy(te); if (te) { for (o = E -> operands; o; o = o -> next) @@ -544,7 +577,9 @@ lw_expr_t te; te = evaluate_var(E -> value2, priv); - if (te) + if (lw_expr_contains(te, E)) + lw_expr_destroy(te); + else if (te) { for (o = E -> operands; o; o = o -> next) lw_expr_destroy(o -> p); @@ -631,7 +666,7 @@ // simplify operands for (o = E -> operands; o; o = o -> next) - lw_expr_simplify(o -> p, priv); + lw_expr_simplify_l(o -> p, priv); for (o = E -> operands; o; o = o -> next) { @@ -993,10 +1028,21 @@ } } -void lw_expr_simplify(lw_expr_t E, void *priv) +void lw_expr_simplify_l(lw_expr_t E, void *priv) { lw_expr_t te; int c; + + (level)++; + // bail out if the level gets too deep + if (level >= 500 || bailing) + { + bailing = 1; + level--; + if (level == 0) + bailing = 0; + return; + } do { te = lw_expr_copy(E); @@ -1007,8 +1053,13 @@ lw_expr_destroy(te); } while (c); + (level)--; } +void lw_expr_simplify(lw_expr_t E, void *priv) +{ + lw_expr_simplify_l(E, priv); +} /*