Expr: reference id_list before passing to new BroFunc

Passing the `id_list` pointer to `BroFunc` transfers ownership of the
contained `ID` instances, because `~BroFunc()` unreferences them.
Therefore, we need to increase the reference counters for each
`BroFunc` instance to fix the use-after-free bug.

Closes https://github.com/zeek/zeek/issues/845
This commit is contained in:
Max Kellermann 2020-03-05 17:00:55 +01:00
parent 4d39f53ab2
commit df7a47510a

View file

@ -4283,6 +4283,20 @@ void CallExpr::ExprDescribe(ODesc* d) const
args->Describe(d); args->Describe(d);
} }
/**
* Create a new #id_list containing new references to the given list.
*/
static std::unique_ptr<id_list> shallow_copy_id_list(const id_list &src)
{
auto dest = std::make_unique<id_list>(src.length());
for (ID *i : src)
{
Ref(i);
dest->push_back(i);
}
return dest;
}
LambdaExpr::LambdaExpr(std::unique_ptr<function_ingredients> arg_ing, LambdaExpr::LambdaExpr(std::unique_ptr<function_ingredients> arg_ing,
id_list arg_outer_ids) : Expr(EXPR_LAMBDA) id_list arg_outer_ids) : Expr(EXPR_LAMBDA)
{ {
@ -4297,7 +4311,7 @@ LambdaExpr::LambdaExpr(std::unique_ptr<function_ingredients> arg_ing,
BroFunc* dummy_func = new BroFunc( BroFunc* dummy_func = new BroFunc(
ingredients->id, ingredients->id,
ingredients->body, ingredients->body,
ingredients->inits, ingredients->body && ingredients->inits && ingredients->inits->length() > 0 ? shallow_copy_id_list(*ingredients->inits).release() : nullptr,
ingredients->frame_size, ingredients->frame_size,
ingredients->priority); ingredients->priority);
@ -4345,7 +4359,7 @@ IntrusivePtr<Val> LambdaExpr::Eval(Frame* f) const
auto lamb = make_intrusive<BroFunc>( auto lamb = make_intrusive<BroFunc>(
ingredients->id, ingredients->id,
ingredients->body, ingredients->body,
ingredients->inits, ingredients->body && ingredients->inits && ingredients->inits->length() > 0 ? shallow_copy_id_list(*ingredients->inits).release() : nullptr,
ingredients->frame_size, ingredients->frame_size,
ingredients->priority); ingredients->priority);