BIO_dump_fp 导致数百个 valgrind 错误

BIO_dump_fp causing hundreds of valgrind errors

我正在尝试使用 OpenSSL 库进行 AES 加密。一切都编译并且似乎工作正常。但是,当我使用 BIO_dump_fp(stdout, (char*)ciphertext, ciphertext_len) valgrind 时,最终会报告数百个错误,大部分是 "conditional jump of move depends on uninitialized value(s)" 错误,例如:

Conditional jump or move depends on uninitialised value(s)
    at 0x579A9C3: fwrite (iofwrite.c:49)
    by 0x4F187B0: ??? (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
    by 0x4F18AC4: BIO_dump_indent_cb (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
    by 0x401748: main (in /home/van/Desktop/aes-test/temp/test)

是否可以安全地忽略这些错误(即这些误报)?如果重要的话,我正在使用 Ubuntu 14.04,g++ 版本 4.8.2,valgrind 3.10。

更新:我的完整源代码如下:

#include <stdio.h>

#include "QAesHelper.h"

int main(int argc, char *argv[])
{
  unsigned char iv[] = "1234567812345678";
  unsigned char key[] = "Testing Testing...";
  printf("Size of key: %d\n", (int)sizeof(key));

  unsigned char plaintext[] = "The quick brown fox jumps over the lazy dog";
  int plaintext_len = sizeof(plaintext);
  printf("Size of plaintext: %d\n", plaintext_len);
  unsigned char *ciphertext = (unsigned char*)malloc(plaintext_len + 32);
  unsigned char *decryptedtext = (unsigned char*)malloc(plaintext_len + 2);

  QAesHelper *aesHelper = new QAesHelper(key, sizeof(key));
  int ciphertext_len = aesHelper->encrypt(plaintext, plaintext_len, iv, sizeof(iv), &ciphertext);
  int decryptedtext_len = aesHelper->decrypt(ciphertext, ciphertext_len + 1, iv, sizeof(iv), &decryptedtext);
  // If I remove the following line (BIO_dump_fp...), then
  // valgrind reports no errors. With this line left in, there
  // are over 900 errors reported.
  BIO_dump_fp(stdout, (char*)ciphertext, ciphertext_len);
  delete aesHelper;

  free(ciphertext);
  free(decryptedtext);

  return 0;
}

而 QAesHelper::encrypt() 是:

int QAesHelper::encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *iv, int iv_len, unsigned char **ciphertext)
{
  EVP_CIPHER_CTX *ctx;

  int len;
  int ciphertext_len;

  if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();

  if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
    handleErrors();

  if(1 != EVP_EncryptUpdate(ctx, *ciphertext, &len, plaintext, plaintext_len))
    handleErrors();
  ciphertext_len = len;

  if(1 != EVP_EncryptFinal_ex(ctx, *ciphertext + len, &len)) handleErrors();
  ciphertext_len += len;

  EVP_CIPHER_CTX_free(ctx);

  return ciphertext_len;
}

这不是错误。 OpenSSL 大量使用未初始化的内存段。 Valgrind 将此类用法视为错误并发出警告。它的正常行为可以在一定程度上美化:

  • 编写并使用 valgrind 抑制文件 valgrind --gen-suppressions=no|yes|all
  • 在 cflags 中启用 PURIFY 宏编译 openssl
  • 推送到 valgrind --error-limit=no 并忽略来自 libssl/libcrypto
  • 的警告