Bug #76675 [Csd]: Segfault with H2 server push

From: Date: Fri, 03 May 2019 13:39:06 +0000
Subject: Bug #76675 [Csd]: Segfault with H2 server push
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-220685@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=76675&edit=1 ID: 76675 Updated by: cmb@php.net Reported by: tobias dot nyholm at gmail dot com Summary: Segfault with H2 server push Status: Closed Type: Bug Package: cURL related Operating System: OSX PHP Version: 7.2.8 -Assigned To: +Assigned To: cmb Block user comment: N Private report: N New Comment: > The failing script uses pipelining. No, see <https://github.com/winlibs/cURL/pull/12#issuecomment-489097607>. Previous Comments: ------------------------------------------------------------------------ [2019-04-23 05:57:47] phpdev at ehrhardt dot nl The failing script uses pipelining. This has been removed from curl now: https://github.com/curl/curl/commit/2f44e94efb3df8e50bb2ddbc4ec6b569a6424517 Remark by Daniel Stenberg (5 days ago, see last coment in that issue) about pipelining: I know for a fact that it is not used a lot with curl. I can be sure of this since we know the pipelining code had a few rather nasty known issues and yet hardly anyone reported problems with those. Or any other problems that relate to pipelining. All indications that it isn't a much used feature. ------------------------------------------------------------------------ [2019-01-18 11:07:30] nikic@php.net Automatic comment on behalf of pmmaga Revision: http://git.php.net/?p=php-src.git;a=commit;h=32ae7160377e9548dcf27ff3e0e75c3c9cd3c36c Log: Fixed bug #76675 ------------------------------------------------------------------------ [2018-07-29 11:42:21] rasmus@php.net In that backtrace, ch looks like a valid curl handle, but ch->res is null at that point. (gdb) p ch $1 = (php_curl *) 0x7fffec265c80 (gdb) p *ch $2 = {cp = 0x5555569af080, handlers = 0x7fffec25f348, res = 0x0, to_free = 0x7fffec28f000, header = {str = 0x0}, err = {str = '\000' <repeats 256 times>, no = 0}, in_callback = 0 '\000', clone = 0x7fffec28a010} ------------------------------------------------------------------------ [2018-07-29 11:36:57] rasmus@php.net I am able to reproduce the segfault. Interestingly it doesn't crash under Valgrind, nor is it giving me any clues about the crash, which is odd. The gdb backtrace is useful though (against 7.3): Thread 1 "php" received signal SIGSEGV, Segmentation fault. curl_write_header (data=0x555557c48c60 "HTTP/2 200 \r\n", size=1, nmemb=13, ctx=0x7fffec266040) at /home/rasmus/php-src/ext/curl/interface.c:1654 1654 GC_ADDREF(ch->res); (gdb) bt #0 curl_write_header (data=0x555557c48c60 "HTTP/2 200 \r\n", size=1, nmemb=13, ctx=0x7fffec266040) at /home/rasmus/php-src/ext/curl/interface.c:1654 #1 0x00007ffff36f22bd in ?? () from /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 #2 0x00007ffff36f0754 in ?? () from /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 #3 0x00007ffff3709a78 in ?? () from /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 #4 0x00007ffff3714726 in ?? () from /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 #5 0x00007ffff3715361 in curl_multi_perform () from /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 #6 0x0000555555838f4e in zif_curl_multi_exec (execute_data=<optimized out>, return_value=0x7fffec21d190) at /home/rasmus/php-src/ext/curl/multi.c:278 #7 0x0000555555ba64e8 in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER () at /home/rasmus/php-src/Zend/zend_vm_execute.h:690 #8 execute_ex (ex=0x28) at /home/rasmus/php-src/Zend/zend_vm_execute.h:54894 #9 0x0000555555baef55 in zend_execute (op_array=op_array@entry=0x7fffec27d2a0, return_value=return_value@entry=0x7fffdc0d58d8) at /home/rasmus/php-src/Zend/zend_vm_execute.h:60326 #10 0x0000555555b23f65 in zend_execute_scripts (type=-333328176, type@entry=8, retval=0x7fffdc0d58d8, retval@entry=0x0, file_count=file_count@entry=3) at /home/rasmus/php-src/Zend/zend.c:1564 #11 0x0000555555ac6b50 in php_execute_script (primary_file=0x7fffffffcf10) at /home/rasmus/php-src/main/main.c:2608 #12 0x0000555555bb12dd in do_cli (argc=2, argv=0x555556706330) at /home/rasmus/php-src/sapi/cli/php_cli.c:1002 #13 0x00005555556cba76 in main (argc=2, argv=0x555556706330) at /home/rasmus/php-src/sapi/cli/php_cli.c:1395 ------------------------------------------------------------------------ [2018-07-28 00:12:09] tobias dot nyholm at gmail dot com Description: ------------ When experimenting with HTTP2 server push I found some issues. 1) It does not work when using CURLOPT_TIMEOUT 2) Segmentation fault when using CURLOPT_WRITEFUNCTION and CURLOPT_HEADERFUNCTION 3) Segmentation fault when using CURLOPT_WRITEFUNCTION and CURLOPT_HEADERFUNCTION in CURLMOPT_PUSHFUNCTION. I started with a working example provided by Davey: https://github.com/dshafik/php-http2-push-example Please note my 3 FIXME comments in the test script. Im on PHP 7.2.8 with cUrl 7.61.0. Test script: --------------- <?php $urls = []; function parseUrl($headers, $handle) { global $urls; foreach ($headers as $header) { if (strpos($header, ':path:') === 0) { $path = substr($header, 6); $url = curl_getinfo($handle)['url']; $url = str_replace( parse_url($url, PHP_URL_PATH), $path, $url ); $urls[$url] = $handle; } } } function getUrl($handle) { $found = false; global $urls; foreach ($urls as $url => $h) { if ($handle == $h) { $found = $url; } } if (!$found) { $found = curl_getinfo($handle)['url']; } return $found; } function get_request($url) { $cb = function ($parent, $pushed, $headers) { curl_setopt($pushed, CURLOPT_RETURNTRANSFER, true); curl_setopt($pushed, CURLOPT_HEADER, true); //FIXME These two lines will cause segmentation fault //curl_setopt($pushed, CURLOPT_HEADERFUNCTION, null); //curl_setopt($pushed, CURLOPT_WRITEFUNCTION, null); parseUrl($headers, $pushed); return CURL_PUSH_OK; }; $mh = curl_multi_init(); curl_multi_setopt($mh, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); curl_multi_setopt($mh, CURLMOPT_PUSHFUNCTION, $cb); $curl = curl_init(); curl_reset($curl); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false); curl_setopt($curl, CURLOPT_MAXREDIRS, 0); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 1); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($curl, CURLOPT_HTTPGET, true); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, true); curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); curl_setopt($curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); curl_setopt($curl, CURLOPT_HEADER, false); curl_setopt($curl, CURLOPT_FAILONERROR, false); $originalResponseContent = ''; //FIXME Using timeout will weirdly disable pushed responses (content will be empty) //curl_setopt($curl, CURLOPT_TIMEOUT, 30); // ----------- curl_setopt($curl, CURLOPT_RETURNTRANSFER, false); //FIXME These 2 lines will case segmentation fault curl_setopt($curl, CURLOPT_HEADERFUNCTION, function ($ch, $data) { return strlen($data); }); curl_setopt($curl, CURLOPT_WRITEFUNCTION, function ($ch, $data) use (&$originalResponseContent) { $originalResponseContent .= $data; return strlen($data); }); curl_multi_add_handle($mh, $curl); // Start fetching the responses. $content = null; $active = null; do { $mrc = curl_multi_exec($mh, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM); while ($active && $mrc == CURLM_OK) { curl_multi_select($mh); do { $mrc = curl_multi_exec($mh, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM); while ($info = curl_multi_info_read($mh)) { if ($info['msg'] == CURLMSG_DONE) { $handle = $info['handle']; if ($handle !== null) { $content = curl_multi_getcontent($handle); $url = getUrl($handle); // Debug echo strlen($content).': '.$url."\n"; curl_multi_remove_handle($mh, $handle); curl_close($handle); } } } } curl_multi_close($mh); return $originalResponseContent; } $url = 'https://http2.golang.org/serverpush'; $response = get_request($url); echo strlen($response).': '.$url."\n\n"; ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=76675&edit=1

« previous php.bugs (#220685) next »