]> granicus.if.org Git - php/commitdiff
Fixed bug #80121
authorNikita Popov <nikita.ppv@gmail.com>
Thu, 1 Oct 2020 15:05:23 +0000 (17:05 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Thu, 1 Oct 2020 15:05:23 +0000 (17:05 +0200)
The issue affected both CurlHandle and CurlMultiHandle. I'll have
to double check this for other resource->object conversions as well.

NEWS
ext/curl/interface.c
ext/curl/multi.c
ext/curl/tests/bug80121.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 57892d8bb6dbfeecce27a4f9844344e92983bc00..dc39e99d07f018e9821fa3f8560953ade6d7e57c 100644 (file)
--- 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)
index 150f98d46fe81f6aa5ac338c880421734d14deb1..8ff3e0f37471f713dc764700cb1283fc81821698 100644 (file)
@@ -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) {
index 2c2e37e4028accbdab8111f091afcf3744f2cd29..e717fd5d9e29183f54c63709afb9e6928a454c6f 100644 (file)
@@ -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 (file)
index 0000000..9239cf0
--- /dev/null
@@ -0,0 +1,26 @@
+--TEST--
+Bug #80121: Null pointer deref if CurlHandle directly instantiated
+--FILE--
+<?php
+
+try {
+    new CurlHandle;
+} catch (Error $e) {
+    echo $e->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