From: Sriram Natarajan Date: Tue, 21 Jul 2009 20:32:32 +0000 (+0000) Subject: - Fixed bug #48774 (SIGSEGVs when using curl_copy_handle()). X-Git-Tag: php-5.4.0alpha1~191^2~3023 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=38916290fff746fe7672778267584a787d4bc084;p=php - Fixed bug #48774 (SIGSEGVs when using curl_copy_handle()). --- diff --git a/NEWS b/NEWS index e7387d4788..60da3f5a1a 100644 --- a/NEWS +++ b/NEWS @@ -48,3 +48,4 @@ PHP NEWS - Fixed bug #46647 (SplFileObject::fgetcsv segfaults). (Etienne) - Fixed bug #40325 (Vary: header missing in gzip output handlers). (Mike) +- Fixed bug #48774 (SIGSEGVs when using curl_copy_handle()). (Sriram Natarajan) diff --git a/ext/curl/interface.c b/ext/curl/interface.c index eef4db2a0e..220d5892e0 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -1334,6 +1334,7 @@ PHP_FUNCTION(curl_init) { php_curl *ch; CURL *cp; + zval *clone; zstr url = NULL_ZSTR; int url_len = 0; zend_uchar url_type = 0; @@ -1368,6 +1369,9 @@ PHP_FUNCTION(curl_init) ch->uses = 0; + MAKE_STD_ZVAL(clone); + ch->clone = clone; + curl_easy_setopt(ch->cp, CURLOPT_NOPROGRESS, 1); curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0); curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER, ch->err.str); @@ -1467,6 +1471,10 @@ PHP_FUNCTION(curl_copy_handle) zend_llist_copy(&dupch->to_free.slist, &ch->to_free.slist); zend_llist_copy(&dupch->to_free.post, &ch->to_free.post); + /* Keep track of cloned copies to avoid invoking curl destructors for every clone */ + Z_ADDREF_P(ch->clone); + dupch->clone = ch->clone; + ZEND_REGISTER_RESOURCE(return_value, dupch, le_curl); dupch->id = Z_LVAL_P(return_value); } @@ -2364,8 +2372,19 @@ static void _php_curl_close_ex(php_curl *ch TSRMLS_DC) #if LIBCURL_VERSION_NUM < 0x071101 zend_llist_clean(&ch->to_free.str); #endif - zend_llist_clean(&ch->to_free.slist); - zend_llist_clean(&ch->to_free.post); + + /* cURL destructors should be invoked only by last curl handle */ + if (Z_REFCOUNT_P(ch->clone) <= 1) { + zend_llist_clean(&ch->to_free.slist); + zend_llist_clean(&ch->to_free.post); + zval_ptr_dtor(&ch->clone); + } else { + Z_DELREF_P(ch->clone); + ch->to_free.slist.dtor = NULL; + ch->to_free.post.dtor = NULL; + zend_llist_clean(&ch->to_free.slist); + zend_llist_clean(&ch->to_free.post); + } if (ch->handlers->write->buf.len > 0) { smart_str_free(&ch->handlers->write->buf); diff --git a/ext/curl/php_curl.h b/ext/curl/php_curl.h index e85fa4df25..3063d8b42d 100644 --- a/ext/curl/php_curl.h +++ b/ext/curl/php_curl.h @@ -139,6 +139,7 @@ typedef struct { long id; unsigned int uses; zend_bool in_callback; + zval *clone; } php_curl; typedef struct { diff --git a/ext/curl/tests/curl_copy_handle_basic_007.phpt b/ext/curl/tests/curl_copy_handle_basic_007.phpt new file mode 100644 index 0000000000..5be9048af6 --- /dev/null +++ b/ext/curl/tests/curl_copy_handle_basic_007.phpt @@ -0,0 +1,44 @@ +--TEST-- +Test curl_copy_handle() with simple POST +--SKIPIF-- + +--FILE-- + "World", "Foo" => "Bar", "Person" => "John Doe")); + curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use + + $copy = curl_copy_handle($ch); + curl_close($ch); + + $curl_content = curl_exec($copy); + curl_close($copy); + + var_dump( $curl_content ); +?> +===DONE=== +--EXPECTF-- +*** Testing curl copy handle with simple POST using array as arguments *** +string(163) "array(1) { + ["test"]=> + string(7) "getpost" +} +array(3) { + ["Hello"]=> + string(5) "World" + ["Foo"]=> + string(3) "Bar" + ["Person"]=> + string(8) "John Doe" +} +" +===DONE===