Index: base/memory/scoped_ptr.h |
diff --git a/base/memory/scoped_ptr.h b/base/memory/scoped_ptr.h |
index fb781b0b32ddfd8b47ff3e4a0662ff53b9cd8760..27a1fd4839ef1ccd0962a5eee3561b599f7ef213 100644 |
--- a/base/memory/scoped_ptr.h |
+++ b/base/memory/scoped_ptr.h |
@@ -217,9 +217,19 @@ class scoped_ptr_impl { |
~scoped_ptr_impl() { |
if (data_.ptr != nullptr) { |
+ // Even though |this| should no longer be accessed after destruction, |
+ // there may be use-after-free bugs. Setting |data_.ptr| to null should |
+ // cause many attempts to dereference |this| to segfault closer to the |
+ // source of the use-after-free. Of course, this may not catch issues if |
+ // the memory is immediately re-allocated and altered. |
+ // Set the value to nullptr before running the deleter in case the deleter |
+ // references |this|. Unlike libc++, we can't call reset() because reset() |
+ // references |this| after running the deleter. |
Peter Kasting
2015/09/23 01:14:39
It looks like reset() was changed to an intermedia
Anand Mistry (off Chromium)
2015/09/23 01:44:52
Despite being small, I think that's a significant
Peter Kasting
2015/09/23 01:52:58
That's fine; why not do that first and then make a
Anand Mistry (off Chromium)
2015/09/23 04:48:04
Done.
|
+ T* old = data_.ptr; |
+ data_.ptr = nullptr; |
// Not using get_deleter() saves one function call in non-optimized |
// builds. |
- static_cast<D&>(data_)(data_.ptr); |
+ static_cast<D&>(data_)(old); |
} |
} |