From: Nikita Popov Date: Wed, 11 Nov 2020 10:51:20 +0000 (+0100) Subject: Retain reference to share handle from curl handle X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b4a2a9662b4244837e348f58d398523361dbcc7f;p=php Retain reference to share handle from curl handle Not keeping a reference will not result in use after free, because curl protects against it, but it will result in a memory leak, because curl_share_cleanup() will fail. We should make sure that the share handle object stays alive as long as the curl handles use it. --- diff --git a/ext/curl/curl_private.h b/ext/curl/curl_private.h index 8ff0aef605..6ed2eba3c3 100644 --- a/ext/curl/curl_private.h +++ b/ext/curl/curl_private.h @@ -104,6 +104,8 @@ typedef struct { zend_bool in_callback; uint32_t* clone; zval postfields; + /* CurlShareHandle object set using CURLOPT_SHARE. */ + struct _php_curlsh *share; zend_object std; } php_curl; @@ -124,7 +126,7 @@ typedef struct { zend_object std; } php_curlm; -typedef struct { +typedef struct _php_curlsh { CURLSH *share; struct { int no; diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 8ff3e0f374..f01f6f775a 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -2832,6 +2832,12 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue, bool i if (Z_TYPE_P(zvalue) == IS_OBJECT && Z_OBJCE_P(zvalue) == curl_share_ce) { php_curlsh *sh = Z_CURL_SHARE_P(zvalue); curl_easy_setopt(ch->cp, CURLOPT_SHARE, sh->share); + + if (ch->share) { + OBJ_RELEASE(&ch->share->std); + } + GC_ADDREF(&sh->std); + ch->share = sh; } } break; @@ -3373,6 +3379,10 @@ static void curl_free_obj(zend_object *object) efree(ch->handlers); zval_ptr_dtor(&ch->postfields); + if (ch->share) { + OBJ_RELEASE(&ch->share->std); + } + zend_object_std_dtor(&ch->std); } /* }}} */ diff --git a/ext/curl/tests/curl_share_basic.phpt b/ext/curl/tests/curl_share_basic.phpt new file mode 100644 index 0000000000..2a37fce16a --- /dev/null +++ b/ext/curl/tests/curl_share_basic.phpt @@ -0,0 +1,29 @@ +--TEST-- +Basic curl_share test +--FILE-- + +--EXPECT-- +string(6) "CURL1 +" +string(6) "CURL2 +"