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
 [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

Add a Patch

Pull Requests

Add a Pull Request

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-2024 The PHP Group
All rights reserved.
Last updated: Tue Mar 19 03:01:29 2024 UTC