Skip to content

Commit 5276ca6

Browse files
committed
Manually store CURLOPT_PRIVATE data
This is simpler than going through curl, because we can manage the memory more easily (in particular, this removes the need for to_free->str). Additionally this allows the CURLOPT_PRIVATE data to have any type, instead of being implicitly cast to string.
1 parent 5c21d39 commit 5276ca6

File tree

3 files changed

+48
-34
lines changed

3 files changed

+48
-34
lines changed

ext/curl/curl_private.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ struct _php_curl_send_headers {
8888
};
8989

9090
struct _php_curl_free {
91-
zend_llist str;
9291
zend_llist post;
9392
zend_llist stream;
9493
HashTable *slist;
@@ -103,6 +102,8 @@ typedef struct {
103102
zend_bool in_callback;
104103
uint32_t* clone;
105104
zval postfields;
105+
/* For CURLOPT_PRIVATE */
106+
zval private_data;
106107
/* CurlShareHandle object set using CURLOPT_SHARE. */
107108
struct _php_curlsh *share;
108109
zend_object std;

ext/curl/interface.c

Lines changed: 21 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -97,26 +97,14 @@ static ZEND_ATTRIBUTE_UNUSED unsigned long php_curl_ssl_id(void)
9797
# define php_curl_ret(__ret) RETVAL_FALSE; return;
9898
#endif
9999

100-
static int php_curl_option_str(php_curl *ch, zend_long option, const char *str, const size_t len, zend_bool make_copy)
100+
static int php_curl_option_str(php_curl *ch, zend_long option, const char *str, const size_t len)
101101
{
102-
CURLcode error = CURLE_OK;
103-
104102
if (strlen(str) != len) {
105103
zend_value_error("%s(): cURL option must not contain any null bytes", get_active_function_name());
106104
return FAILURE;
107105
}
108106

109-
if (make_copy) {
110-
char *copystr;
111-
112-
/* Strings passed to libcurl as 'char *' arguments, are copied by the library since 7.17.0 */
113-
copystr = estrndup(str, len);
114-
error = curl_easy_setopt(ch->cp, option, copystr);
115-
zend_llist_add_element(&ch->to_free->str, &copystr);
116-
} else {
117-
error = curl_easy_setopt(ch->cp, option, str);
118-
}
119-
107+
CURLcode error = curl_easy_setopt(ch->cp, option, str);
120108
SAVE_CURL_ERROR(ch, error);
121109

122110
return error == CURLE_OK ? SUCCESS : FAILURE;
@@ -136,11 +124,11 @@ static int php_curl_option_url(php_curl *ch, const char *url, const size_t len)
136124
memmove(_tmp, "file:///", sizeof("file:///") - 1);
137125
memmove(_tmp + sizeof("file:///") - 1, url + sizeof("file://") - 1, len - sizeof("file://") + 1);
138126

139-
return php_curl_option_str(ch, CURLOPT_URL, _tmp, len + 1, 0);
127+
return php_curl_option_str(ch, CURLOPT_URL, _tmp, len + 1);
140128
}
141129
#endif
142130

143-
return php_curl_option_str(ch, CURLOPT_URL, url, len, 0);
131+
return php_curl_option_str(ch, CURLOPT_URL, url, len);
144132
}
145133
/* }}} */
146134

@@ -1291,6 +1279,7 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n)
12911279
#endif
12921280

12931281
zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers.std_err);
1282+
zend_get_gc_buffer_add_zval(gc_buffer, &curl->private_data);
12941283

12951284
zend_get_gc_buffer_use(gc_buffer, table, n);
12961285

@@ -1634,13 +1623,6 @@ static int curl_debug(CURL *cp, curl_infotype type, char *buf, size_t buf_len, v
16341623
}
16351624
/* }}} */
16361625

1637-
/* {{{ curl_free_string */
1638-
static void curl_free_string(void **string)
1639-
{
1640-
efree((char *)*string);
1641-
}
1642-
/* }}} */
1643-
16441626
/* {{{ curl_free_post */
16451627
static void curl_free_post(void **post)
16461628
{
@@ -1755,7 +1737,6 @@ void init_curl_handle(php_curl *ch)
17551737

17561738
memset(&ch->err, 0, sizeof(struct _php_curl_error));
17571739

1758-
zend_llist_init(&ch->to_free->str, sizeof(char *), (llist_dtor_func_t)curl_free_string, 0);
17591740
zend_llist_init(&ch->to_free->post, sizeof(struct HttpPost *), (llist_dtor_func_t)curl_free_post, 0);
17601741
zend_llist_init(&ch->to_free->stream, sizeof(struct mime_data_cb_arg *), (llist_dtor_func_t)curl_free_cb_arg, 0);
17611742

@@ -1925,6 +1906,8 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
19251906
curl_easy_setopt(ch->cp, CURLOPT_FNMATCH_DATA, (void *) ch);
19261907
}
19271908

1909+
ZVAL_COPY(&ch->private_data, &source->private_data);
1910+
19281911
efree(ch->to_free->slist);
19291912
efree(ch->to_free);
19301913
ch->to_free = source->to_free;
@@ -2447,7 +2430,7 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue, bool i
24472430
{
24482431
zend_string *tmp_str;
24492432
zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
2450-
int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 0);
2433+
int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str));
24512434
zend_tmp_string_release(tmp_str);
24522435
return ret;
24532436
}
@@ -2474,7 +2457,7 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue, bool i
24742457
} else {
24752458
zend_string *tmp_str;
24762459
zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
2477-
int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 0);
2460+
int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str));
24782461
zend_tmp_string_release(tmp_str);
24792462
return ret;
24802463
}
@@ -2484,11 +2467,9 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue, bool i
24842467
/* Curl private option */
24852468
case CURLOPT_PRIVATE:
24862469
{
2487-
zend_string *tmp_str;
2488-
zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
2489-
int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 1);
2490-
zend_tmp_string_release(tmp_str);
2491-
return ret;
2470+
zval_ptr_dtor(&ch->private_data);
2471+
ZVAL_COPY(&ch->private_data, zvalue);
2472+
return SUCCESS;
24922473
}
24932474

24942475
/* Curl url option */
@@ -2794,7 +2775,7 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue, bool i
27942775
return FAILURE;
27952776
}
27962777

2797-
ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 0);
2778+
ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str));
27982779
zend_tmp_string_release(tmp_str);
27992780
return ret;
28002781
}
@@ -3160,6 +3141,13 @@ PHP_FUNCTION(curl_getinfo)
31603141
}
31613142
break;
31623143
}
3144+
case CURLINFO_PRIVATE:
3145+
if (!Z_ISUNDEF(ch->private_data)) {
3146+
RETURN_COPY(&ch->private_data);
3147+
} else {
3148+
RETURN_FALSE;
3149+
}
3150+
break;
31633151
default: {
31643152
int type = CURLINFO_TYPEMASK & option;
31653153
switch (type) {
@@ -3323,7 +3311,6 @@ static void curl_free_obj(zend_object *object)
33233311

33243312
/* cURL destructors should be invoked only by last curl handle */
33253313
if (--(*ch->clone) == 0) {
3326-
zend_llist_clean(&ch->to_free->str);
33273314
zend_llist_clean(&ch->to_free->post);
33283315
zend_llist_clean(&ch->to_free->stream);
33293316
zend_hash_destroy(ch->to_free->slist);
@@ -3360,6 +3347,7 @@ static void curl_free_obj(zend_object *object)
33603347
}
33613348

33623349
zval_ptr_dtor(&ch->postfields);
3350+
zval_ptr_dtor(&ch->private_data);
33633351

33643352
if (ch->share) {
33653353
OBJ_RELEASE(&ch->share->std);

ext/curl/tests/curlopt_private.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
CURLOPT_PRIVATE
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('curl')) exit("skip curl extension not loaded");
6+
?>
7+
--FILE--
8+
<?php
9+
$curl = curl_init("foobar");
10+
$obj = new stdClass;
11+
curl_setopt($curl, CURLOPT_PRIVATE, $obj);
12+
var_dump($obj === curl_getinfo($curl, CURLINFO_PRIVATE));
13+
14+
$curl2 = curl_copy_handle($curl);
15+
var_dump($obj === curl_getinfo($curl2, CURLINFO_PRIVATE));
16+
$obj2 = new stdClass;
17+
curl_setopt($curl2, CURLOPT_PRIVATE, $obj2);
18+
var_dump($obj === curl_getinfo($curl, CURLINFO_PRIVATE));
19+
var_dump($obj2 === curl_getinfo($curl2, CURLINFO_PRIVATE));
20+
?>
21+
--EXPECT--
22+
bool(true)
23+
bool(true)
24+
bool(true)
25+
bool(true)

0 commit comments

Comments
 (0)