Skip to content

Bad HTTP response causing 'double free detected in tcache 2' #11101

Closed
@twrecked

Description

@twrecked

I did this

I have an old device I need to support that returns badly formatted HTTP responses for certain requests. I noticed that if I reuse a handle I get a SIGABRT in curl_dbg_realloc.

I managed to reproduce it with the following code:

#include <curl/curl.h>

int
main(int argc, char** argv)
{
	CURL* cl = curl_easy_init();
	curl_easy_setopt(cl, CURLOPT_URL, "https://google.com");
	curl_easy_perform(cl);

	curl_easy_setopt(cl, CURLOPT_URL, "http://127.0.0.1:12000");
	curl_easy_perform(cl);
	return 0;
}

And using the following badly formed header:

HTTP/1.1 200 OK
	Access-Control-Allow-Origin: *
	Connection: Keep-Alive
	Content-Type: text/html; charset=utf-8
Date: Wed, 10 May 2023 14:58:08 GMT

<!DOCTYPE html>
<html lang=\en\></html>

Which I serve with cat index.html | nc -l -C 12000.

The error I'm seeing is

free(): double free detected in tcache 2
Aborted (core dumped)

And the back trace shows

#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:49
#1  0x00007ffff7735086 in __GI_abort () at abort.c:79
#2  0x00007ffff778cb80 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff789a845 "%s\n")
    at ../sysdeps/posix/libc_fatal.c:155
#3  0x00007ffff779454a in malloc_printerr (str=str@entry=0x7ffff789cc58 "free(): double free detected in tcache 2") at malloc.c:5389
#4  0x00007ffff779681a in _int_free (av=av@entry=0x7ffff7ad2bc0 <main_arena>, p=p@entry=0x636db0, have_lock=have_lock@entry=1) at malloc.c:4232
#5  0x00007ffff7798845 in _int_realloc (av=av@entry=0x7ffff7ad2bc0 <main_arena>, oldp=oldp@entry=0x636db0, oldsize=oldsize@entry=128, nb=160)
    at malloc.c:4655
#6  0x00007ffff77999f6 in __GI___libc_realloc (oldmem=0x636dc0, bytes=152) at malloc.c:3255
#7  0x00007ffff7b3403d in curl_dbg_realloc (ptr=0x636dc8, wantedsize=136, line=118, source=0x7ffff7b973c0 "strdup.c") at memdebug.c:265
#8  0x00007ffff7b60bcc in Curl_saferealloc (ptr=0x636dc8, size=136) at strdup.c:118
#9  0x00007ffff7b170eb in unfold_value (data=0x623f38, value=0x636888 "\tAccess-Control-Allow-Origin: *\n", vlen=31) at headers.c:252
#10 0x00007ffff7b1727e in Curl_headers_push (data=0x623f38, header=0x636888 "\tAccess-Control-Allow-Origin: *\n", type=1 '\001')
    at headers.c:302
#11 0x00007ffff7b4c934 in chop_write (data=0x623f38, type=2, optr=0x636888 "\tAccess-Control-Allow-Origin: *\n", olen=32) at sendf.c:332
#12 0x00007ffff7b4ca75 in Curl_client_write (data=0x623f38, type=2, ptr=0x636888 "\tAccess-Control-Allow-Origin: *\n", len=32) at sendf.c:386
#13 0x00007ffff7b234be in Curl_http_readwrite_headers (data=0x623f38, conn=0x637258, nread=0x7fffffffd898, stop_reading=0x7fffffffd896)
    at http.c:4328
#14 0x00007ffff7b682fb in readwrite_data (data=0x623f38, conn=0x637258, k=0x624008, didwhat=0x7fffffffd94c, done=0x7fffffffd9f3, 
    comeback=0x7fffffffd9c7) at transfer.c:522
#15 0x00007ffff7b696c0 in Curl_readwrite (conn=0x637258, data=0x623f38, done=0x7fffffffd9f3, comeback=0x7fffffffd9c7) at transfer.c:1119
#16 0x00007ffff7b40461 in multi_runsingle (multi=0x623c18, nowp=0x7fffffffdb20, data=0x623f38) at multi.c:2443
#17 0x00007ffff7b40d9f in curl_multi_perform (multi=0x623c18, running_handles=0x7fffffffdb74) at multi.c:2729
#18 0x00007ffff7b04554 in easy_transfer (multi=0x623c18) at easy.c:668
#19 0x00007ffff7b04785 in easy_perform (data=0x623f38, events=false) at easy.c:758
#20 0x00007ffff7b047cf in curl_easy_perform (data=0x623f38) at easy.c:777
#21 0x0000000000400778 in main (argc=1, argv=0x7fffffffdda8) at test.c:24

A couple of things:

  • is reusing the handle valid?
  • if you comment out the request to Google it works fine, you need the good response before the bad one

I expected the following

When I use a valid response I see the following:

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="https://www.google.com/">here</A>.
</BODY></HTML>
<!DOCTYPE html>
<html lang=\en\></html>

curl/libcurl version

curl 8.0.1 (x86_64-pc-linux-gnu) libcurl/8.0.1 OpenSSL/3.0.2 zlib/1.2.11 brotli/1.0.9 libidn2/2.3.2 libpsl/0.21.0 (+libidn2/2.3.2)
Release-Date: 2023-03-20
Protocols: dict file ftp ftps gopher gophers http https imap imaps mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS brotli Debug HSTS HTTPS-proxy IDN IPv6 Largefile libz NTLM NTLM_WB PSL SSL threadsafe TLS-SRP TrackMemory UnixSockets

Note, 7.81.0 curl shows no such issue.

operating system

Linux skippy 5.15.0-71-generic #78-Ubuntu SMP Tue Apr 18 09:00:29 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

Thanks for reading, if I haven't provided enough information let me know.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions