From 5e779ce4ac4f4c9d6f14f5c56dbfcfd7a32501ec Mon Sep 17 00:00:00 2001 From: Eugene Lazutkin Date: Wed, 5 Jun 2024 12:02:16 -0500 Subject: [PATCH] Added a guard against calling a weak callback on already deleted instance. Refs #210. --- lib/addon.cc | 36 +++++++++++++++++++++++++++++++----- lib/wrapped_re2.h | 20 +++++++++++++------- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/lib/addon.cc b/lib/addon.cc index 7b22159..d446385 100644 --- a/lib/addon.cc +++ b/lib/addon.cc @@ -94,8 +94,29 @@ NODE_MODULE_INIT() Nan::Set(module->ToObject(context).ToLocalChecked(), Nan::New("exports").ToLocalChecked(), WrappedRE2::Init()); } +WrappedRE2::~WrappedRE2() +{ + for (auto ptr : callbackRegistry) + { + *ptr = nullptr; + } + dropLastString(); +} + // private methods +WrappedRE2::PtrWrappedRE2 *WrappedRE2::registerCallback() +{ + PtrWrappedRE2 *ptr = new PtrWrappedRE2(this); + callbackRegistry.insert(ptr); + return ptr; +} + +void WrappedRE2::unregisterCallback(PtrWrappedRE2 *ptr) +{ + callbackRegistry.erase(ptr); +} + void WrappedRE2::dropLastString() { lastString.Reset(); @@ -106,10 +127,15 @@ void WrappedRE2::dropLastString() } } -void WrappedRE2::weakLastStringCallback(const Nan::WeakCallbackInfo &data) +void WrappedRE2::weakLastStringCallback(const Nan::WeakCallbackInfo &data) { - WrappedRE2* re2 = data.GetParameter(); - re2->dropLastString(); + PtrWrappedRE2 *re2 = data.GetParameter(); + if (*re2) + { + (*re2)->unregisterCallback(re2); + (*re2)->dropLastString(); + } + delete re2; } void WrappedRE2::prepareLastString(const v8::Local &arg, bool ignoreLastIndex) @@ -137,10 +163,10 @@ void WrappedRE2::prepareLastString(const v8::Local &arg, bool ignoreL dropLastString(); lastString.Reset(arg); - static_cast&>(lastString).SetWeak(); + static_cast &>(lastString).SetWeak(); Nan::Persistent dummy(arg); - dummy.SetWeak(this, weakLastStringCallback, Nan::WeakCallbackType::kParameter); + dummy.SetWeak(registerCallback(), weakLastStringCallback, Nan::WeakCallbackType::kParameter); lastStringValue = new StrValString(arg, startFrom); }; diff --git a/lib/wrapped_re2.h b/lib/wrapped_re2.h index 33ed15a..89fa68a 100644 --- a/lib/wrapped_re2.h +++ b/lib/wrapped_re2.h @@ -6,6 +6,7 @@ #include #include +#include struct StrValBase; @@ -67,10 +68,7 @@ class WrappedRE2 : public Nan::ObjectWrap static NAN_SETTER(SetUnicodeWarningLevel); public: - ~WrappedRE2() - { - dropLastString(); - } + ~WrappedRE2(); static v8::Local Init(); @@ -108,7 +106,13 @@ class WrappedRE2 : public Nan::ObjectWrap Nan::Persistent lastString; // weak pointer StrValBase *lastStringValue; - static void weakLastStringCallback(const Nan::WeakCallbackInfo &data); + typedef WrappedRE2 *PtrWrappedRE2; + + std::unordered_set callbackRegistry; + PtrWrappedRE2 *registerCallback(); + void unregisterCallback(PtrWrappedRE2 *re2); + + static void weakLastStringCallback(const Nan::WeakCallbackInfo &data); void dropLastString(); void prepareLastString(const v8::Local &arg, bool ignoreLastIndex = false); @@ -116,11 +120,13 @@ class WrappedRE2 : public Nan::ObjectWrap struct PrepareLastString { - PrepareLastString(WrappedRE2 *re2, const v8::Local &arg, bool ignoreLastIndex = false) : re2(re2) { + PrepareLastString(WrappedRE2 *re2, const v8::Local &arg, bool ignoreLastIndex = false) : re2(re2) + { re2->prepareLastString(arg, ignoreLastIndex); } - ~PrepareLastString() { + ~PrepareLastString() + { if (!re2->enabledCache || !(re2->global || re2->sticky)) re2->dropLastString(); }