diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2021-01-04 16:59:57 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2021-01-04 16:59:57 +0100 |
commit | 5276ca61791c4204d3052d7e6d1e89f50cecad6c (patch) | |
tree | 3aff45f225014fb180c98e536b27d81cca831116 | |
parent | 5c21d39d557e9362f6a4cfc095bb7b7694107878 (diff) | |
download | php-git-5276ca61791c4204d3052d7e6d1e89f50cecad6c.tar.gz |
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.
-rw-r--r-- | ext/curl/curl_private.h | 3 | ||||
-rw-r--r-- | ext/curl/interface.c | 54 | ||||
-rw-r--r-- | ext/curl/tests/curlopt_private.phpt | 25 |
3 files changed, 48 insertions, 34 deletions
diff --git a/ext/curl/curl_private.h b/ext/curl/curl_private.h index d2cba1668b..859a064dc8 100644 --- a/ext/curl/curl_private.h +++ b/ext/curl/curl_private.h @@ -88,7 +88,6 @@ struct _php_curl_send_headers { }; struct _php_curl_free { - zend_llist str; zend_llist post; zend_llist stream; HashTable *slist; @@ -103,6 +102,8 @@ typedef struct { zend_bool in_callback; uint32_t* clone; zval postfields; + /* For CURLOPT_PRIVATE */ + zval private_data; /* CurlShareHandle object set using CURLOPT_SHARE. */ struct _php_curlsh *share; zend_object std; diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 4c077d66a2..5b2b974e88 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -97,26 +97,14 @@ static ZEND_ATTRIBUTE_UNUSED unsigned long php_curl_ssl_id(void) # define php_curl_ret(__ret) RETVAL_FALSE; return; #endif -static int php_curl_option_str(php_curl *ch, zend_long option, const char *str, const size_t len, zend_bool make_copy) +static int php_curl_option_str(php_curl *ch, zend_long option, const char *str, const size_t len) { - CURLcode error = CURLE_OK; - if (strlen(str) != len) { zend_value_error("%s(): cURL option must not contain any null bytes", get_active_function_name()); return FAILURE; } - if (make_copy) { - char *copystr; - - /* Strings passed to libcurl as 'char *' arguments, are copied by the library since 7.17.0 */ - copystr = estrndup(str, len); - error = curl_easy_setopt(ch->cp, option, copystr); - zend_llist_add_element(&ch->to_free->str, ©str); - } else { - error = curl_easy_setopt(ch->cp, option, str); - } - + CURLcode error = curl_easy_setopt(ch->cp, option, str); SAVE_CURL_ERROR(ch, error); 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) memmove(_tmp, "file:///", sizeof("file:///") - 1); memmove(_tmp + sizeof("file:///") - 1, url + sizeof("file://") - 1, len - sizeof("file://") + 1); - return php_curl_option_str(ch, CURLOPT_URL, _tmp, len + 1, 0); + return php_curl_option_str(ch, CURLOPT_URL, _tmp, len + 1); } #endif - return php_curl_option_str(ch, CURLOPT_URL, url, len, 0); + return php_curl_option_str(ch, CURLOPT_URL, url, len); } /* }}} */ @@ -1291,6 +1279,7 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n) #endif zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers.std_err); + zend_get_gc_buffer_add_zval(gc_buffer, &curl->private_data); zend_get_gc_buffer_use(gc_buffer, table, n); @@ -1634,13 +1623,6 @@ static int curl_debug(CURL *cp, curl_infotype type, char *buf, size_t buf_len, v } /* }}} */ -/* {{{ curl_free_string */ -static void curl_free_string(void **string) -{ - efree((char *)*string); -} -/* }}} */ - /* {{{ curl_free_post */ static void curl_free_post(void **post) { @@ -1755,7 +1737,6 @@ void init_curl_handle(php_curl *ch) memset(&ch->err, 0, sizeof(struct _php_curl_error)); - zend_llist_init(&ch->to_free->str, sizeof(char *), (llist_dtor_func_t)curl_free_string, 0); zend_llist_init(&ch->to_free->post, sizeof(struct HttpPost *), (llist_dtor_func_t)curl_free_post, 0); zend_llist_init(&ch->to_free->stream, sizeof(struct mime_data_cb_arg *), (llist_dtor_func_t)curl_free_cb_arg, 0); @@ -1925,6 +1906,8 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source) curl_easy_setopt(ch->cp, CURLOPT_FNMATCH_DATA, (void *) ch); } + ZVAL_COPY(&ch->private_data, &source->private_data); + efree(ch->to_free->slist); efree(ch->to_free); 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 { zend_string *tmp_str; zend_string *str = zval_get_tmp_string(zvalue, &tmp_str); - int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 0); + int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str)); zend_tmp_string_release(tmp_str); return ret; } @@ -2474,7 +2457,7 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue, bool i } else { zend_string *tmp_str; zend_string *str = zval_get_tmp_string(zvalue, &tmp_str); - int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 0); + int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str)); zend_tmp_string_release(tmp_str); return ret; } @@ -2484,11 +2467,9 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue, bool i /* Curl private option */ case CURLOPT_PRIVATE: { - zend_string *tmp_str; - zend_string *str = zval_get_tmp_string(zvalue, &tmp_str); - int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 1); - zend_tmp_string_release(tmp_str); - return ret; + zval_ptr_dtor(&ch->private_data); + ZVAL_COPY(&ch->private_data, zvalue); + return SUCCESS; } /* Curl url option */ @@ -2794,7 +2775,7 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue, bool i return FAILURE; } - ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 0); + ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str)); zend_tmp_string_release(tmp_str); return ret; } @@ -3160,6 +3141,13 @@ PHP_FUNCTION(curl_getinfo) } break; } + case CURLINFO_PRIVATE: + if (!Z_ISUNDEF(ch->private_data)) { + RETURN_COPY(&ch->private_data); + } else { + RETURN_FALSE; + } + break; default: { int type = CURLINFO_TYPEMASK & option; switch (type) { @@ -3323,7 +3311,6 @@ static void curl_free_obj(zend_object *object) /* cURL destructors should be invoked only by last curl handle */ if (--(*ch->clone) == 0) { - zend_llist_clean(&ch->to_free->str); zend_llist_clean(&ch->to_free->post); zend_llist_clean(&ch->to_free->stream); zend_hash_destroy(ch->to_free->slist); @@ -3360,6 +3347,7 @@ static void curl_free_obj(zend_object *object) } zval_ptr_dtor(&ch->postfields); + zval_ptr_dtor(&ch->private_data); if (ch->share) { OBJ_RELEASE(&ch->share->std); diff --git a/ext/curl/tests/curlopt_private.phpt b/ext/curl/tests/curlopt_private.phpt new file mode 100644 index 0000000000..663283195e --- /dev/null +++ b/ext/curl/tests/curlopt_private.phpt @@ -0,0 +1,25 @@ +--TEST-- +CURLOPT_PRIVATE +--SKIPIF-- +<?php +if (!extension_loaded('curl')) exit("skip curl extension not loaded"); +?> +--FILE-- +<?php +$curl = curl_init("foobar"); +$obj = new stdClass; +curl_setopt($curl, CURLOPT_PRIVATE, $obj); +var_dump($obj === curl_getinfo($curl, CURLINFO_PRIVATE)); + +$curl2 = curl_copy_handle($curl); +var_dump($obj === curl_getinfo($curl2, CURLINFO_PRIVATE)); +$obj2 = new stdClass; +curl_setopt($curl2, CURLOPT_PRIVATE, $obj2); +var_dump($obj === curl_getinfo($curl, CURLINFO_PRIVATE)); +var_dump($obj2 === curl_getinfo($curl2, CURLINFO_PRIVATE)); +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) |