-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Open
Labels
Description
The following code causes c++-analyzer
to emit a warning:
#include <memory>
#include <openssl/evp.h>
std::pair<std::unique_ptr<unsigned char[]>, int> decryptA(unsigned char *encdata, int enclength)
{
std::pair<std::unique_ptr<unsigned char[]>, int> decrypted{new unsigned char[enclength], enclength};
std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)> ctx(EVP_CIPHER_CTX_new(), &::EVP_CIPHER_CTX_free);
if (EVP_DecryptUpdate(ctx.get(), decrypted.first.get(), &decrypted.second, encdata, enclength) != 1)
return {nullptr, 0};
return decrypted;
}
[~] $ /usr/lib/clang/c++-analyzer -c main93.cc
main93.cc:14:10: warning: Potential leak of memory pointed to by 'decrypted.first._M_t._M_t._M_head_impl' [cplusplus.NewDeleteLeaks]
14 | return decrypted;
| ^~~~~~~~~
1 warning generated.
I believe this is a false positive (but let me know if I'm mistaken). This is version 20.1.8, running on Arch Linux.
Apologies that the code depends on openssl, if I change the call to EVP_DecryptUpdate()
to anything else the warning goes away:
/* !! NO MEMORY LEAK REPORTED FROM THIS CODE !! */
/* Only change: replace EVP_DecryptUpdate with a dummy function with the same signature */
#include <memory>
#include <openssl/evp.h>
int dummy(EVP_CIPHER_CTX *, unsigned char *, int *, unsigned char *, int);
std::pair<std::unique_ptr<unsigned char[]>, int> decryptC(unsigned char *encdata, int enclength)
{
std::pair<std::unique_ptr<unsigned char[]>, int> decrypted{new unsigned char[enclength], enclength};
std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)> ctx(EVP_CIPHER_CTX_new(), &::EVP_CIPHER_CTX_free);
if (dummy(ctx.get(), decrypted.first.get(), &decrypted.second, encdata, enclength) != 1)
return {nullptr, 0};
return decrypted;
}
Similarly, if I do not put the std::unique_ptr
and int
together in a std::pair
, but keep them separate (until returning from the function), the problem also goes away.
/* !! NO MEMORY LEAK REPORTED FROM THIS CODE !! */
/* Only change: do not save the unique_ptr and int in a pair, but keep them separate until the return statement */
#include <memory>
#include <openssl/evp.h>
std::pair<std::unique_ptr<unsigned char[]>, int> decryptB(unsigned char *encdata, int enclength)
{
std::unique_ptr<unsigned char[]> decrypted_first(new unsigned char[enclength]);
int decrypted_second = enclength;
std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)> ctx(EVP_CIPHER_CTX_new(), &::EVP_CIPHER_CTX_free);
if (EVP_DecryptUpdate(ctx.get(), decrypted_first.get(), &decrypted_second, encdata, enclength) != 1)
return {nullptr, 0};
return std::make_pair(std::move(decrypted_first), decrypted_second);
}
Thanks!