Skip to content

Commit 3c1bcc2

Browse files
author
Jani Taskinen
committed
MFH:- Fixed bug #45161 (Reusing a curl handle leaks memory)
1 parent 1cd04d8 commit 3c1bcc2

File tree

3 files changed

+35
-7
lines changed

3 files changed

+35
-7
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ PHP NEWS
1313
- Fixed bug #46739 (array returned by curl_getinfo should contain content_type key).
1414
(Mikko)
1515
- Fixed bug #46699 (xml_parse crash when parser is namespace aware). (Rob)
16+
- Fixed bug #45161 (Reusing a curl handle leaks memory). (Mark Karpeles, Jani)
1617
- Fixed bug #35975 (Session cookie expires date format isn't the most compatible.
1718
Now matches that of setcookie()). (Scott)
1819

ext/curl/interface.c

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -996,13 +996,15 @@ static size_t curl_passwd(void *ctx, char *prompt, char *buf, int buflen)
996996
/* }}} */
997997
#endif
998998

999+
#if LIBCURL_VERSION_NUM < 0x071101
9991000
/* {{{ curl_free_string
10001001
*/
10011002
static void curl_free_string(void **string)
10021003
{
10031004
efree(*string);
10041005
}
10051006
/* }}} */
1007+
#endif
10061008

10071009
/* {{{ curl_free_post
10081010
*/
@@ -1077,7 +1079,9 @@ static void alloc_curl_handle(php_curl **ch)
10771079

10781080
memset(&(*ch)->err, 0, sizeof((*ch)->err));
10791081

1082+
#if LIBCURL_VERSION_NUM < 0x071101
10801083
zend_llist_init(&(*ch)->to_free.str, sizeof(char *), (llist_dtor_func_t) curl_free_string, 0);
1084+
#endif
10811085
zend_llist_init(&(*ch)->to_free.slist, sizeof(struct curl_slist), (llist_dtor_func_t) curl_free_slist, 0);
10821086
zend_llist_init(&(*ch)->to_free.post, sizeof(struct HttpPost), (llist_dtor_func_t) curl_free_post, 0);
10831087
}
@@ -1136,11 +1140,15 @@ PHP_FUNCTION(curl_init)
11361140
#endif
11371141

11381142
if (argc > 0) {
1143+
#if LIBCURL_VERSION_NUM >= 0x071100
1144+
curl_easy_setopt(ch->cp, CURLOPT_URL, Z_STRVAL_PP(url));
1145+
#else
11391146
char *urlcopy;
11401147

11411148
urlcopy = estrndup(Z_STRVAL_PP(url), Z_STRLEN_PP(url));
11421149
curl_easy_setopt(ch->cp, CURLOPT_URL, urlcopy);
11431150
zend_llist_add_element(&ch->to_free.str, &urlcopy);
1151+
#endif
11441152
}
11451153

11461154
ZEND_REGISTER_RESOURCE(return_value, ch, le_curl);
@@ -1206,9 +1214,11 @@ PHP_FUNCTION(curl_copy_handle)
12061214
curl_easy_setopt(dupch->cp, CURLOPT_INFILE, (void *) dupch);
12071215
curl_easy_setopt(dupch->cp, CURLOPT_WRITEHEADER, (void *) dupch);
12081216

1217+
#if LIBCURL_VERSION_NUM < 0x071101
12091218
zend_llist_copy(&dupch->to_free.str, &ch->to_free.str);
12101219
/* Don't try to free copied strings, they're free'd when the original handle is destroyed */
12111220
dupch->to_free.str.dtor = NULL;
1221+
#endif
12121222
zend_llist_copy(&dupch->to_free.slist, &ch->to_free.slist);
12131223
zend_llist_copy(&dupch->to_free.post, &ch->to_free.post);
12141224

@@ -1331,17 +1341,24 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu
13311341
case CURLOPT_SSLENGINE_DEFAULT:
13321342
case CURLOPT_SSLCERTTYPE:
13331343
case CURLOPT_ENCODING: {
1344+
#if LIBCURL_VERSION_NUM < 0x071100
13341345
char *copystr = NULL;
1346+
#endif
13351347

13361348
convert_to_string_ex(zvalue);
13371349

13381350
if (option == CURLOPT_URL) {
13391351
PHP_CURL_CHECK_OPEN_BASEDIR(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue), 1);
13401352
}
13411353

1354+
#if LIBCURL_VERSION_NUM >= 0x071100
1355+
/* Strings passed to libcurl as ’char *’ arguments, are copied by the library... NOTE: before 7.17.0 strings were not copied. */
1356+
error = curl_easy_setopt(ch->cp, option, Z_STRVAL_PP(zvalue));
1357+
#else
13421358
copystr = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue));
13431359
error = curl_easy_setopt(ch->cp, option, copystr);
13441360
zend_llist_add_element(&ch->to_free.str, &copystr);
1361+
#endif
13451362

13461363
break;
13471364
}
@@ -1532,6 +1549,11 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu
15321549
error = curl_easy_setopt(ch->cp, CURLOPT_HTTPPOST, first);
15331550

15341551
} else {
1552+
#if LIBCURL_VERSION_NUM >= 0x071101
1553+
/* with curl 7.17.0 and later, we can use COPYPOSTFIELDS, but we have to provide size before */
1554+
error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, Z_STRLEN_PP(zvalue));
1555+
error = curl_easy_setopt(ch->cp, CURLOPT_COPYPOSTFIELDS, Z_STRVAL_PP(zvalue));
1556+
#else
15351557
char *post = NULL;
15361558

15371559
convert_to_string_ex(zvalue);
@@ -1540,6 +1562,7 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu
15401562

15411563
error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDS, post);
15421564
error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, Z_STRLEN_PP(zvalue));
1565+
#endif
15431566
}
15441567
break;
15451568
case CURLOPT_HTTPHEADER:
@@ -1561,20 +1584,15 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu
15611584
zend_hash_get_current_data(ph, (void **) &current) == SUCCESS;
15621585
zend_hash_move_forward(ph)
15631586
) {
1564-
char *indiv = NULL;
1565-
15661587
SEPARATE_ZVAL(current);
15671588
convert_to_string_ex(current);
15681589

1569-
indiv = estrndup(Z_STRVAL_PP(current), Z_STRLEN_PP(current) + 1);
1570-
slist = curl_slist_append(slist, indiv);
1590+
slist = curl_slist_append(slist, Z_STRVAL_PP(current));
15711591
if (!slist) {
1572-
efree(indiv);
15731592
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not build curl_slist");
15741593
RETVAL_FALSE;
15751594
return 1;
15761595
}
1577-
zend_llist_add_element(&ch->to_free.str, &indiv);
15781596
}
15791597
zend_llist_add_element(&ch->to_free.slist, &slist);
15801598

@@ -1589,7 +1607,9 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu
15891607
case CURLOPT_SSLCERT:
15901608
case CURLOPT_RANDOM_FILE:
15911609
case CURLOPT_COOKIEFILE: {
1610+
#if LIBCURL_VERSION_NUM < 0x071100
15921611
char *copystr = NULL;
1612+
#endif
15931613

15941614
convert_to_string_ex(zvalue);
15951615

@@ -1598,11 +1618,14 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu
15981618
return 1;
15991619
}
16001620

1621+
#if LIBCURL_VERSION_NUM >= 0x071100
1622+
error = curl_easy_setopt(ch->cp, option, Z_STRVAL_PP(zvalue));
1623+
#else
16011624
copystr = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue));
16021625

16031626
error = curl_easy_setopt(ch->cp, option, copystr);
16041627
zend_llist_add_element(&ch->to_free.str, &copystr);
1605-
1628+
#endif
16061629
break;
16071630
}
16081631
case CURLINFO_HEADER_OUT:
@@ -1968,7 +1991,9 @@ static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC)
19681991
#endif
19691992

19701993
curl_easy_cleanup(ch->cp);
1994+
#if LIBCURL_VERSION_NUM < 0x071101
19711995
zend_llist_clean(&ch->to_free.str);
1996+
#endif
19721997
zend_llist_clean(&ch->to_free.slist);
19731998
zend_llist_clean(&ch->to_free.post);
19741999

ext/curl/php_curl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,9 @@ struct _php_curl_send_headers {
114114
};
115115

116116
struct _php_curl_free {
117+
#if LIBCURL_VERSION_NUM < 0x071100
117118
zend_llist str;
119+
#endif
118120
zend_llist post;
119121
zend_llist slist;
120122
};

0 commit comments

Comments
 (0)