summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMurray Cumming <murrayc@murrayc.com>2005-05-01 02:00:47 +0000
committerMurray Cumming <murrayc@src.gnome.org>2005-05-01 02:00:47 +0000
commit66b2af11838094e8b4459f1d6fdedd8d35d4c483 (patch)
treebb2fb99656dd243c2c79af08703124b4940ee8e6
parent9d3a58d8953932e3619da68ee2b31d8aff5d1f98 (diff)
downloadsigc++-66b2af11838094e8b4459f1d6fdedd8d35d4c483.tar.gz
slot_base::slot_base(src): If the source slot_base has a null rep->call_,
2005-05-01 Murray Cumming <murrayc@murrayc.com> * sigc++/functors/slot_base.cc: slot_base::slot_base(src): If the source slot_base has a null rep->call_, meaning that the slot is invalid, just return a default-constructed slot, to prevent the crash shown in tests/tests_copy_invalid_slot.cc. Bug #302515 by Régis Duchesne.
-rw-r--r--ChangeLog10
-rw-r--r--sigc++/functors/slot_base.cc14
-rw-r--r--tests/test_copy_invalid_slot.cc5
3 files changed, 28 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index eed146c..0825c48 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
2005-05-01 Murray Cumming <murrayc@murrayc.com>
+ * sigc++/functors/slot_base.cc:
+ slot_base::slot_base(src): If the source
+ slot_base has a null rep->call_, meaning that the
+ slot is invalid, just return a default-constructed
+ slot, to prevent the crash shown in
+ tests/tests_copy_invalid_slot.cc. Bug #302515 by
+ Régis Duchesne.
+
+2005-05-01 Murray Cumming <murrayc@murrayc.com>
+
* sigc++/functors/macros/mem_fun.h.m4: bound_*<>:
Add a new is_base_and_derived<sigc::trackable>
parameter to the template and thereby provide a
diff --git a/sigc++/functors/slot_base.cc b/sigc++/functors/slot_base.cc
index 6f57e74..27e37ae 100644
--- a/sigc++/functors/slot_base.cc
+++ b/sigc++/functors/slot_base.cc
@@ -55,9 +55,11 @@ void slot_rep::disconnect()
void* slot_rep::notify(void* data)
{
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.
self_->disconnect(); // Disconnect the slot (might lead to deletion of self_!).
+
return 0;
}
@@ -78,7 +80,17 @@ slot_base::slot_base(const slot_base& src)
blocked_(src.blocked_)
{
if (src.rep_)
- rep_ = src.rep_->dup();
+ {
+ //Check call_ so we can ignore invalidated slots.
+ //Otherwise, destroyed bound reference parameters (whose destruction caused the slot's invalidation) may be used during dup().
+ //Note: I'd prefer to check somewhere during dup(). murrayc.
+ if (src.rep_->call_)
+ rep_ = src.rep_->dup();
+ else
+ {
+ *this = slot_base(); //Return the default invalid slot.
+ }
+ }
}
slot_base::~slot_base()
diff --git a/tests/test_copy_invalid_slot.cc b/tests/test_copy_invalid_slot.cc
index 4739c17..40162b0 100644
--- a/tests/test_copy_invalid_slot.cc
+++ b/tests/test_copy_invalid_slot.cc
@@ -11,6 +11,11 @@ int main(int argc, char **argv)
// This invalidates foo.
delete t;
+ // Try to crash if the invalid slot parameter is used by libsigc++,
+ // and get a debugger backtrace at the point that it happens.
+ //
+ // Comment this out to get a meaningful backtrace from valgrind.
+ //
// Try to pollute the memory previously occupied by the sigc::trackable
// instance. The hope is that with a regular memory allocator (i.e. not
// valgrind), we end up with buffer == (void *)t.