php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #46756 curl_copy_handle crashes with curl_multi
Submitted: 2008-12-05 06:11 UTC Modified: 2008-12-12 04:42 UTC
From: kyle at ifixit dot com Assigned:
Status: Closed Package: cURL related
PHP Version: 5CVS, 6CVS (2008-12-08) OS: *
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: kyle at ifixit dot com
New email:
PHP Version: OS:

 

 [2008-12-05 06:11 UTC] kyle at ifixit dot com
Description:
------------
Multicurl crashes when using curl_copy_handle. Setup a multi request 
(A), copy the handlers, perform the first multi request (A) and clean it 
up, then perform a second request (B) with the copied handlers. PHP 
segfaults (a double free) on one of the handler close calls. 

If I don't manually free the multihandle, then the segfault is delayed 
until PHP cleans up the objects.

Reproduce code:
---------------
<?
$count = 3;
$mh = curl_multi_init();
$mh2 = curl_multi_init();
$conn = array();
$conn2 = array();

// Setup requests                                                               
for ($i = 0; $i < $count; $i++) {
   $ch = curl_init();
   curl_setopt($ch, CURLOPT_URL, 'http://www.google.com/');
   curl_setopt($ch, CURLOPT_TIMEOUT, 1);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
   $conn[$i] = $ch;
   curl_multi_add_handle($mh, $ch);
}

// Perform first set of requests                                                
do {
   do {
   } while (curl_multi_exec($mh, $stillRunning) ===
    CURLM_CALL_MULTI_PERFORM);
 } while ($stillRunning);
for ($i = 0; $i < $count; $i++) {
   // Copy the completed handlers                                               
   $conn2[$i] = curl_copy_handle($conn[$i]);
   curl_multi_add_handle($mh2, $conn2[$i]);

   // Remove the handlers from the first multihandler                           
   curl_multi_remove_handle($mh, $conn[$i]);
   curl_close($conn[$i]);
}

curl_multi_close($mh);

echo "Initial requests Finished.\n";

// Perform the second set of requests                                           
do {
   do {
   } while (curl_multi_exec($mh2, $stillRunning) ===
    CURLM_CALL_MULTI_PERFORM);
 } while ($stillRunning);

// Remove the second set of completed handlers                                  
for ($i = 0; $i < $count; $i++) {
   curl_multi_remove_handle($mh2, $conn2[$i]);
   curl_close($conn2[$i]);
}

curl_multi_close($mh2);
echo "Copied requests finished.\n";

?>



Expected result:
----------------
Initial requests Finished.
Copied requests finished.






Actual result:
--------------
*** glibc detected *** php: double free or corruption (out): 
0x0000000011e59630 ***
======= Backtrace: =========
/lib64/libc.so.6[0x35a906f4f4]
/lib64/libc.so.6(cfree+0x8c)[0x35a9072b1c]
/usr/local/lib/libcurl.so.4(curl_slist_free_all+0x23)[0x2aaaabeff893]
php[0x4bd7ee]
php(zend_llist_destroy+0x43)[0x83eb3c]
php(zend_llist_clean+0x15)[0x83eba5]
php[0x4c2094]
php(list_entry_destructor+0x87)[0x85cd84]
php(zend_hash_del_key_or_index+0x218)[0x859e8e]
php(_zend_list_delete+0x69)[0x85c851]
php(_zval_dtor_func+0x142)[0x84934a]
php[0x839385]
php(_zval_ptr_dtor+0x49)[0x8395f2]
php(_zval_ptr_dtor_wrapper+0x21)[0x8496f2]
php(zend_hash_destroy+0x70)[0x859fe1]
php(_zval_dtor_func+0xfb)[0x849303]
php[0x839385]
php(_zval_ptr_dtor+0x49)[0x8395f2]
php(_zval_ptr_dtor_wrapper+0x21)[0x8496f2]
php(zend_hash_clean+0x70)[0x85a133]
php[0x876e58]
php[0x87796d]
php(execute+0x2f4)[0x8764e8]
php[0x876c7c]
php[0x87796d]
php(execute+0x2f4)[0x8764e8]
php[0x876c7c]
php[0x87796d]
php(execute+0x2f4)[0x8764e8]
php[0x876c7c]
php[0x87796d]
php(execute+0x2f4)[0x8764e8]
php[0x876c7c]
php[0x87796d]
php(execute+0x2f4)[0x8764e8]
php[0x876c7c]
php[0x87796d]
php(execute+0x2f4)[0x8764e8]
php(zend_execute_scripts+0x290)[0x84be45]
php(php_execute_script+0x38e)[0x7eb4f4]
php(main+0x143e)[0x8e43d5]
/lib64/libc.so.6(__libc_start_main+0xf4)[0x35a901d8a4]
php[0x474859]






Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-12-06 15:52 UTC] crrodriguez at opensuse dot org
VERIFIED, but it is curl_multi_exec() that crashes.
 [2008-12-07 09:54 UTC] kalle@php.net
I cannot reproduce this on PHP 5.2.7 using Windows Vista
 [2008-12-07 16:45 UTC] kyle at ifixit dot com
Reproducible using libcurl/7.19.2 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5 
on kernel 2.6.18-53.1.14.el5. This is not a new bug-- also reproducible 
with PHP 5.2.6 and an older version of libcurl.
 [2008-12-08 11:33 UTC] jani@php.net
Verified with latest CVS + Curl 7.18.2
 [2008-12-10 19:32 UTC] magicaltux@php.net
I checked the origin of the crash, and it seems that libcurl does NOT behave good if you duplicate a handle while it's part of a curl_multi.

Calling curl_multi_remove_handle($mh, $conn[$i]); before $conn2[$i] = curl_copy_handle($conn[$i]); fixes the issue.

Checking curl's documentation, I found it to be quite picky about processing order. I believe this is either a bug in libcurl, or a "feature".

libcurl's manpages are not providing exact informations about calling curl_easy_duphandle() on a curl handle part of a curl_multi.

I'm going to investigate this more and either fix this bug (by providing a patch) or mark it as bogus (if this is a curl feature).
 [2008-12-11 07:18 UTC] magicaltux@php.net
This bug has been reproduced without PHP by reproducing the same sequence in C.

$ svn co http://ookoo.org/svn/snip/curl_bug
...
$ cd curl_bug
$ make
...
$ gdb ./curl_bug 
...
#0  0x00007f81692626c9 in ?? () from /usr/lib/libcurl.so.4
#1  0x00007f8169263ec4 in ?? () from /usr/lib/libcurl.so.4
#2  0x00007f816926444c in Curl_connect () from /usr/lib/libcurl.so.4
#3  0x00007f81692721ba in ?? () from /usr/lib/libcurl.so.4
#4  0x00007f8169272a6e in curl_multi_perform () from /usr/lib/libcurl.so.4
#5  0x0000000000400b34 in main (argc=1, argv=0x7fff716a14d8) at test.c:36

I'll build latest curl with debug mode, check if this can be reproduced, and if so, I'll open a but on libcurl providing more debug informations.
 [2008-12-11 07:56 UTC] magicaltux@php.net
Confirmed against curl 7.19.2 and more debug data posted to libcurl's bug tracker.

https://sourceforge.net/tracker/index.php?func=detail&aid=2416182&group_id=976&atid=100976
 [2008-12-12 04:42 UTC] magicaltux@php.net
This bug has been fixed in libcurl's CVS.

Snapshots of libcurl's sources are packaged every day; this change
will be in the next snapshot. You can grab the snapshot at
http://cool.haxx.se/curl-daily/.
 
Thank you for the report, and for helping us make libcurl and PHP better.
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Wed Jan 15 17:01:31 2025 UTC