Merge branch 'v2.6.x'
authorMichael Wallner <mike@php.net>
Wed, 10 Aug 2016 13:41:09 +0000 (15:41 +0200)
committerMichael Wallner <mike@php.net>
Wed, 10 Aug 2016 13:41:09 +0000 (15:41 +0200)
src/php_http_client.c
src/php_http_client.h
src/php_http_client_curl.c
src/php_http_url.c
tests/gh-issue50.phpt [new file with mode: 0644]

index b719d2f6676b49ae78d9b525c981e1bd1d25daca..d0e6e80107c28dc65de29971d3d348a2689fba86 100644 (file)
@@ -476,7 +476,9 @@ static ZEND_RESULT_CODE handle_response(void *arg, php_http_client_t *client, ph
                        ZVAL_UNDEF(&retval);
                        zend_fcall_info_argn(&e->closure.fci, 1, &zresponse);
                        zend_replace_error_handling(EH_NORMAL, NULL, &zeh);
+                       ++client->callback.depth;
                        zend_fcall_info_call(&e->closure.fci, &e->closure.fcc, &retval, NULL);
+                       --client->callback.depth;
                        zend_restore_error_handling(&zeh);
                        zend_fcall_info_argn(&e->closure.fci, 0);
 
@@ -521,7 +523,9 @@ static void handle_progress(void *arg, php_http_client_t *client, php_http_clien
        add_property_double(&args[1], "ulnow", progress->ul.now);
 
        zend_replace_error_handling(EH_NORMAL, NULL, &zeh);
+       ++client->callback.depth;
        php_http_object_method_call(&client_obj->notify, &zclient, NULL, 2, args);
+       --client->callback.depth;
        zend_restore_error_handling(&zeh);
 
        zval_ptr_dtor(&zclient);
@@ -542,7 +546,9 @@ static void handle_debug(void *arg, php_http_client_t *client, php_http_client_e
 
        zend_replace_error_handling(EH_NORMAL, NULL, &zeh);
        if (SUCCESS == zend_fcall_info_argn(&client_obj->debug.fci, 4, &zclient, &zreq, &ztype, &zdata)) {
+               ++client->callback.depth;
                zend_fcall_info_call(&client_obj->debug.fci, &client_obj->debug.fcc, NULL, NULL);
+               --client->callback.depth;
                zend_fcall_info_args_clear(&client_obj->debug.fci, 0);
        }
        zend_restore_error_handling(&zeh);
index 08743e69ebbaa9188d7a64da3c888bb1b217aa55..0edd1bb1d29d466652a5dc77d89c3b3e9a156c5b 100644 (file)
@@ -117,6 +117,7 @@ typedef struct php_http_client {
                        php_http_client_debug_callback_t func;
                        void *arg;
                } debug;
+               unsigned depth;
        } callback;
 
        zend_llist requests;
index be04be89296d47728cc8aa63571d7675eca35c63..1e92fbe1c1e2bb26053f9b81e5e43b995c3cd8b5 100644 (file)
@@ -177,22 +177,19 @@ static int php_http_curle_progress_callback(void *ctx, double dltotal, double dl
 #endif
 {
        php_http_client_curl_handler_t *h = ctx;
-       zend_bool update = 0;
 
        if (h->progress.dl.total != dltotal
        ||      h->progress.dl.now != dlnow
        ||      h->progress.ul.total != ultotal
        ||      h->progress.ul.now != ulnow
        ) {
-               update = 1;
-
                h->progress.dl.total = dltotal;
                h->progress.dl.now = dlnow;
                h->progress.ul.total = ultotal;
                h->progress.ul.now = ulnow;
        }
 
-       if (update && h->client->callback.progress.func) {
+       if (h->client->callback.progress.func) {
                h->client->callback.progress.func(h->client->callback.progress.arg, h->client, &h->queue, &h->progress);
        }
 
@@ -2195,6 +2192,11 @@ static ZEND_RESULT_CODE php_http_client_curl_dequeue(php_http_client_t *h, php_h
        php_http_client_curl_t *curl = h->ctx;
        php_http_client_curl_handler_t *handler = enqueue->opaque;
 
+       if (h->callback.depth) {
+               php_error_docref(NULL, E_WARNING, "Could not dequeue request while executing callbacks");
+               return FAILURE;
+       }
+
        php_http_client_curl_handler_clear(handler);
        if (CURLM_OK == (rs = curl_multi_remove_handle(curl->handle->multi, handler->handle))) {
                zend_llist_del_element(&h->requests, handler->handle, (int (*)(void *, void *)) compare_queue);
index 8352608982e4ab769dfeccbdea4ae01f47d58f1d..1520ae9cbe747682e70c1aa4d5cac5b5e40a69e6 100644 (file)
@@ -1119,7 +1119,7 @@ static ZEND_RESULT_CODE parse_hostinfo(struct parse_state *state, const char *pt
                                /* sort of a compromise, just ensure we don't end up
                                 * with a hyphen at the beginning
                                 */
-                               php_error_docref(NULL TSRMLS_CC, E_WARNING,
+                               php_error_docref(NULL, E_WARNING,
                                                "Failed to parse %s; unexpected '%c' at pos %u in '%s'",
                                                port ? "port" : "host",
                                                (unsigned char) *ptr, (unsigned) (ptr - tmp), tmp);
diff --git a/tests/gh-issue50.phpt b/tests/gh-issue50.phpt
new file mode 100644 (file)
index 0000000..6cef7d9
--- /dev/null
@@ -0,0 +1,39 @@
+--TEST--
+segfault with Client::setDebug and Client::dequeue()
+--SKIPIF--
+<?php
+include "skipif.inc";
+skip_client_test();
+skip_online_test();
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$c = new http\Client;
+$c->enqueue(new http\Client\Request("GET", "http://example.com"));
+
+$c->setDebug(function(http\Client $c, http\Client\Request $r, $type, $data) {
+    if ($type & http\Client::DEBUG_HEADER) {
+        $c->dequeue($r);
+    }
+});
+
+try {
+       $c->send();
+} catch (Exception $e) {
+       echo $e;
+}
+
+?>
+
+===DONE===
+--EXPECTF--
+Test
+http\Exception\RuntimeException: http\Client::dequeue(): Could not dequeue request while executing callbacks in %sgh-issue50.php:9
+Stack trace:
+#0 %sgh-issue50.php(9): http\Client->dequeue(Object(http\Client\Request))
+#1 [internal function]: {closure}(Object(http\Client), Object(http\Client\Request), 18, 'GET / HTTP/1.1\r...')
+#2 %sgh-issue50.php(14): http\Client->send()
+#3 {main}
+===DONE===