|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #69100 Bus error from stream_copy_to_stream (file -> SSL stream) with invalid length
Submitted: 2015-02-22 01:16 UTC Modified: -
From: zingaburga at hotmail dot com Assigned:
Status: Open Package: Streams related
PHP Version: 5.6.6 OS: Debian 7 amd64
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2015-02-22 01:16 UTC] zingaburga at hotmail dot com
It seems that a Bus error can be generated by stream_copy_to_stream, when copying to a SSL stream if the given length exceeds the available remaining data.

I've successfully replicated the problem on a few machines, using the exact parameters below, all running Debian 7 x86-64, on both PHP 5.5 and 5.6, although it doesn't seem to occur _everywhere_.

I haven't experimented, but I suspect it may be something to do with mmap and the range check.

From main/streams/plain_wrapper.c:

		do_fstat(data, 1);
		if (range->length == 0 && range->offset > 0 && range->offset < data->sb.st_size) {
			range->length = data->sb.st_size - range->offset;
		if (range->length == 0 || range->length > data->sb.st_size) {
			range->length = data->sb.st_size;
		if (range->offset >= data->sb.st_size) {
			range->offset = data->sb.st_size;
			range->length = 0;

It doesn't look like range->length is ever checked against range->offset+data->sb.st_size, hence it's possible for php_stdiop_set_option to claim that more memory was mapped than actually was.  This can cause invalid memory errors when the buffer is read.

And for reference's sake, it seems that sending the file over HTTP is also problematic, though you won't get a crash:

Notice: stream_copy_to_stream(): send of 8192 bytes failed with errno=14 Bad address in /root/b.php on line 9

Test script:

// create an TLS stream to localhost:443 (this means you need a server listening there)
$context = stream_context_create();
stream_context_set_option($context, 'ssl', 'verify_peer', false);
$fw = stream_socket_client('tls://localhost:443', $null, $null, 5, STREAM_CLIENT_CONNECT, $context);
fwrite($fw, "POST /null.php HTTP/1.1\r\nHost: localhost\r\nContent-Length: 1073741824\r\n\r\n");

// the file './data' needs to be 8383276 bytes long, can be created via 'dd if=/dev/zero of=data count=1 bs=8383276'
$fr = fopen('./data', 'rb');

// copy
var_dump(stream_copy_to_stream($fr, $fw, 7340032));
var_dump(stream_copy_to_stream($fr, $fw, 1048576)); // causes Bus Error as it overflows the file's size

Expected result:

Actual result:

Program received signal SIGBUS, Bus error.
__memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:36
36      ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S: No such file or directory.

----- BACKTRACE -----

#0  __memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:36
#1  0x00007ffff70e9c7c in memcpy (__len=8192, __src=0x7fffec514000, __dest=<optimized out>)
    at /usr/include/x86_64-linux-gnu/bits/string3.h:51
#2  do_ssl3_write (s=s@entry=0x1229b40, type=type@entry=23, buf=buf@entry=0x7fffec514000 "", len=8192,
    create_empty_fragment=create_empty_fragment@entry=0) at s3_pkt.c:836
#3  0x00007ffff70e9e24 in ssl3_write_bytes (s=0x1229b40, type=23, buf_=0x7fffec514000, len=<optimized out>)
    at s3_pkt.c:646
#4  0x0000000000479878 in php_openssl_sockop_write (stream=0x7ffff7fceb18, buf=0x7fffec514000 "",
    count=<optimized out>) at /usr/src/php5.6/nonzts/source/dotdeb-php5/ext/openssl/xp_ssl.c:1786
#5  0x000000000068d25e in _php_stream_write_buffer (stream=0x7ffff7fceb18, buf=0x7fffec514000 "", count=8192)
    at /usr/src/php5.6/nonzts/source/dotdeb-php5/main/streams/streams.c:1133
#6  0x000000000068f8df in _php_stream_copy_to_stream_ex (src=src@entry=0x7ffff7fcff10, dest=dest@entry=0x7ffff7fceb18,
    maxlen=1048576, len=len@entry=0x7fffffffac98)
    at /usr/src/php5.6/nonzts/source/dotdeb-php5/main/streams/streams.c:1536
#7  0x000000000065015f in zif_stream_copy_to_stream (ht=<optimized out>, return_value=0x7ffff7fcd768,
    return_value_ptr=<optimized out>, this_ptr=<optimized out>, return_value_used=<optimized out>)
    at /usr/src/php5.6/nonzts/source/dotdeb-php5/ext/standard/streamsfuncs.c:477
#8  0x00000000006c9919 in dtrace_execute_internal (execute_data_ptr=<optimized out>, fci=<optimized out>,
    return_value_used=<optimized out>) at /usr/src/php5.6/nonzts/source/dotdeb-php5/Zend/zend_dtrace.c:97
#9  0x000000000077d1e1 in zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7f9b268)
    at /usr/src/php5.6/nonzts/source/dotdeb-php5/Zend/zend_vm_execute.h:560
#10 0x0000000000743a88 in execute_ex (execute_data=0x7ffff7f9b268)
    at /usr/src/php5.6/nonzts/source/dotdeb-php5/Zend/zend_vm_execute.h:363
#11 0x00000000006c97ed in dtrace_execute_ex (execute_data=<optimized out>)
    at /usr/src/php5.6/nonzts/source/dotdeb-php5/Zend/zend_dtrace.c:73
#12 0x00000000006dc028 in zend_execute_scripts (type=type@entry=8, retval=retval@entry=0x0,
    file_count=file_count@entry=3) at /usr/src/php5.6/nonzts/source/dotdeb-php5/Zend/zend.c:1341
#13 0x000000000067796c in php_execute_script (primary_file=primary_file@entry=0x7fffffffd250)
    at /usr/src/php5.6/nonzts/source/dotdeb-php5/main/main.c:2584
#14 0x0000000000780783 in do_cli (argc=2, argv=0xedd990)
    at /usr/src/php5.6/nonzts/source/dotdeb-php5/sapi/cli/php_cli.c:994
#15 0x0000000000433b7f in main (argc=2, argv=0xedd990)
    at /usr/src/php5.6/nonzts/source/dotdeb-php5/sapi/cli/php_cli.c:1378


Add a Patch

Pull Requests

Add a Pull Request

PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Sun Jun 16 20:01:28 2019 UTC