Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

memory leak after using curl_easy_duphandled() #5665

Closed
NobodyXu opened this issue Jul 9, 2020 · 1 comment
Closed

memory leak after using curl_easy_duphandled() #5665

NobodyXu opened this issue Jul 9, 2020 · 1 comment

Comments

@NobodyXu
Copy link

NobodyXu commented Jul 9, 2020

I did this

I compiled the following code with clang++ -std=c++17 libcurl_bug.cc -lcurl -g -fsanitize=address -o libcurl_bug:

#include <curl/curl.h>
#include <memory>

#include <err.h>
#include <cassert>

class Curl_global {
public:
    Curl_global() noexcept
    {
        auto code = curl_global_init(CURL_GLOBAL_ALL);
        if (code != CURLE_OK)
            errx(1, "curl_global_init(CURL_GLOBAL_ALL) failed with %s", curl_easy_strerror(code));
    }

    ~Curl_global()
    {
        curl_global_cleanup();
    }
};

long get_response_code(CURL *easy) noexcept
{
    long response_code;
    curl_easy_getinfo(easy, CURLINFO_RESPONSE_CODE, &response_code);
    return response_code;
}

int main(int argc, char* argv[])
{
    Curl_global curl_global{};

    auto url = std::unique_ptr<CURLU, void (*)(CURLU*)>{curl_url(), curl_url_cleanup};
    assert(url.get());
    assert(curl_url_set(url.get(), CURLUPART_URL, "http://en.cppreference.com/", 0) == CURLUE_OK);

    auto easy1 = std::unique_ptr<CURL, void (*)(CURL*)>{curl_easy_init(), curl_easy_cleanup};
    assert(easy1.get());

    assert(curl_easy_setopt(easy1.get(), CURLOPT_CURLU, url.get()) == CURLE_OK);

    assert(curl_easy_perform(easy1.get()) == CURLE_OK);
    assert(get_response_code(easy1.get()) == 302L);

    auto easy2 = std::unique_ptr<CURL, void (*)(CURL*)>{curl_easy_duphandle(easy1.get()), curl_easy_cleanup};
    assert(easy2.get());

    assert(curl_easy_perform(easy2.get()) == CURLE_OK);
    assert(get_response_code(easy2.get()) == 302L);

    return 0;
}

and here's the output:

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved <a href="https://en.cppreference.com/">here</a>.</p>
</body></html>
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved <a href="https://en.cppreference.com/">here</a>.</p>
</body></html>

=================================================================
==60998==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 28 byte(s) in 1 object(s) allocated from:
    #0 0x480ee4 in strdup (/home/nobodyxu/libcurl_bug+0x480ee4)
    #1 0x7ff0330f39c5  (/lib/x86_64-linux-gnu/libcurl.so.4+0x589c5)

SUMMARY: AddressSanitizer: 28 byte(s) leaked in 1 allocation(s).

which shows that libcurl internally leaked 28 bytes.

I expected the following

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved <a href="https://en.cppreference.com/">here</a>.</p>
</body></html>
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved <a href="https://en.cppreference.com/">here</a>.</p>
</body></html>

curl/libcurl version

curl 7.68.0 (x86_64-pc-linux-gnu) libcurl/7.68.0 OpenSSL/1.1.1f zlib/1.2.11 brotli/1.0.7 libidn2/2.2.0 libpsl/0.21.0 (+libidn2/2.2.0) libssh/0.9.3/openssl/zlib nghttp2/1.40.0 librtmp/2.3
Release-Date: 2020-01-08
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: AsynchDNS brotli GSS-API HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM NTLM_WB PSL SPNEGO SSL TLS-SRP UnixSockets

ldd /usr/lib/x86_64-linux-gnu/libcurl.so.4 gives me:

        linux-vdso.so.1 (0x00007ffdcc5e1000)
        libnghttp2.so.14 => /lib/x86_64-linux-gnu/libnghttp2.so.14 (0x00007f14b2f6c000)
        libidn2.so.0 => /lib/x86_64-linux-gnu/libidn2.so.0 (0x00007f14b2f4b000)
        librtmp.so.1 => /lib/x86_64-linux-gnu/librtmp.so.1 (0x00007f14b2f2b000)
        libssh.so.4 => /lib/x86_64-linux-gnu/libssh.so.4 (0x00007f14b2ebd000)
        libpsl.so.5 => /lib/x86_64-linux-gnu/libpsl.so.5 (0x00007f14b2eaa000)
        libssl.so.1.1 => /lib/x86_64-linux-gnu/libssl.so.1.1 (0x00007f14b2e17000)
        libcrypto.so.1.1 => /lib/x86_64-linux-gnu/libcrypto.so.1.1 (0x00007f14b2b3f000)
        libgssapi_krb5.so.2 => /lib/x86_64-linux-gnu/libgssapi_krb5.so.2 (0x00007f14b2af2000)
        libldap_r-2.4.so.2 => /lib/x86_64-linux-gnu/libldap_r-2.4.so.2 (0x00007f14b2a9c000)
        liblber-2.4.so.2 => /lib/x86_64-linux-gnu/liblber-2.4.so.2 (0x00007f14b2a8b000)
        libbrotlidec.so.1 => /lib/x86_64-linux-gnu/libbrotlidec.so.1 (0x00007f14b2a7c000)
        libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f14b2a60000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f14b2a3b000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f14b2849000)
        libunistring.so.2 => /lib/x86_64-linux-gnu/libunistring.so.2 (0x00007f14b26c7000)
        libgnutls.so.30 => /lib/x86_64-linux-gnu/libgnutls.so.30 (0x00007f14b24f1000)
        libhogweed.so.5 => /lib/x86_64-linux-gnu/libhogweed.so.5 (0x00007f14b24b9000)
        libnettle.so.7 => /lib/x86_64-linux-gnu/libnettle.so.7 (0x00007f14b247f000)
        libgmp.so.10 => /lib/x86_64-linux-gnu/libgmp.so.10 (0x00007f14b23f9000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f14b304a000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f14b23f3000)
        libkrb5.so.3 => /lib/x86_64-linux-gnu/libkrb5.so.3 (0x00007f14b2316000)
        libk5crypto.so.3 => /lib/x86_64-linux-gnu/libk5crypto.so.3 (0x00007f14b22e5000)
        libcom_err.so.2 => /lib/x86_64-linux-gnu/libcom_err.so.2 (0x00007f14b22de000)
        libkrb5support.so.0 => /lib/x86_64-linux-gnu/libkrb5support.so.0 (0x00007f14b22cd000)
        libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f14b22b1000)
        libsasl2.so.2 => /lib/x86_64-linux-gnu/libsasl2.so.2 (0x00007f14b2294000)
        libgssapi.so.3 => /lib/x86_64-linux-gnu/libgssapi.so.3 (0x00007f14b224f000)
        libbrotlicommon.so.1 => /lib/x86_64-linux-gnu/libbrotlicommon.so.1 (0x00007f14b222c000)
        libp11-kit.so.0 => /lib/x86_64-linux-gnu/libp11-kit.so.0 (0x00007f14b20f6000)
        libtasn1.so.6 => /lib/x86_64-linux-gnu/libtasn1.so.6 (0x00007f14b20de000)
        libkeyutils.so.1 => /lib/x86_64-linux-gnu/libkeyutils.so.1 (0x00007f14b20d7000)
        libheimntlm.so.0 => /lib/x86_64-linux-gnu/libheimntlm.so.0 (0x00007f14b20cb000)
        libkrb5.so.26 => /lib/x86_64-linux-gnu/libkrb5.so.26 (0x00007f14b2038000)
        libasn1.so.8 => /lib/x86_64-linux-gnu/libasn1.so.8 (0x00007f14b1f91000)
        libhcrypto.so.4 => /lib/x86_64-linux-gnu/libhcrypto.so.4 (0x00007f14b1f57000)
        libroken.so.18 => /lib/x86_64-linux-gnu/libroken.so.18 (0x00007f14b1f3e000)
        libffi.so.7 => /lib/x86_64-linux-gnu/libffi.so.7 (0x00007f14b1f32000)
        libwind.so.0 => /lib/x86_64-linux-gnu/libwind.so.0 (0x00007f14b1f08000)
        libheimbase.so.1 => /lib/x86_64-linux-gnu/libheimbase.so.1 (0x00007f14b1ef6000)
        libhx509.so.5 => /lib/x86_64-linux-gnu/libhx509.so.5 (0x00007f14b1ea6000)
        libsqlite3.so.0 => /lib/x86_64-linux-gnu/libsqlite3.so.0 (0x00007f14b1d7d000)
        libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007f14b1d42000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f14b1bf3000)

The libcurl I am using is installed from pop!_os official apt source:

curl/focal-security,focal-updates,now 7.68.0-1ubuntu2.1 amd64 [installed]
libcurl4-doc/focal-security,focal-security,focal-updates,focal-updates,now 7.68.0-1ubuntu2.1 all [installed]
libcurl4-openssl-dev/focal-security,focal-updates,now 7.68.0-1ubuntu2.1 amd64 [installed]
libcurl4/focal-security,focal-updates,now 7.68.0-1ubuntu2.1 amd64 [installed,automatic]

operating system

NAME="Pop!_OS"
VERSION="20.04 LTS"
ID=pop
ID_LIKE="ubuntu debian"
PRETTY_NAME="Pop!_OS 20.04 LTS"
VERSION_ID="20.04"
HOME_URL="https://pop.system76.com"
SUPPORT_URL="https://support.system76.com"
BUG_REPORT_URL="https://github.com/pop-os/pop/issues"
PRIVACY_POLICY_URL="https://system76.com/privacy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
LOGO=distributor-logo-pop-os
Linux pop-os 5.4.0-7634-generic #38~1592497129~20.04~9a1ea2e-Ubuntu SMP Fri Jun 19 22:43:37 UTC  x86_64 x86_64 x86_64 GNU/Linux
@bagder
Copy link
Member

bagder commented Jul 11, 2020

I can reproduce this on current master.

bagder added a commit that referenced this issue Jul 11, 2020
Added test case 674 to reproduce and verify the bug report.

Fixes #5665
Reported-by: NobodyXu
@bagder bagder closed this as completed in 9466034 Jul 12, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

2 participants