Skip to content

Commit

Permalink
Fixed bug #70330 (Segmentation Fault with multiple "curl_copy_handle")
Browse files Browse the repository at this point in the history
  • Loading branch information
laruence committed Aug 23, 2015
1 parent 55f8814 commit 4df6f26
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 5 deletions.
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
12 changes: 8 additions & 4 deletions ext/curl/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion ext/curl/php_curl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 17 additions & 0 deletions ext/curl/tests/bug70330.phpt
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 4df6f26

Please sign in to comment.