Expr: fix memory leaks in CondExpr::Eval()

No code path had any cleanup code, leaking all the local references.

More weird was however the result building code: it took elements from
one of the existing vectors without referencing them, and passed them
to VectorVal::Assign() which assumes that the caller-owned reference
is now owned by that VectorVal.

Even in the successful code path, no references were freed.

Everything was wrong with this method!
This commit is contained in:
Max Kellermann 2020-02-19 12:11:48 +01:00
parent 862f48da45
commit 65c4f34385

View file

@ -1995,11 +1995,18 @@ Val* CondExpr::Eval(Frame* f) const
Val* v2 = op2->Eval(f);
if ( ! v2 )
{
Unref(v1);
return 0;
}
Val* v3 = op3->Eval(f);
if ( ! v3 )
{
Unref(v1);
Unref(v2);
return 0;
}
VectorVal* cond = v1->AsVectorVal();
VectorVal* a = v2->AsVectorVal();
@ -2007,6 +2014,9 @@ Val* CondExpr::Eval(Frame* f) const
if ( cond->Size() != a->Size() || a->Size() != b->Size() )
{
Unref(v1);
Unref(v2);
Unref(v3);
RuntimeError("vectors in conditional expression have different sizes");
return 0;
}
@ -2018,13 +2028,19 @@ Val* CondExpr::Eval(Frame* f) const
{
Val* local_cond = cond->Lookup(i);
if ( local_cond )
result->Assign(i,
local_cond->IsZero() ?
b->Lookup(i) : a->Lookup(i));
{
Val *v = local_cond->IsZero() ? b->Lookup(i) : a->Lookup(i);
::Ref(v);
result->Assign(i, v);
}
else
result->Assign(i, 0);
}
Unref(v1);
Unref(v2);
Unref(v3);
return result;
}