From: Nikita Popov Date: Thu, 1 Oct 2020 15:05:23 +0000 (+0200) Subject: Fixed bug #80121 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d96219c185e68c82beb994db2c93bd26f47ce16a;p=php Fixed bug #80121 The issue affected both CurlHandle and CurlMultiHandle. I'll have to double check this for other resource->object conversions as well. --- diff --git a/NEWS b/NEWS index 57892d8bb6..dc39e99d07 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.0.0rc2 +- Curl: + . Fixed bug #80121 (Null pointer deref if CurlHandle directly instantiated). + (Nikita) + - SPL. . Fixed bug #65387 (Circular references in SPL iterators are not garbage collected). (Nikita) diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 150f98d46f..8ff3e0f374 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -3308,6 +3308,12 @@ static void curl_free_obj(zend_object *object) fprintf(stderr, "DTOR CALLED, ch = %x\n", ch); #endif + if (!ch->cp) { + /* Can happen if constructor throws. */ + zend_object_std_dtor(&ch->std); + return; + } + _php_curl_verify_handlers(ch, 0); /* @@ -3321,12 +3327,10 @@ static void curl_free_obj(zend_object *object) * * Libcurl commit d021f2e8a00 fix this issue and should be part of 7.28.2 */ - if (ch->cp != NULL) { - curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_nothing); - curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write_nothing); + curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_nothing); + curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write_nothing); - curl_easy_cleanup(ch->cp); - } + curl_easy_cleanup(ch->cp); /* cURL destructors should be invoked only by last curl handle */ if (--(*ch->clone) == 0) { diff --git a/ext/curl/multi.c b/ext/curl/multi.c index 2c2e37e402..e717fd5d9e 100644 --- a/ext/curl/multi.c +++ b/ext/curl/multi.c @@ -537,6 +537,12 @@ void curl_multi_free_obj(zend_object *object) php_curl *ch; zval *pz_ch; + if (!mh->multi) { + /* Can happen if constructor throws. */ + zend_object_std_dtor(&mh->std); + return; + } + for (pz_ch = (zval *)zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch; pz_ch = (zval *)zend_llist_get_next_ex(&mh->easyh, &pos)) { if (!(OBJ_FLAGS(Z_OBJ_P(pz_ch)) & IS_OBJ_FREE_CALLED)) { diff --git a/ext/curl/tests/bug80121.phpt b/ext/curl/tests/bug80121.phpt new file mode 100644 index 0000000000..9239cf007f --- /dev/null +++ b/ext/curl/tests/bug80121.phpt @@ -0,0 +1,26 @@ +--TEST-- +Bug #80121: Null pointer deref if CurlHandle directly instantiated +--FILE-- +getMessage(), "\n"; +} +try { + new CurlMultiHandle; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + new CurlShareHandle; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Cannot directly construct CurlHandle, use curl_init() instead +Cannot directly construct CurlMultiHandle, use curl_multi_init() instead +Cannot directly construct CurlShareHandle, use curl_share_init() instead