summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjell Ahlstedt <kjell.ahlstedt@bredband.net>2011-07-14 16:40:16 +0200
committerMurray Cumming <murrayc@murrayc.com>2011-07-19 11:13:08 +0200
commitad1bce5b0ad1caeee5c499b3a80d3455e326b63c (patch)
treef973e933b0241d54d32010d23c097c6dbd3a9ce1
parent471d4a5341db13ee471792d31d3d59e53b6c7184 (diff)
downloadsigc++-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--ChangeLog8
-rw-r--r--sigc++/functors/slot_base.cc27
2 files changed, 33 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index dbf622c..56984e3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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(&notifier, 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(&notifier);
+ 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;
}