Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check _ptr != ptr is not enough in AutoPtr.assign #3979

Closed
funny-falcon opened this issue Mar 21, 2023 · 4 comments · Fixed by #4068
Closed

Check _ptr != ptr is not enough in AutoPtr.assign #3979

funny-falcon opened this issue Mar 21, 2023 · 4 comments · Fixed by #4068

Comments

@funny-falcon
Copy link
Contributor

if (&ptr != this)
{
if (_ptr) _ptr->release();
_ptr = ptr._ptr;
if (_ptr) _ptr->duplicate();
}

New object could be one referenced by old with it's internal AutoPtr.
If we release old pointer before duplicate new we could have dangled pointer problem already.

@funny-falcon funny-falcon changed the title Check _ptr != ptr is not enouch in AutoPtr.assign Check _ptr != ptr is not enough in AutoPtr.assign Apr 5, 2023
@aleks-f
Copy link
Member

aleks-f commented Jun 10, 2023

@funny-falcon how does the dangling pointer happen exactly? the check is whether the assigned-from AutoPtr is the same as the assigned-to one. If they are different AutoPtrs pointing to the same object, assignment can be skipped because they are both in the desired state already, but there is no harm done even if assignment happens - the assigned-to release() will not delete because assigned-from still keeps the reference count > 0

@funny-falcon
Copy link
Contributor Author

Using poco 1.11.0 from Ubuntu 23.04

#include <iostream>
#include <string>
#include <Poco/RefCountedObject.h>
#include <Poco/AutoPtr.h>

class RCO : public Poco::RefCountedObject
{
    public:
        RCO(int _i) : i(_i), name("RCO(" + std::to_string(_i) + ")")
        {
            std::cout << name << " constructed\n";
        }

        int i;
        std::string name;
        Poco::AutoPtr<RCO> linked;

        ~RCO()
        {
            std::cout << name << " destructed\n";
            name = "BOOMED " + name;
        }
};

Poco::AutoPtr<RCO>
make_two()
{
    Poco::AutoPtr<RCO> a(new RCO(1));
    a->linked = new RCO(2);
    return a;
}

int
main() {
    Poco::AutoPtr<RCO> a;

    a = make_two();
    std::cout << "will it boom?\n";
    a = a->linked;

    std::cout << "hello " << a->name << "\n";
}

Output:

~/tmp/poco_issue3979 $ g++ issue3979.cc -lPocoFoundation
~/tmp/poco_issue3979 $ ./a.out 
RCO(1) constructed
RCO(2) constructed
will it boom?
RCO(1) destructed
RCO(2) destructed
hello BOOMED RCO(2)

@funny-falcon
Copy link
Contributor Author

funny-falcon commented Jun 10, 2023

Is it desired behavior?

@aleks-f
Copy link
Member

aleks-f commented Jun 21, 2023

Is it desired behavior?

I'd say, it is not a desirable use - you are assigning a member AutoPtr to the owner object, which is also an AutoPtr, so the operation causes the member to inadvertently be destructed during the assignment.
Sadly, we don't provide a shield against shooting yourself in the foot.

You can do this instead and everything will be fine:

auto b = a->linked;
a = b;

funny-falcon added a commit to funny-falcon/poco that referenced this issue Jun 30, 2023
Common knowledge in reference counting is "on assignment increment first
then decrement", because "just to be deleted" object could hold last
reference to "just to be assigned" one.

Fixes pocoproject#3979
aleks-f pushed a commit that referenced this issue Nov 23, 2023
Common knowledge in reference counting is "on assignment increment first
then decrement", because "just to be deleted" object could hold last
reference to "just to be assigned" one.

Fixes #3979
aleks-f pushed a commit that referenced this issue Nov 27, 2023
Common knowledge in reference counting is "on assignment increment first
then decrement", because "just to be deleted" object could hold last
reference to "just to be assigned" one.

Fixes #3979
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants