【问题标题】:valgrind reports problems with libcurl when using httpsvalgrind 在使用 https 时报告 libcurl 的问题
【发布时间】:2011-06-19 17:27:53
【问题描述】:

所以我有一个通过 https 与 facebook 服务器交谈的非常基本的示例,但 valgrind 遗憾地抱怨。所以我假设我没有设置错误...有人知道我做错了什么吗?

这是我的代码:

#include <string>
#include <iostream>
#include <curl/curl.h>

size_t write_fn_impl( void* ptr, size_t size, size_t nmemb, void * data )
{
  std::string * result = static_cast<std::string*>(data);
  *result += std::string( (char*)ptr, size*nmemb );
  return size*nmemb;
}

int main()
{
  std::string url_full="https://graph.facebook.com/me";
  std::string useragent = "Facebook API C++ Client (curl)";

  CURL * ch_ = curl_easy_init();
  char error_buffer[CURL_ERROR_SIZE];
  curl_easy_setopt( ch_, CURLOPT_ERRORBUFFER, error_buffer );
  curl_easy_setopt( ch_, CURLOPT_WRITEFUNCTION, &write_fn_impl );
  std::string result;
  curl_easy_setopt( ch_, CURLOPT_WRITEDATA, &result );
  int id = 1;
  curl_easy_setopt( ch_, CURLOPT_VERBOSE, id );

  curl_easy_setopt( ch_, CURLOPT_URL, url_full.c_str() );
  curl_easy_setopt( ch_, CURLOPT_USERAGENT, useragent.c_str() );
  curl_easy_setopt( ch_, CURLOPT_CONNECTTIMEOUT, 10);
  curl_easy_setopt( ch_, CURLOPT_TIMEOUT, 30);
  curl_easy_perform(ch_);
  curl_easy_cleanup(ch_);

  std::cout<< result<<std::endl;
}

valgrind 说的是:

==14149== Memcheck, a memory error detector
==14149== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==14149== Using Valgrind-3.5.0-Debian and LibVEX; rerun with -h for copyright info
==14149== Command: ./a.out
==14149== 
* About to connect() to graph.facebook.com port 443 (#0)
*   Trying 66.220.146.47... * connected
* Connected to graph.facebook.com (66.220.146.47) port 443 (#0)
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
==14149== Syscall param write(buf) points to uninitialised byte(s)
==14149==    at 0x4268113: __write_nocancel (in /lib/tls/i686/cmov/libc-2.10.1.so)
==14149==    by 0x44A5A8E: BIO_write (in /lib/i686/cmov/libcrypto.so.0.9.8)
==14149==    by 0x43E49B8: ssl23_write_bytes (in /lib/i686/cmov/libssl.so.0.9.8)
==14149==    by 0x43E39AB: ssl23_connect (in /lib/i686/cmov/libssl.so.0.9.8)
==14149==    by 0x43F0D49: SSL_connect (in /lib/i686/cmov/libssl.so.0.9.8)
==14149==    by 0x4050EB0: ossl_connect_common (in /usr/lib/libcurl.so.4.1.1)
==14149==    by 0x4052202: Curl_ossl_connect (in /usr/lib/libcurl.so.4.1.1)
==14149==    by 0x406597F: Curl_ssl_connect (in /usr/lib/libcurl.so.4.1.1)
==14149==    by 0x403FF1B: Curl_http_connect (in /usr/lib/libcurl.so.4.1.1)
==14149==    by 0x4046F6D: Curl_protocol_connect (in /usr/lib/libcurl.so.4.1.1)
==14149==    by 0x404C396: Curl_connect (in /usr/lib/libcurl.so.4.1.1)
==14149==    by 0x4059B23: Curl_perform (in /usr/lib/libcurl.so.4.1.1)
==14149==  Address 0x47e92df is 15 bytes inside a block of size 21,848 alloc'd
==14149==    at 0x4024C1C: malloc (vg_replace_malloc.c:195)
==14149==    by 0x4446EFD: ??? (in /lib/i686/cmov/libcrypto.so.0.9.8)
==14149==    by 0x444755B: CRYPTO_malloc (in /lib/i686/cmov/libcrypto.so.0.9.8)
==14149==    by 0x44A4EF7: BUF_MEM_grow (in /lib/i686/cmov/libcrypto.so.0.9.8)
==14149==    by 0x43E3BAB: ssl23_connect (in /lib/i686/cmov/libssl.so.0.9.8)
==14149==    by 0x43F0D49: SSL_connect (in /lib/i686/cmov/libssl.so.0.9.8)
==14149==    by 0x4050EB0: ossl_connect_common (in /usr/lib/libcurl.so.4.1.1)
==14149==    by 0x4052202: Curl_ossl_connect (in /usr/lib/libcurl.so.4.1.1)
==14149==    by 0x406597F: Curl_ssl_connect (in /usr/lib/libcurl.so.4.1.1)
==14149==    by 0x403FF1B: Curl_http_connect (in /usr/lib/libcurl.so.4.1.1)
==14149==    by 0x4046F6D: Curl_protocol_connect (in /usr/lib/libcurl.so.4.1.1)
==14149==    by 0x404C396: Curl_connect (in /usr/lib/libcurl.so.4.1.1)

还有更多页面......

【问题讨论】:

    标签: c++ c curl valgrind


    【解决方案1】:

    MK 部分正确。 Valgrind 确实抛出了很多关于 OpenSSL 的垃圾警告。但就我而言,我看到的崩溃似乎是由于我使用 openSSL 的方式出现了一些问题。特别是它没有正确设置为多线程使用。 curl 文档涵盖了您需要做的事情..但不知何故我一定错过了)

    无论如何,这是帮助我找到它的抑制文件..它可能对某人有用..但要注意它可能无法捕获您想要捕获的所有内容,它可能会捕获一些您不想要的东西.. .

    {
       openssl-rand-write 
       Memcheck:Param
       write(buf)
       fun:__write_nocancel
       fun:BIO_write
       fun:ssl23_write_bytes
       fun:ssl23_connect
       fun:SSL_connect
       fun:ossl_connect_common
    }
    {
       openssl-rand-write2
       Memcheck:Param
       write(buf)
       fun:__write_nocancel
       fun:BIO_write
       fun:ssl3_write_pending
       obj:/lib/i686/cmov/libssl.so.0.9.8
       fun:ssl3_write_bytes
       fun:ssl3_write
       fun:SSL_write
    }
    {
       openssl-rand-write3
       Memcheck:Param
       write(buf)
       fun:__write_nocancel
       fun:BIO_write
       ...
       fun:ossl_connect_common
    }
    {
       openssl-rand-uninit_mod_inverse
       Memcheck:Cond
       fun:BN_mod_inverse
       ...
       obj:/lib/i686/cmov/libcrypto.so.0.9.8
    }
    {
       openssl-rand-uninit_div
       Memcheck:Cond
       fun:BN_div
       ...
       obj:/lib/i686/cmov/libcrypto.so.0.9.8
    }
    {
       openssl-uninit-padding
       Memcheck:Cond
       fun:RSA_padding_add_PKCS1_type_2
       obj:/lib/i686/cmov/libcrypto.so.0.9.8
    }
    {
       openssl-uninit-ucmp
       Memcheck:Cond
       fun:BN_ucmp
       obj:/lib/i686/cmov/libcrypto.so.0.9.8
    }
    {
       openssl-uninit-encrypt
       Memcheck:Cond
       obj:/lib/i686/cmov/libcrypto.so.0.9.8
       fun:RSA_public_encrypt
    }
    {
       openssl-uninit-ssl3_read_bytes
       Memcheck:Cond
       fun:ssl3_read_bytes
       fun:ssl3_read
       fun:SSL_read
    }
    {
       openssl-uninit-get_finished
       Memcheck:Cond
       fun:ssl3_get_finished
       fun:ssl3_connect
       fun:SSL_connect
       fun:ossl_connect_common
    }
    {
       openssl-uninit-read_bytes
       Memcheck:Cond
       ...
       fun:ossl_connect_common
    }
    {
       openssl-value4-connect_common
       Memcheck:Value4
       ...
       fun:ossl_connect_common
    }
    {
       openssl-uninit-encrypt
       Memcheck:Cond
       ...      
       fun:RSA_public_encrypt
    }
    

    【讨论】:

      【解决方案2】:

      上次有人试图确保 OpenSSL 在 valgrind 下运行干净时发生了坏事(tm): http://blogs.fsfe.org/tonnerre/archives/24

      所以我会忽略任何关于 OpenSSL 的 vlagrind 警告。

      【讨论】:

      • 那篇文章很有趣,但它忽略了 valgrind 确实在 OpenSSL 中发现了一个错误这一事实。 OpenSSL 曾经(并且可能仍然是)依赖 未定义的行为 作为熵的来源,而不是从合法来源获取熵。 Debian 添加的相同“错误”很容易出现在编译器或库更改中,这些更改使 OpenSSL 读取的未初始化数据“更少随机”。简而言之,如果 valgrind 报告了这样的问题,那几乎肯定意味着代码错误,但微不足道的修复可能会更糟。 :-)
      • @R 我不记得细节,但我认为你的解释有点不对劲。我的回忆是他们没有依赖未初始化的内存,而是修复意外删除了一些其他“真实”熵源。我的记忆很模糊......但底线仍然存在:不要乱用 OpenSSL。
      • @MK:从文章来看,这个问题更多地与开发人员尝试“有根据的猜测”修复有关。如果该库带有一个适当的 valgrind 抑制文件,表明这是预期的行为(或代码中的注释),或者如果开发人员已经与 OpenSSL 开发人员检查了“错误”并征求他们的建议,那么就不会有任何问题。故事的精神:修复错误不仅仅需要一个工具......但我们不都知道吗?
      • @Matthieu 哦,还有更多的戏剧性。开发人员确实提出了这个问题,但没有说明它的重要性(他是 Dabian 打包者!),他确实得到了某种半途而废的回应,说没关系。我认为这需要成为 CS 课程的一部分,如此美丽的失败。
      • 请注意...为其中的某些内容构建您自己的抑制文件是值得的。在我从 valgrind .. 抑制了足够的警告 \s 之后(都与来自 CRYPTO_malloc 或类似的东西的未初始化的再见有关)我最终发现 OpenSSL 没有为多线程使用正确初始化。修复了这个问题,崩溃似乎已经消失了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-01
      • 2012-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-25
      相关资源
      最近更新 更多