[llvm-bugs] [Bug 50369] New: Initializing shared_ptr with make_shared should not call destructor

via llvm-bugs llvm-bugs at lists.llvm.org
Mon May 17 01:51:04 PDT 2021


https://bugs.llvm.org/show_bug.cgi?id=50369

            Bug ID: 50369
           Summary: Initializing shared_ptr with make_shared should not
                    call destructor
           Product: clang
           Version: 12.0
          Hardware: PC
                OS: All
            Status: NEW
          Severity: normal
          Priority: P
         Component: C++
          Assignee: unassignedclangbugs at nondot.org
          Reporter: 19210240016 at fudan.edu.cn
                CC: blitzrakete at gmail.com, dgregor at apple.com,
                    erik.pilkington at gmail.com, llvm-bugs at lists.llvm.org,
                    richard-llvm at metafoo.co.uk

Created attachment 24861
  --> https://bugs.llvm.org/attachment.cgi?id=24861&action=edit
the code to generate a double free case

I test my program with Apple clang version 12.0.5. When I initialize a
shared_ptr by calling make_shared, it will call the destructor. I think it is
against the semantics of shared_ptr.
Here is a short code example to explain what happens.

//code_example.cpp
#include<iostream>
#include<memory>
using namespace std;

struct foo {
    int val;
    foo(int value): val(value) {cout << "constructor" << endl;}
    foo(const foo &other) {cout << "copy" << endl;}
    ~foo() {cout << "destructor" << endl;}
};

int main() {
    shared_ptr<foo> foo1 = make_shared<foo>(3);
    return 0;
}

If we compile the program code_example.cpp with clang++ and run it, the output
is following 4 lines.
constructor
copy
destructor
destructor

I can guess what happens behind the result. When I call make_shared to
initialize foo1 (the first line in the main function), the righthand of the
assignment calls the constructor to construct a foo object. Then the copy
constructor is called to initilize foo1 with righthand object. Finally, the
destructor is called to destroy the righthand object. When main function exits,
the destructor is called again to destroy foo1.

I think this result is against the semantics of shared_ptr. shared_ptr should
copy an object by adding the reference count, rather than calling the copy
constructor to copy a new object and destroy the old one.

If I compile code_example.cpp with g++(version 7.5.0, ubuntu 18.04), the result
is right. It views the first line in main function as initializing a new
shared_ptr. It will output
constructor
destructor

I think the g++ result is correct. g++ does not call the copy constructor, so
g++ will also not call destructor to destroy the righthand object.

This behavior is very dangerous as it may introduce security issues in the
seemingly harmless code. I give a double free example in attached
double_free.cpp.

I also find that if the struct foo has a constructor with no parameters (like
the default-generated constructor), the bug will not be triggered.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20210517/108cc147/attachment-0001.html>


More information about the llvm-bugs mailing list