From 94656c2308f6d0fb2316e8cd38821511ce949620 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 23 Mar 2020 21:50:00 -0700 Subject: [PATCH] Fix memory leak in Zeek when-statement bodies with runtime errors --- src/Trigger.cc | 19 +++++++++++++++---- src/Trigger.h | 6 ++++-- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/Trigger.cc b/src/Trigger.cc index b962e449c1..ae2127f791 100644 --- a/src/Trigger.cc +++ b/src/Trigger.cc @@ -321,9 +321,14 @@ bool Trigger::Eval() delete [] pname; #endif - trigger->Cache(frame->GetCall(), v.get()); + auto queued = trigger->Cache(frame->GetCall(), v.get()); trigger->Release(); frame->ClearTrigger(); + + if ( ! queued && trigger->TimeoutValue() < 0 ) + // Usually the parent-trigger would get unref'd either by + // its Eval() or its eventual Timeout(), but has neither + Unref(trigger); } Unref(f); @@ -368,9 +373,14 @@ void Trigger::Timeout() DBG_LOG(DBG_NOTIFIERS, "%s: trigger has parent %s, caching timeout result", Name(), pname); delete [] pname; #endif - trigger->Cache(frame->GetCall(), v.get()); + auto queued = trigger->Cache(frame->GetCall(), v.get()); trigger->Release(); frame->ClearTrigger(); + + if ( ! queued && trigger->TimeoutValue() < 0 ) + // Usually the parent-trigger would get unref'd either by + // its Eval() or its eventual Timeout(), but has neither + Unref(trigger); } } @@ -429,10 +439,10 @@ void Trigger::Attach(Trigger *trigger) Hold(); } -void Trigger::Cache(const CallExpr* expr, Val* v) +bool Trigger::Cache(const CallExpr* expr, Val* v) { if ( disabled || ! v ) - return; + return false; ValCache::iterator i = cache.find(expr); @@ -448,6 +458,7 @@ void Trigger::Cache(const CallExpr* expr, Val* v) Ref(v); trigger_mgr->Queue(this); + return true; } diff --git a/src/Trigger.h b/src/Trigger.h index 685f8ec129..5d91b17aa0 100644 --- a/src/Trigger.h +++ b/src/Trigger.h @@ -59,8 +59,10 @@ public: // to the given trigger. Note, automatically calls Hold(). void Attach(Trigger* trigger); - // Cache for return values of delayed function calls. - void Cache(const CallExpr* expr, Val* val); + // Cache for return values of delayed function calls. Returns whether + // the trigger is queued for later evaluation -- it may not be queued + // if the Val is null or it's disabled. + bool Cache(const CallExpr* expr, Val* val); Val* Lookup(const CallExpr*); // Disable this trigger completely. Needed because Unref'ing the trigger