diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2020-03-23 12:59:56 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2020-03-23 12:59:56 -0400 |
commit | 12e93e7c7721f9a581f62a8df9534571d0ec353d (patch) | |
tree | 4b352f5a4c940438fb9bcca117a1d330f6134d93 /opt.c | |
parent | cd76a94a328719df61c15b02f25f984b43cce19e (diff) | |
download | bfs-12e93e7c7721f9a581f62a8df9534571d0ec353d.tar.xz |
opt: Avoid dangling pointers in de_morgan()
If optimize_{and,or}_expr() relocates expr, we need to update the parent
expr or else we might return garbage. It seems impossible to actually
trigger this bug right now, since the {and,or} optimizations are
symmetric, but it could be hit if the simplifications in de_morgan()
expose more information than was known previously.
Diffstat (limited to 'opt.c')
-rw-r--r-- | opt.c | 12 |
1 files changed, 7 insertions, 5 deletions
@@ -308,11 +308,11 @@ static struct expr *de_morgan(const struct opt_state *state, struct expr *expr, has_parent = false; } + assert(expr->eval == eval_and || expr->eval == eval_or); if (expr->eval == eval_and) { expr->eval = eval_or; expr->argv = &fake_or_arg; } else { - assert(expr->eval == eval_or); expr->eval = eval_and; expr->argv = &fake_and_arg; } @@ -342,11 +342,13 @@ static struct expr *de_morgan(const struct opt_state *state, struct expr *expr, } else { expr = optimize_or_expr(state, expr); } + if (has_parent) { + parent->rhs = expr; + } else { + parent = expr; + } if (!expr) { - if (has_parent) { - parent->rhs = NULL; - free_expr(parent); - } + free_expr(parent); return NULL; } |