summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorAdam Harvey <aharvey@php.net>2013-08-19 12:16:36 -0700
committerAdam Harvey <aharvey@php.net>2013-08-19 12:16:36 -0700
commit69f12ad582c102c1d7b3b2c0ae6cf7cd633dfe1d (patch)
treef804acd47531734907653caf50b632e1439285d4 /ext
parentd2c78c9e2039b0dfd14587800e24b30ff0ab0e1e (diff)
parentaa7d3d8e6d8de73ebe8dd015fb5392a4bde5bfc6 (diff)
downloadphp-git-69f12ad582c102c1d7b3b2c0ae6cf7cd633dfe1d.tar.gz
Merge branch 'PHP-5.4' into PHP-5.5
* PHP-5.4: Track created curl_slist structs by option so they can be updated in situ. Conflicts: ext/curl/interface.c
Diffstat (limited to 'ext')
-rw-r--r--ext/curl/interface.c14
-rw-r--r--ext/curl/php_curl.h2
-rw-r--r--ext/curl/tests/bug65458.phpt25
3 files changed, 35 insertions, 6 deletions
diff --git a/ext/curl/interface.c b/ext/curl/interface.c
index 4b6e5e27dc..861795485d 100644
--- a/ext/curl/interface.c
+++ b/ext/curl/interface.c
@@ -1717,9 +1717,9 @@ static void curl_free_post(void **post)
/* {{{ curl_free_slist
*/
-static void curl_free_slist(void **slist)
+static void curl_free_slist(void *slist)
{
- curl_slist_free_all((struct curl_slist *) *slist);
+ curl_slist_free_all(*((struct curl_slist **) slist));
}
/* }}} */
@@ -1790,9 +1790,11 @@ static void alloc_curl_handle(php_curl **ch)
(*ch)->handlers->read->stream = NULL;
zend_llist_init(&(*ch)->to_free->str, sizeof(char *), (llist_dtor_func_t) curl_free_string, 0);
- zend_llist_init(&(*ch)->to_free->slist, sizeof(struct curl_slist), (llist_dtor_func_t) curl_free_slist, 0);
zend_llist_init(&(*ch)->to_free->post, sizeof(struct HttpPost), (llist_dtor_func_t) curl_free_post, 0);
(*ch)->safe_upload = 0; /* for now, for BC reason we allow unsafe API */
+
+ (*ch)->to_free->slist = emalloc(sizeof(HashTable));
+ zend_hash_init((*ch)->to_free->slist, 4, NULL, curl_free_slist, 0);
}
/* }}} */
@@ -2043,6 +2045,7 @@ PHP_FUNCTION(curl_copy_handle)
}
#endif
+ efree(dupch->to_free->slist);
efree(dupch->to_free);
dupch->to_free = ch->to_free;
@@ -2488,7 +2491,7 @@ string_copy:
return 1;
}
}
- zend_llist_add_element(&ch->to_free->slist, &slist);
+ zend_hash_index_update(ch->to_free->slist, (ulong) option, &slist, sizeof(struct curl_slist *), NULL);
error = curl_easy_setopt(ch->cp, option, slist);
@@ -3266,8 +3269,9 @@ static void _php_curl_close_ex(php_curl *ch TSRMLS_DC)
/* cURL destructors should be invoked only by last curl handle */
if (Z_REFCOUNT_P(ch->clone) <= 1) {
zend_llist_clean(&ch->to_free->str);
- zend_llist_clean(&ch->to_free->slist);
zend_llist_clean(&ch->to_free->post);
+ zend_hash_destroy(ch->to_free->slist);
+ efree(ch->to_free->slist);
efree(ch->to_free);
FREE_ZVAL(ch->clone);
} else {
diff --git a/ext/curl/php_curl.h b/ext/curl/php_curl.h
index 9e98fe57cd..c45ed80fc2 100644
--- a/ext/curl/php_curl.h
+++ b/ext/curl/php_curl.h
@@ -168,7 +168,7 @@ struct _php_curl_send_headers {
struct _php_curl_free {
zend_llist str;
zend_llist post;
- zend_llist slist;
+ HashTable *slist;
};
typedef struct {
diff --git a/ext/curl/tests/bug65458.phpt b/ext/curl/tests/bug65458.phpt
new file mode 100644
index 0000000000..99288f24be
--- /dev/null
+++ b/ext/curl/tests/bug65458.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Bug #65458 (curl memory leak)
+--SKIPIF--
+<?php
+if (!extension_loaded('curl')) exit("skip curl extension not loaded");
+?>
+--FILE--
+<?php
+$ch = curl_init();
+$init = memory_get_usage();
+for ($i = 0; $i < 10000; $i++) {
+ curl_setopt($ch, CURLOPT_HTTPHEADER, [ "SOAPAction: getItems" ]);
+}
+
+$preclose = memory_get_usage();
+curl_close($ch);
+
+// This is a slightly tricky heuristic, but basically, we want to ensure
+// $preclose - $init has a delta in the order of bytes, not megabytes. Given
+// the number of iterations in the loop, if we're wasting memory here, we
+// should have megs and megs of extra allocations.
+var_dump(($preclose - $init) < 10000);
+?>
+--EXPECT--
+bool(true)