OpenSSL函数EVP_EncryptFinal_ex中的内存泄漏

我根据教程实现了加密过程:

http://www.openssl.org/docs/crypto/EVP_EncryptInit.html#

当我运行它通过低谷并得到以下报告:

==2371== 176 bytes in 1 blocks are still reachable in loss record 3 of 6

==2371== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64- linux.so)

==2371== by 0x56CA133: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)

==2371== by 0x575280F: lh_new (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)

==2371== by 0x5754D4F: ??? (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)

==2371== by 0x575503E: ??? (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)

==2371== by 0x5755A1D: ERR_get_state (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)

==2371== by 0x5755E5E: ERR_put_error (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)

==2371== by 0x5757E38: EVP_DecryptFinal_ex (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)

==2371== by 0x46DA2A: unmangleUrl(std::string const&, std::string const&, std::string const&) (mangle_url.cpp:84)

==2371== by 0x46621C: main (main.cpp:348)

我下载了OpenSSL的源代码。在ERR_put_error内部,我看到了ERR_get_state中的内存分配,并在err_clear_data内部释放了内存,但是累积了err_clear_data内部的逻辑。仅当标志ERR_TXT_MALLOCED时它才被释放,并且我看不到谁在升旗。

我做错了什么?

我正在使用Ubuntu 12.04

$ cat /etc/issue

Ubuntu 12.04.2 LTS \n \l

而且OpenSSL版本是

$ openssl version

OpenSSL 1.0.1 14 Mar 2012

我的代码段mangle_url.cpp:

std::string unmangleUrl(const std::string &key, const std::string &iv, const std::string &url)

{

std::string binUrl = hexToBin(url);

std::string res;

res.resize(binUrl.size() * 2);

EVP_CIPHER_CTX ctx;

EVP_CIPHER_CTX_init(&ctx);

EVP_DecryptInit_ex(&ctx, EVP_bf_cbc(), NULL, (const unsigned char *)&key[0], (const unsigned char *)&iv[0]);

int len;

if(!EVP_DecryptUpdate(&ctx, (unsigned char *)&res[0], &len, (const unsigned char *)&binUrl[0], binUrl.size()))

{

EVP_CIPHER_CTX_cleanup(&ctx);

throw std::runtime_error("cannot decrypt URL");

}

int tmpLen;

if(!EVP_DecryptFinal_ex(&ctx, (unsigned char *)&res[len], &tmpLen))

{

EVP_CIPHER_CTX_cleanup(&ctx);

throw std::runtime_error("cannot decrypt URL");

}

len += tmpLen;

EVP_CIPHER_CTX_cleanup(&ctx);

res.resize(len);

return res;

}

来自OpenSSL err.c的代码:

void ERR_put_error(int lib, int func, int reason, const char *file,

int line)

{

ERR_STATE *es;

#ifdef _OSD_POSIX

/* In the BS2000-OSD POSIX subsystem, the compiler generates

* path names in the form "*POSIX(/etc/passwd)".

* This dirty hack strips them to something sensible.

* @@@ We shouldn't modify a const string, though.

*/

if (strncmp(file,"*POSIX(", sizeof("*POSIX(")-1) == 0) {

char *end;

/* Skip the "*POSIX(" prefix */

file += sizeof("*POSIX(")-1;

end = &file[strlen(file)-1];

if (*end == ')')

*end = '\0';

/* Optional: use the basename of the path only. */

if ((end = strrchr(file, '/')) != NULL)

file = &end[1];

}

#endif

es=ERR_get_state(); <-- memory got allocated

es->top=(es->top+1)%ERR_NUM_ERRORS;

if (es->top == es->bottom)

es->bottom=(es->bottom+1)%ERR_NUM_ERRORS;

es->err_flags[es->top]=0;

es->err_buffer[es->top]=ERR_PACK(lib,func,reason);

es->err_file[es->top]=file;

es->err_line[es->top]=line;

err_clear_data(es,es->top); <-- suppose to be released

}

ERR_STATE *ERR_get_state(void)

{

static ERR_STATE fallback;

ERR_STATE *ret,tmp,*tmpp=NULL;

int i;

CRYPTO_THREADID tid;

err_fns_check();

CRYPTO_THREADID_current(&tid);

CRYPTO_THREADID_cpy(&tmp.tid, &tid);

ret=ERRFN(thread_get_item)(&tmp);

/* ret == the error state, if NULL, make a new one */

if (ret == NULL)

{

ret=(ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE)); <-- memory got allocated

if (ret == NULL) return(&fallback);

CRYPTO_THREADID_cpy(&ret->tid, &tid);

ret->top=0;

ret->bottom=0;

for (i=0; i<ERR_NUM_ERRORS; i++)

{

ret->err_data[i]=NULL;

ret->err_data_flags[i]=0;

}

tmpp = ERRFN(thread_set_item)(ret);

/* To check if insertion failed, do a get. */

if (ERRFN(thread_get_item)(ret) != ret)

{

ERR_STATE_free(ret); /* could not insert it */

return(&fallback);

}

/* If a race occured in this function and we came second, tmpp

* is the first one that we just replaced. */

if (tmpp)

ERR_STATE_free(tmpp);

}

return ret;

}

#define err_clear_data(p,i) \

do { \

if (((p)->err_data[i] != NULL) && \

(p)->err_data_flags[i] & ERR_TXT_MALLOCED) \ <-- weired logic with ERR_TXT_MALLOCED flag

{ \

OPENSSL_free((p)->err_data[i]); \

(p)->err_data[i]=NULL; \

} \

(p)->err_data_flags[i]=0; \

} while(0)

回答:

在退出程序之前调用这些函数,就可以了:

CRYPTO_cleanup_all_ex_data();

ERR_free_strings();

ERR_remove_state(0);

EVP_cleanup();

以上是 OpenSSL函数EVP_EncryptFinal_ex中的内存泄漏 的全部内容, 来源链接: utcz.com/qa/421356.html

回到顶部