[libsigc++2] slot_rep: Avoid access to deleted object in notify().



commit ad1bce5b0ad1caeee5c499b3a80d3455e326b63c
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Thu Jul 14 16:40:16 2011 +0200

    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.

 ChangeLog                    |    8 ++++++++
 sigc++/functors/slot_base.cc |   27 +++++++++++++++++++++++++--
 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;
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]