]> granicus.if.org Git - php/commitdiff
Fixed bug #70330 (Segmentation Fault with multiple "curl_copy_handle")
authorXinchen Hui <laruence@php.net>
Sun, 23 Aug 2015 05:01:47 +0000 (13:01 +0800)
committerXinchen Hui <laruence@php.net>
Sun, 23 Aug 2015 05:01:47 +0000 (13:01 +0800)
NEWS
ext/curl/interface.c
ext/curl/php_curl.h
ext/curl/tests/bug70330.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index d401f5f5621d2ba1b963884ca9c79b235bf99a4c..51006c318516dc668b62af563bc56f3a28813da0 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,10 @@ PHP                                                                        NEWS
   . Fixed bug #70145 (From field incorrectly parsed from headers). (Anatol)
   . Fixed bug causing exception traces with anon classes to be truncated. (Bob)
 
+- Curl:
+  . Fixed bug #70330 (Segmentation Fault with multiple "curl_copy_handle").
+    (Laruence)
+
 - PDO_OCI:
   . Fixed bug #70308 (PDO::ATTR_PREFETCH is ignored). (Chris Jones)
 
index 32ec54278f57d6c2d8533dabc9c208696a76e5d8..5081127649665998b75e8752ac40b5c293870f99 100644 (file)
@@ -1739,7 +1739,8 @@ static php_curl *alloc_curl_handle()
 #if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
        ch->handlers->fnmatch      = NULL;
 #endif
-       ch->clone                                  = 1;
+       ch->clone                                  = emalloc(sizeof(uint32_t));
+       *ch->clone                 = 1;
 
        memset(&ch->err, 0, sizeof(struct _php_curl_error));
 
@@ -1994,9 +1995,11 @@ PHP_FUNCTION(curl_copy_handle)
        efree(dupch->to_free->slist);
        efree(dupch->to_free);
        dupch->to_free = ch->to_free;
+       efree(dupch->clone);
+       dupch->clone = ch->clone;
 
        /* Keep track of cloned copies to avoid invoking curl destructors for every clone */
-       ch->clone++;
+       (*ch->clone)++;
 
        ZVAL_RES(return_value, zend_register_resource(dupch, le_curl));
        dupch->res = Z_RES_P(return_value);
@@ -2580,7 +2583,7 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{
                                        return FAILURE;
                                }
 
-                               if (ch->clone == 0) {
+                               if ((*ch->clone) == 1) {
                                        zend_llist_clean(&ch->to_free->post);
                                }
                                zend_llist_add_element(&ch->to_free->post, &first);
@@ -3190,12 +3193,13 @@ static void _php_curl_close_ex(php_curl *ch)
        curl_easy_cleanup(ch->cp);
 
        /* cURL destructors should be invoked only by last curl handle */
-       if (--ch->clone == 0) {
+       if (--(*ch->clone) == 0) {
                zend_llist_clean(&ch->to_free->str);
                zend_llist_clean(&ch->to_free->post);
                zend_hash_destroy(ch->to_free->slist);
                efree(ch->to_free->slist);
                efree(ch->to_free);
+               efree(ch->clone);
        }
 
        smart_str_free(&ch->handlers->write->buf);
index b3853ef6fd213a2384c2471ecee4d0c9fc1eebed..50651340e73078d41ee043a9f0df5b8c723d9918 100644 (file)
@@ -181,7 +181,7 @@ typedef struct {
        struct _php_curl_send_headers header;
        struct _php_curl_error        err;
        zend_bool                     in_callback;
-       uint32_t                      clone;
+       uint32_t*                     clone;
 } php_curl;
 
 #define CURLOPT_SAFE_UPLOAD -1
diff --git a/ext/curl/tests/bug70330.phpt b/ext/curl/tests/bug70330.phpt
new file mode 100644 (file)
index 0000000..570a451
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Bug #70330 (Segmentation Fault with multiple "curl_copy_handle")
+--SKIPIF--
+<?php include 'skipif.inc'; ?>
+--FILE--
+<?php
+$t2 = curl_init();
+$t3 = curl_copy_handle($t2);
+$t3 = curl_copy_handle($t2);
+$t4 = curl_init();
+$t3 = curl_copy_handle($t4);
+$t5 = curl_init();
+$t6 = curl_copy_handle($t5);
+?>
+okey
+--EXPECT--
+okey