Skip to content

Commit b675db4

Browse files
committed
Merge branch 'PHP-8.4'
* PHP-8.4: curl: Prevent a CurlMultiHandle from holding onto a CurlHandle if `add_handle` fails (#16302)
2 parents dd0ced3 + f2fbb75 commit b675db4

File tree

2 files changed

+58
-5
lines changed

2 files changed

+58
-5
lines changed

ext/curl/multi.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,14 @@ PHP_FUNCTION(curl_multi_add_handle)
9797

9898
_php_curl_cleanup_handle(ch);
9999

100-
Z_ADDREF_P(z_ch);
101-
zend_llist_add_element(&mh->easyh, z_ch);
102-
103100
error = curl_multi_add_handle(mh->multi, ch->cp);
104101
SAVE_CURLM_ERROR(mh, error);
105102

103+
if (error == CURLM_OK) {
104+
Z_ADDREF_P(z_ch);
105+
zend_llist_add_element(&mh->easyh, z_ch);
106+
}
107+
106108
RETURN_LONG((zend_long) error);
107109
}
108110
/* }}} */
@@ -164,9 +166,11 @@ PHP_FUNCTION(curl_multi_remove_handle)
164166
error = curl_multi_remove_handle(mh->multi, ch->cp);
165167
SAVE_CURLM_ERROR(mh, error);
166168

167-
RETVAL_LONG((zend_long) error);
168-
zend_llist_del_element(&mh->easyh, z_ch, (int (*)(void *, void *))curl_compare_objects);
169+
if (error == CURLM_OK) {
170+
zend_llist_del_element(&mh->easyh, z_ch, (int (*)(void *, void *))curl_compare_objects);
171+
}
169172

173+
RETURN_LONG((zend_long) error);
170174
}
171175
/* }}} */
172176

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
--TEST--
2+
curl_multi_add_handle does not hold onto the handle on failure
3+
--EXTENSIONS--
4+
curl
5+
--FILE--
6+
<?php
7+
8+
class MyClass {
9+
public function __destruct() {
10+
echo __METHOD__, PHP_EOL;
11+
}
12+
}
13+
14+
$urls = [
15+
"file://".__DIR__."/curl_testdata1.txt",
16+
"file://".__DIR__."/curl_testdata2.txt",
17+
];
18+
19+
$mh = curl_multi_init();
20+
21+
$toRemove = [];
22+
foreach ($urls as $url) {
23+
$ch = curl_init($url);
24+
curl_setopt($ch, CURLOPT_PRIVATE, new MyClass());
25+
26+
if (curl_multi_add_handle($mh, $ch) == CURLM_OK) {
27+
$toRemove[] = $ch;
28+
}
29+
if (curl_multi_add_handle($mh, $ch) == CURLM_OK) {
30+
$toRemove[] = $ch;
31+
}
32+
33+
unset($ch);
34+
}
35+
36+
echo "Removing", PHP_EOL;
37+
foreach ($toRemove as $i => $ch) {
38+
curl_multi_remove_handle($mh, $ch);
39+
unset($ch);
40+
unset($toRemove[$i]);
41+
}
42+
echo "Removed", PHP_EOL;
43+
44+
?>
45+
--EXPECTF--
46+
Removing
47+
MyClass::__destruct
48+
MyClass::__destruct
49+
Removed

0 commit comments

Comments
 (0)