|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2016-08-04 06:15 UTC] stas@php.net
-Type: Security
+Type: Bug
[2016-08-04 11:11 UTC] laruence@php.net
[2016-08-04 11:11 UTC] laruence@php.net
-Status: Open
+Status: Closed
[2016-10-17 10:10 UTC] bwoebi@php.net
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Mon Oct 27 00:00:01 2025 UTC |
Description: ------------ Actually OOB read occurs within zend_inline_hash_func when the len is casting from negative integer to size_t. <snippet main\streams\filter.c:250> PHPAPI php_stream_filter *php_stream_filter_create(const char *filtername, zval *filterparams, int persistent) { HashTable *filter_hash = (FG(stream_filters) ? FG(stream_filters) : &stream_filters_hash); php_stream_filter_factory *factory = NULL; php_stream_filter *filter = NULL; int n; char *period; n = (int)strlen(filtername); //n become negative if (NULL != (factory = zend_hash_str_find_ptr(filter_hash, filtername, n))) { //parameter expect 64 bit size_t </snippet> <snippet Zend/zend_string.h:325> static zend_always_inline zend_ulong zend_inline_hash_func(const char *str, size_t len) { zend_ulong hash = Z_UL(5381); /* variant with the hash unrolled eight times */ for (; len >= 8; len -= 8) { //len here is 64bit and very big hash = ((hash << 5) + hash) + *str++; </snippet> proposed patch below only patch the filter_create function. zend_inline_hash_func may need a proper check too, but I don't know how: --- a/main/streams/filter.c +++ b/main/streams/filter.c @@ -252,10 +252,10 @@ PHPAPI php_stream_filter *php_stream_filter_create(const char *filtername, zval HashTable *filter_hash = (FG(stream_filters) ? FG(stream_filters) : &stream_filters_hash); php_stream_filter_factory *factory = NULL; php_stream_filter *filter = NULL; - int n; + size_t n; char *period; - n = (int)strlen(filtername); + n = strlen(filtername); if (NULL != (factory = zend_hash_str_find_ptr(filter_hash, filtername, n))) { filter = factory->create_filter(filtername, filterparams, persistent); Test script: --------------- <?php ini_set('memory_limit',-1); $fp = fopen('php://filter/'.str_repeat("A",0x80000000).'/resource=foo', 'w+'); ?> Expected result: ---------------- PHP Warning: fopen(): unable to locate filter Actual result: -------------- Stopped reason: SIGSEGV 0x000000000085ef0f in zend_inline_hash_func (str=0x7ffff5a01001 <error: Cannot access memory at address 0x7ffff5a01001>, len=0xfffffffefffff008) at /home/vps/git/php-src/Zend/zend_string.h:338 338 hash = ((hash << 5) + hash) + *str++; gdb-peda$ bt #0 0x000000000085ef0f in zend_inline_hash_func (str=0x7ffff5a01001 <error: Cannot access memory at address 0x7ffff5a01001>, len=0xfffffffefffff008) at /home/vps/git/php-src/Zend/zend_string.h:338 #1 0x0000000000864f09 in zend_hash_str_find (ht=0x10cac80 <stream_filters_hash>, str=0x7fff75a00001 'A' <repeats 200 times>..., len=0xffffffff80000000) at /home/vps/git/php-src/Zend/zend_hash.c:1967 #2 0x00000000007ddce0 in zend_hash_str_find_ptr (ht=0x10cac80 <stream_filters_hash>, str=0x7fff75a00001 'A' <repeats 200 times>..., len=0xffffffff80000000) at /home/vps/git/php-src/Zend/zend_hash.h:717 #3 0x00000000007de76e in php_stream_filter_create (filtername=0x7fff75a00001 'A' <repeats 200 times>..., filterparams=0x0, persistent=0x0) at /home/vps/git/php-src/main/streams/filter.c:260 #4 0x000000000078a370 in php_stream_apply_filter_list (stream=0x7ffff685fb40, filterlist=0x7fff75a00001 'A' <repeats 200 times>..., read_chain=0x1, write_chain=0x2) at /home/vps/git/php-src/ext/standard/php_fopen_wrapper.c:156 #5 0x000000000078af78 in php_stream_url_wrap_php (wrapper=0x10a6950 <php_stream_php_wrapper>, path=0x7ffef580001e "filter/", 'A' <repeats 193 times>..., mode=0x7ffff6858d58 "w+", options=0x0, opened_path=0x0, context=0x7ffff6858e00, __php_stream_call_depth=0x1, __zend_filename=0xd723f8 "/home/vps/git/php-src/main/streams/streams.c", __zend_lineno=0x809, __zend_orig_filename=0xd550d0 "/home/vps/git/php-src/ext/standard/file.c", __zend_orig_lineno=0x366) at /home/vps/git/php-src/ext/standard/php_fopen_wrapper.c:375 #6 0x00000000007da8db in _php_stream_open_wrapper_ex (path=0x7ffef5800018 "php://filter/", 'A' <repeats 187 times>..., mode=0x7ffff6858d58 "w+", options=0x8, opened_path=0x0, context=0x7ffff6858e00, __php_stream_call_depth=0x0, __zend_filename=0xd550d0 "/home/vps/git/php-src/ext/standard/file.c", __zend_lineno=0x366, __zend_orig_filename=0x0, __zend_orig_lineno=0x0) at /home/vps/git/php-src/main/streams/streams.c:2055 #7 0x0000000000730e32 in php_if_fopen (execute_data=0x7ffff6814110, return_value=0x7ffff68140d0) at /home/vps/git/php-src/ext/standard/file.c:870 #8 0x0000000000670167 in phar_fopen (execute_data=0x7ffff6814110, return_value=0x7ffff68140d0) at /home/vps/git/php-src/ext/phar/func_interceptors.c:427 #9 0x00000000008ae50b in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER () at /home/vps/git/php-src/Zend/zend_vm_execute.h:675 #10 0x00000000008adc2e in execute_ex (ex=0x7ffff6814030) at /home/vps/git/php-src/Zend/zend_vm_execute.h:429 #11 0x00000000008add40 in zend_execute (op_array=0x7ffff687d000, return_value=0x0) at /home/vps/git/php-src/Zend/zend_vm_execute.h:474 #12 0x000000000084e490 in zend_execute_scripts (type=0x8, retval=0x0, file_count=0x3) at /home/vps/git/php-src/Zend/zend.c:1447 #13 0x00000000007b9126 in php_execute_script (primary_file=0x7fffffffd6c0) at /home/vps/git/php-src/main/main.c:2533 #14 0x000000000092d910 in do_cli (argc=0x2, argv=0x10d5770) at /home/vps/git/php-src/sapi/cli/php_cli.c:990 #15 0x000000000092ead4 in main (argc=0x2, argv=0x10d5770) at /home/vps/git/php-src/sapi/cli/php_cli.c:1378 #16 0x00007ffff6faaf45 in __libc_start_main (main=0x92e2cc <main>, argc=0x2, argv=0x7fffffffea68, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffea58) at libc-start.c:287 #17 0x0000000000422ca9 in _start ()