diff options
author | Kjell Ahlstedt <kjell.ahlstedt@bredband.net> | 2011-07-14 16:40:16 +0200 |
---|---|---|
committer | Murray Cumming <murrayc@murrayc.com> | 2011-07-19 11:13:08 +0200 |
commit | ad1bce5b0ad1caeee5c499b3a80d3455e326b63c (patch) | |
tree | f973e933b0241d54d32010d23c097c6dbd3a9ce1 | |
parent | 471d4a5341db13ee471792d31d3d59e53b6c7184 (diff) | |
download | sigc++-ad1bce5b0ad1caeee5c499b3a80d3455e326b63c.tar.gz |
slot_rep: Avoid access to deleted object in notify().
* sigc++/functors/slot_base.cc: slot_rep::notify() calls disconnect() before
destroy(). If disconnect() has deleted the slot_rep object, destroy() is not
called. Bug #564005.
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | sigc++/functors/slot_base.cc | 27 |
2 files changed, 33 insertions, 2 deletions
@@ -1,3 +1,11 @@ +2011-07-14 Kjell Ahlstedt <kjell.ahlstedt@bredband.net> + + slot_rep: Avoid access to deleted object in notify(). + + * sigc++/functors/slot_base.cc: slot_rep::notify() calls disconnect() before + destroy(). If disconnect() has deleted the slot_rep object, destroy() is not + called. Bug #564005. + 2.2.9: 2011-02-22 Kjell Ahlstedt <kjell.ahlstedt@bredband.net> diff --git a/sigc++/functors/slot_base.cc b/sigc++/functors/slot_base.cc index 896276b..3f1de0b 100644 --- a/sigc++/functors/slot_base.cc +++ b/sigc++/functors/slot_base.cc @@ -56,12 +56,35 @@ void slot_rep::disconnect() //static void* slot_rep::notify(void* data) { + struct destroy_notify_struct + { + destroy_notify_struct() : deleted_(false) { } + + static void* notify(void* data) + { + destroy_notify_struct* self_ = reinterpret_cast<destroy_notify_struct*>(data); + self_->deleted_ = true; + return 0; + } + + bool deleted_; + }; + slot_rep* self_ = reinterpret_cast<slot_rep*>(data); self_->call_ = 0; // Invalidate the slot. - self_->destroy(); // Detach the stored functor from the other referred trackables and destroy it. + + // Make sure we are notified if disconnect() deletes self_, which is trackable. + destroy_notify_struct notifier; + self_->add_destroy_notify_callback(¬ifier, destroy_notify_struct::notify); self_->disconnect(); // Disconnect the slot (might lead to deletion of self_!). - + // If self_ has been deleted, the destructor has called destroy(). + if (!notifier.deleted_) + { + self_->remove_destroy_notify_callback(¬ifier); + self_->destroy(); // Detach the stored functor from the other referred trackables and destroy it. + // destroy() might lead to deletion of self_. Bug #564005. + } return 0; } |