Skip to content

False positive in clang-analyzer-cplusplus.NewDeleteLeaks for std::unique_ptr #143807

@ns-osmolsky

Description

@ns-osmolsky
#include <memory>
#include <cstring>
#include <string>

struct Repro {
    std::unique_ptr<int> m_ptr;

    struct Other {
        char url[256];
    };
    char m_buff[1000];

    void CopyIn()
    {
        auto other = (Other *)m_buff;

        std::string local_url = "foo bar";
        strncpy(other->url, local_url.c_str(), sizeof(other->url) - 1);
    }
};

void
bug()
{
    Repro rep;
    rep.m_ptr = std::make_unique<int>();
    rep.CopyIn();
}

clang-tidy reports the following when building against the GCC-15's libstdc++:

repro.cpp:19:5: error: Potential leak of memory pointed to by field '_M_head_impl' [clang-analyzer-cplusplus.NewDeleteLeaks,-warnings-as-errors]
   19 |     }
      |     ^
repro.cpp:26:17: note: Calling 'make_unique<int, >'
   26 |     rep.m_ptr = std::make_unique<int>();
      |                 ^~~~~~~~~~~~~~~~~~~~~~~
/opt/gcc-15/lib/gcc/x86_64-pc-linux-gnu/15.1.1/../../../../include/c++/15.1.1/bits/unique_ptr.h:1085:30: note: Memory is allocated
 1085 |     { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
      |                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
repro.cpp:26:17: note: Returned allocated memory
   26 |     rep.m_ptr = std::make_unique<int>();
      |                 ^~~~~~~~~~~~~~~~~~~~~~~
repro.cpp:27:5: note: Calling 'Repro::CopyIn'
   27 |     rep.CopyIn();
      |     ^~~~~~~~~~~~
repro.cpp:19:5: note: Potential leak of memory pointed to by field '_M_head_impl'
   19 |     }
      |     ^

There is clearly no leak here and the warning goes away if the code is tweaked just a little bit... I cannot understand

Activity

ns-osmolsky

ns-osmolsky commented on Jun 11, 2025

@ns-osmolsky
Author

I cannot understand why/how this code gets flagged by the analyzer... especially given that tiny changes such as this eliminate the warning:

    void CopyIn()
    {
        auto other = (Other *)m_buff;
        strncpy(other->url, "foo bar", sizeof(other->url) - 1);
    }
llvmbot

llvmbot commented on Jun 11, 2025

@llvmbot
Member

@llvm/issue-subscribers-clang-static-analyzer

Author: Oleg Smolsky (ns-osmolsky)

``` #include <memory> #include <cstring> #include <string>

struct Repro {
std::unique_ptr<int> m_ptr;

struct Other {
    char url[256];
};
char m_buff[1000];

void CopyIn()
{
    auto other = (Other *)m_buff;

    std::string local_url = "foo bar";
    strncpy(other-&gt;url, local_url.c_str(), sizeof(other-&gt;url) - 1);
}

};

void
bug()
{
Repro rep;
rep.m_ptr = std::make_unique<int>();
rep.CopyIn();
}


`clang-tidy` reports the following when building against the GCC-15's libstdc++:

repro.cpp:19:5: error: Potential leak of memory pointed to by field '_M_head_impl' [clang-analyzer-cplusplus.NewDeleteLeaks,-warnings-as-errors]
19 | }
| ^
repro.cpp:26:17: note: Calling 'make_unique<int, >'
26 | rep.m_ptr = std::make_unique<int>();
| ^~~~~~~~~~~~~~~~~~~~~~~
/opt/gcc-15/lib/gcc/x86_64-pc-linux-gnu/15.1.1/../../../../include/c++/15.1.1/bits/unique_ptr.h:1085:30: note: Memory is allocated
1085 | { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
repro.cpp:26:17: note: Returned allocated memory
26 | rep.m_ptr = std::make_unique<int>();
| ^~~~~~~~~~~~~~~~~~~~~~~
repro.cpp:27:5: note: Calling 'Repro::CopyIn'
27 | rep.CopyIn();
| ^~~~~~~~~~~~
repro.cpp:19:5: note: Potential leak of memory pointed to by field '_M_head_impl'
19 | }
| ^


There is clearly no leak here and the warning goes away if the code is tweaked just a little bit... I cannot understand 
</details>
steakhal

steakhal commented on Jun 12, 2025

@steakhal
Contributor

Did you use clang tidy trunk?

ns-osmolsky

ns-osmolsky commented on Jun 12, 2025

@ns-osmolsky
Author

Did you use clang tidy trunk?

This issue is present in 20.1.3 and 20.1.6. I have not tried Trunk.

ns-lwu

ns-lwu commented on Jun 13, 2025

@ns-lwu

Hope I get CE right.
Tried clang trunk and 20.1 both report the same issue
https://godbolt.org/z/MzWMxG6dr

ns-osmolsky

ns-osmolsky commented on Jun 13, 2025

@ns-osmolsky
Author

The issue is still present in Trunk. Here is a direct repro with the clang-tidy selected as the tool: https://godbolt.org/z/MbM4c1Pdr

ns-osmolsky

ns-osmolsky commented on Jun 13, 2025

@ns-osmolsky
Author

Here is a slightly reduced repro: eliminated casts and extra types.

#include <memory>
#include <cstring>
#include <string>

struct Repro {
    std::unique_ptr<int> m_ptr;
    char m_buff[1000];

    void CopyIn(const std::string &url)
    {
        strncpy(m_buff, url.c_str(), sizeof(m_buff) - 1);
    }
};

void Bug()
{
    Repro rep;
    rep.m_ptr = std::make_unique<int>();
    rep.CopyIn("foo bar");
}
steakhal

steakhal commented on Jun 13, 2025

@steakhal
Contributor

Thabk you.
/CC @necto

necto

necto commented on Jun 13, 2025

@necto
Contributor

I have stumbled upon a similar false positive raising when I use a custom deleter with std::unique_ptr. It seems to be caused by 9b2ec87
A partial fix b756c82 did not cover the case of a copy-initialized deleter, so the false-positive with a custom deleter remains in Clang-20.

In your case, seems to be somewhat different, though, so I encourage you to try if FP appears before or after 9b2ec87

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Participants

      @necto@steakhal@EugeneZelenko@llvmbot@ns-osmolsky

      Issue actions

        False positive in clang-analyzer-cplusplus.NewDeleteLeaks for std::unique_ptr · Issue #143807 · llvm/llvm-project