Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
OpenSSL函数EVP_EncryptFinal_ex内存泄漏_C_Linux_Memory Leaks_Openssl_Valgrind - Fatal编程技术网

OpenSSL函数EVP_EncryptFinal_ex内存泄漏

OpenSSL函数EVP_EncryptFinal_ex内存泄漏,c,linux,memory-leaks,openssl,valgrind,C,Linux,Memory Leaks,Openssl,Valgrind,我根据教程实现了加密过程: 当我通过valgring运行它时,得到了以下报告: ==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 /

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

当我通过valgring运行它时,得到了以下报告:

==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_状态,并释放ERR_clear_数据中的内存,但累积ERR_clear_数据中的逻辑。只有当旗帜出现错误时,它才会发布,我不知道是谁在升起旗帜

我做错了什么

我正在使用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\u put\u error(int-lib、int-func、int-reason、const-char*文件、,
整数行)
{
错误状态;
#ifdef_OSD_POSIX
/*在BS2000-OSD POSIX子系统中,编译器生成
*路径名的格式为“*POSIX(/etc/passwd)”。
*这个卑鄙的黑客把他们剥去了一些理智的东西。
*@@@但是,我们不应该修改常量字符串。
*/
if(strncmp(文件,“*POSIX(”,sizeof(“*POSIX(”)-1)==0){
字符*结束;
/*跳过“*POSIX”(“前缀*/
file+=sizeof(“*POSIX(”)-1;
end=&file[strlen(file)-1];
如果(*end=='))
*结束='\0';
/*可选:仅使用路径的基本名称*/
如果((end=strrchr(文件“/”)!=NULL)
文件=&end[1];
}
#恩迪夫
es=ERR_get_state();top=(es->top+1)%ERR_NUM_ERRORS;
如果(es->top==es->bottom)
es->bottom=(es->bottom+1)%ERR\u NUM\u ERRORS;
es->err_标志[es->top]=0;
es->err_buffer[es->top]=err_PACK(lib、func、reason);
es->err_文件[es->top]=文件;
es->err_行[es->top]=行;
错误清除数据(es,es->top);top=0;
ret->bottom=0;
对于(i=0;ierr_数据[i]=NULL;
ret->err\u data\u标志[i]=0;
}
tmpp=ERRFN(螺纹设置项目)(ret);
/*要检查插入是否失败,请执行get*/
if(ERRFN(线程获取项目)(ret)!=ret)
{
ERR_STATE_free(ret);/*无法插入它*/
返回(&回退);
}
/*如果在这个函数中发生了一场竞赛,而我们排在第二位,那么tmpp
*是我们刚刚更换的第一个*/
国际单项体育联合会(tmpp)
无错误状态(tmpp);
}
返回ret;
}

#定义错误清除数据(p,i)\
做{\
如果((p)->err_data[i]!=NULL)和\
(p) ->err_data_flags[i]&err_TXT_MALLOCED)\err_data[i]\
(p) ->err_data[i]=NULL\
} \
(p) ->错误数据标志[i]=0\
}而(0)

在退出程序之前调用这些函数,您应该可以:

CRYPTO_cleanup_all_ex_data();
ERR_free_strings();
ERR_remove_state(0);
EVP_cleanup();

谢谢,这很有帮助。现在Valgrind很高兴:)就为了后代,当前OpenSSL版本(1.0.2g)不推荐使用
ERR\u remove\u state()
,而应该使用
ERR\u remove\u thread\u state()
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();