OpenSSL中的内存泄漏?

我使用以下代码检查签名。 为简单起见,公钥,消息和签名在main中初始化。

 #include  #include  #include  #include  int main(){ const unsigned char key[] = "-----BEGIN PUBLIC KEY-----\n" "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALulMfYFyX1kSm7oUxZyCWWhrBBcWrRA\n" "V7LSz1PzMPxoxG3KS8H7PRKFkIk42yM8/vhobmcCmj7UM5572wWch50CAwEAAQ==\n" "-----END PUBLIC KEY-----\n"; unsigned int key_len = sizeof(key); const unsigned char data[] = {0x6d,0x65,0x73,0x65,0x0a}; unsigned int data_len = sizeof(data); const unsigned char sig[] = {0xa9,0x29,0x81,0x07,0x8c,0xeb,0xf0,0x1b,0x2a,0x31,0xe5,0x60,0x94,0x8a,0x47,0x94,0x3a,0x8f,0x6b, 0x4e,0x85,0xb9,0xe7,0xe5,0x4a,0x6c,0x56,0x46,0xd1,0x80,0x15,0x57,0xce,0xcb,0x0a,0x3a,0x67,0x15,0xed, 0x68,0x03,0x58,0x99,0xa4,0x73,0x61,0xe3,0x30,0x85,0xff,0x89,0x7e,0x32,0xef,0x16,0xec,0x23,0x7f,0x14, 0xde,0xbf,0x53,0xe0,0x3a}; unsigned int sig_len = sizeof(sig); EVP_PKEY* evp_pubkey = EVP_PKEY_new(); RSA* rsa_pubkey = NULL; EVP_MD_CTX ctx; BIO* bufio = BIO_new_mem_buf((void*)key, key_len); if(bufio == NULL){ fprintf(stderr, "BIO not created.\n"); EVP_PKEY_free(evp_pubkey); BIO_free(bufio); return 3; } evp_pubkey = PEM_read_bio_PUBKEY(bufio, NULL, NULL, NULL); if(evp_pubkey == NULL){ fprintf(stderr, "evp_pubkey not created.\n"); EVP_PKEY_free(evp_pubkey); BIO_free(bufio); return 4; } EVP_MD_CTX_init(&ctx); if (!EVP_VerifyInit(&ctx, EVP_sha256())) { fprintf(stderr, "EVP_SignInit: failed.\n"); EVP_PKEY_free(evp_pubkey); BIO_free(bufio); return 5; } if (!EVP_VerifyUpdate(&ctx, data, data_len)) { fprintf(stderr, "EVP_SignUpdate: failed.\n"); EVP_PKEY_free(evp_pubkey); BIO_free(bufio); return 6; } if (!EVP_VerifyFinal(&ctx, sig, sig_len, evp_pubkey)) { fprintf(stderr, "EVP_VerifyFinal: failed.\n"); EVP_PKEY_free(evp_pubkey); BIO_free(bufio); return 7; } EVP_PKEY_free(evp_pubkey); BIO_free(bufio); return 0; } 

gcc evp.c -lssl -lcrypto编译并运行valgrind --tool=memcheck --leak-check=full ./a.out后,我得到了一些内存泄漏:

 ==7492== 56 bytes in 1 blocks are definitely lost in loss record 9 of 12 ==7492== at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==7492== by 0x4E9AD77: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) ==7492== by 0x4F5D459: EVP_PKEY_new (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) ==7492== by 0x400C4C: main (in a.out) ==7492== ==7492== 120 bytes in 1 blocks are definitely lost in loss record 10 of 12 ==7492== at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==7492== by 0x4E9AD77: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) ==7492== by 0x4F55678: EVP_DigestInit_ex (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) ==7492== by 0x400D6A: main (in a.out) 

难道我做错了什么?

  1. @ iharob在他的回答中写道,

  2. 您使用了EVP_MD_CTX_init()但未使用EVP_MD_CTX_cleanup(&ctx)释放它分配的数据,或者 – 取决于您的openssl版本 – EVP_MD_CTX_free(&ctx)

    如果使用调试信息进行编译(在gcc / clang中使用-g), valgrind会向您显示负责泄漏的源代码行。

  3. 您也可以使用EVP_MD_CTX_create()而不是使用静态EVP_MD_CTX

这是更新的代码:

 #include  #include  #include  #include  int main() { const unsigned char key[] = "-----BEGIN PUBLIC KEY-----\n" "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALulMfYFyX1kSm7oUxZyCWWhrBBcWrRA\n" "V7LSz1PzMPxoxG3KS8H7PRKFkIk42yM8/vhobmcCmj7UM5572wWch50CAwEAAQ==\n" "-----END PUBLIC KEY-----\n"; unsigned int key_len = sizeof(key) - 1; const unsigned char data[] = { 0x6d,0x65,0x73,0x65,0x0a }; unsigned int data_len = sizeof(data); const unsigned char sig[] = { 0xa9,0x29,0x81,0x07,0x8c,0xeb,0xf0,0x1b,0x2a,0x31,0xe5,0x60, 0x94,0x8a,0x47,0x94,0x3a,0x8f,0x6b,0x4e,0x85,0xb8,0xe7,0xe5, 0x4a,0x6c,0x56,0x46,0xd1,0x80,0x15,0x57,0xce,0xcb,0x0a,0x3a, 0x67,0x15,0xed,0x68,0x03,0x58,0x99,0xa4,0x73,0x61,0xe3,0x30, 0x85,0xff,0x89,0x7e,0x32,0xef,0x16,0xec,0x23,0x7f,0x14,0xde, 0xbf,0x53,0xe0,0x3a }; unsigned int sig_len = sizeof(sig); int ret = 0; EVP_PKEY* evp_pubkey = NULL; RSA* rsa_pubkey = NULL; EVP_MD_CTX* evp_ctx; BIO* bufio = NULL; if (!(bufio = BIO_new_mem_buf((void*)key, key_len))) { fprintf(stderr, "BIO not created.\n"); ret = 1; goto out; } if (!(evp_pubkey = PEM_read_bio_PUBKEY(bufio, NULL, NULL, NULL))) { fprintf(stderr, "evp_pubkey not created.\n"); ret = 2; goto out; } if (!(evp_ctx = EVP_MD_CTX_create())) { fprintf(stderr, "ctx not created.\n"); ret = 3; goto out; } if (!EVP_VerifyInit(evp_ctx, EVP_sha256())) { fprintf(stderr, "EVP_SignInit: failed.\n"); ret = 4; goto out; } if (!EVP_VerifyUpdate(evp_ctx, data, data_len)) { fprintf(stderr, "EVP_SignUpdate: failed.\n"); ret = 5; goto out; } if (!EVP_VerifyFinal(evp_ctx, sig, sig_len, evp_pubkey)) { fprintf(stderr, "EVP_VerifyFinal: failed.\n"); ret = 6; goto out; } out: if (evp_ctx) EVP_MD_CTX_destroy(evp_ctx); if (evp_pubkey) EVP_PKEY_free(evp_pubkey); if (bufio) BIO_free(bufio); return 0; } 

你在这里覆盖指针

 evp_pubkey = PEM_read_bio_PUBKEY(bufio, NULL, NULL, NULL); 

所以第一次EVP_PKEY_new()返回的指针的引用会丢失,你不能再释放它了。