-
Notifications
You must be signed in to change notification settings - Fork 15.3k
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. (EDIT now at 21.1.4, issue unchanged)
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!
seandewar