]> granicus.if.org Git - php/commitdiff
Fixed bug #69316 (Use-after-free in php_curl related to CURLOPT_FILE/_INFILE/_WRITEHE...
authorStanislav Malyshev <stas@php.net>
Sat, 4 Apr 2015 22:58:27 +0000 (15:58 -0700)
committerStanislav Malyshev <stas@php.net>
Sun, 5 Apr 2015 07:32:13 +0000 (00:32 -0700)
NEWS
ext/curl/interface.c
ext/curl/tests/bug69316.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 75aa306948e9b1de68a914112e9d8040eaa69c8b..da926d515f3871141b5d5be28c2345ffb95dca9d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,10 @@ PHP                                                                        NEWS
   . Fixed bug #69218 (potential remote code execution with apache 2.4
     apache2handler). (Patrick Schaaf)
 
+- cURL:
+  . Fixed bug #69316 (Use-after-free in php_curl related to CURLOPT_FILE/
+    _INFILE/_WRITEHEADER). (Laruence)
+
 - Fileinfo:
   . Fixed bug #68819 (Fileinfo on specific file causes spurious OOM and/or 
     segfault). (Anatol Belski))
index 0423f71f9a8e35ccb5fa5f6419615cd7c2e151aa..7f8f276791bee0a96293787d831904daada19118 100644 (file)
@@ -1051,6 +1051,7 @@ static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx)
                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_WRITEFUNCTION");
                                length = -1;
                        } else if (retval_ptr) {
+                               _php_curl_verify_handlers(ch, 1 TSRMLS_CC);
                                if (Z_TYPE_P(retval_ptr) != IS_LONG) {
                                        convert_to_long_ex(&retval_ptr);
                                }
@@ -1124,6 +1125,7 @@ static size_t curl_progress(void *clientp, double dltotal, double dlnow, double
                        if (error == FAILURE) {
                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot call the CURLOPT_PROGRESSFUNCTION");
                        } else if (retval_ptr) {
+                               _php_curl_verify_handlers(ch, 1 TSRMLS_CC);
                                if (Z_TYPE_P(retval_ptr) != IS_LONG) {
                                        convert_to_long_ex(&retval_ptr);
                                }
@@ -1200,6 +1202,7 @@ static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx)
                                length = CURL_READFUNC_ABORT;
 #endif
                        } else if (retval_ptr) {
+                               _php_curl_verify_handlers(ch, 1 TSRMLS_CC);
                                if (Z_TYPE_P(retval_ptr) == IS_STRING) {
                                        length = MIN((int) (size * nmemb), Z_STRLEN_P(retval_ptr));
                                        memcpy(data, Z_STRVAL_P(retval_ptr), length);
@@ -1274,6 +1277,7 @@ static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx
                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_HEADERFUNCTION");
                                length = -1;
                        } else if (retval_ptr) {
+                               _php_curl_verify_handlers(ch, 1 TSRMLS_CC);
                                if (Z_TYPE_P(retval_ptr) != IS_LONG) {
                                        convert_to_long_ex(&retval_ptr);
                                }
diff --git a/ext/curl/tests/bug69316.phpt b/ext/curl/tests/bug69316.phpt
new file mode 100644 (file)
index 0000000..0f8106b
--- /dev/null
@@ -0,0 +1,47 @@
+--TEST--
+Bug #69316: Use-after-free in php_curl related to CURLOPT_FILE/_INFILE/_WRITEHEADER
+--SKIPIF--
+<?php 
+if (!extension_loaded("curl")) exit("skip curl extension not loaded");
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER'))  exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+?>
+--FILE--
+<?php
+  function hdr_callback($ch, $data) {
+      // close the stream, causing the FILE structure to be free()'d
+      if($GLOBALS['f_file']) {
+          fclose($GLOBALS['f_file']); $GLOBALS['f_file'] = 0;
+
+          // cause an allocation of approx the same size as a FILE structure, size varies a bit depending on platform/libc
+          $FILE_size = (PHP_INT_SIZE == 4 ? 0x160 : 0x238);
+          curl_setopt($ch, CURLOPT_COOKIE, str_repeat("a", $FILE_size - 1));
+      }
+      return strlen($data);
+  }
+  $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+  
+  $temp_file = dirname(__FILE__) . '/body.tmp';
+  $url = "{$host}/get.php?test=getpost";
+  $ch = curl_init();
+  $f_file = fopen($temp_file, "w") or die("failed to open file\n");
+  curl_setopt($ch, CURLOPT_BUFFERSIZE, 10);
+  curl_setopt($ch, CURLOPT_HEADERFUNCTION, "hdr_callback");
+  curl_setopt($ch, CURLOPT_FILE, $f_file);
+  curl_setopt($ch, CURLOPT_URL, $url);
+  curl_exec($ch);
+  curl_close($ch);
+?>
+===DONE===
+--CLEAN--
+<?php
+unlink(dirname(__FILE__) . '/body.tmp');
+?>
+--EXPECTF--
+Warning: curl_exec(): CURLOPT_FILE resource has gone away, resetting to default in %s on line %d
+array(1) {
+  ["test"]=>
+  string(7) "getpost"
+}
+array(0) {
+}
+===DONE===