Commit a715453a authored by Robert Sesek's avatar Robert Sesek Committed by Commit Bot

Add overload base::ScopedTypeRef::reset(const ScopedTypeRef&)

Without this, reset()ing a ScopedTypeRef with a temporary ScopedTypeRef
results in the receiver storing a dead pointer. This is because the
reset(element_type) method causes implicit conversion of argument
ScopedTypeRef via |operator element_type()|, with the receiver assuming
ownership rather than retaining.

As an example, prior to this change, the following snippet would leave
|member_| holding a dead pointer:

  member_.reset(base::ScopedCFTypeRef<CFStringRef>(
      CFStringCreateCopy(NULL, CFSTR("Use-after-free"))));

Bug: 1100258
Change-Id: I528b6b32d0bd4ac1f91978dde39e818bef41cdd5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2277000
Commit-Queue: Robert Sesek <rsesek@chromium.org>
Reviewed-by: default avatarMark Mentovai <mark@chromium.org>
Cr-Commit-Position: refs/heads/master@{#784432}
parent 41026e04
......@@ -96,4 +96,23 @@ TEST(ScopedNSObjectTest, ScopedNSObjectFreeFunctions) {
ASSERT_EQ(o1, p2.get());
}
TEST(ScopedNSObjectTest, ResetWithAnotherScopedNSObject) {
base::scoped_nsobject<id> p1([[NSObject alloc] init]);
id o1 = p1.get();
id o2 = nil;
{
base::scoped_nsobject<id> p2([[NSObject alloc] init]);
o2 = p2.get();
p1.reset(p2);
EXPECT_EQ(2u, [p1 retainCount]);
}
EXPECT_NE(o1, p1.get());
EXPECT_EQ(o2, p1.get());
EXPECT_NE(p1.get(), nil);
EXPECT_EQ(1u, [p1 retainCount]);
}
} // namespace
......@@ -97,6 +97,10 @@ class ScopedTypeRef {
return &object_;
}
void reset(const ScopedTypeRef<T, Traits>& that) {
reset(that.get(), base::scoped_policy::RETAIN);
}
void reset(element_type object = Traits::InvalidValue(),
base::scoped_policy::OwnershipPolicy policy =
base::scoped_policy::ASSUME) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment