php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #73296 Invalid memory access in spl_filesystem_info_set_filename function
Submitted: 2016-10-11 17:03 UTC Modified: 2016-11-14 11:40 UTC
From: nguyenluan dot vnn at gmail dot com Assigned: stas (profile)
Status: Closed Package: SPL_Types (PECL)
PHP Version: 7.0.11 OS:
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: nguyenluan dot vnn at gmail dot com
New email:
PHP Version: OS:

 

 [2016-10-11 17:03 UTC] nguyenluan dot vnn at gmail dot com
Description:
------------
In function spl_filesystem_info_set_filename:

void spl_filesystem_info_set_filename(spl_filesystem_object *intern, char *path, size_t len, size_t use_copy) /* {{{ */
{
	char *p1, *p2;

	if (intern->file_name) {
		efree(intern->file_name);
	}

	intern->file_name = use_copy ? estrndup(path, len) : path;
	intern->file_name_len = (int)len;  // (1) intern->file_name_len could have very big value after this line

	while (intern->file_name_len > 1 && IS_SLASH_AT(intern->file_name, intern->file_name_len-1)) {  // (2) crash here at IS_SLASH_AT
		intern->file_name[intern->file_name_len-1] = 0;
		intern->file_name_len--;
	}

        ...
        ...
}

After the cast intern->file_name_len = (int)len, intern->file_name_len could have very big value (for example: len = 0x80001004 will make intern->file_name_len = 0xffffffff80001004).

This index is far beyond the input string length so there will be an invalid memory access when execute "IS_SLASH_AT(intern->file_name, intern->file_name_len-1" and cause PHP 7 to crash.

Test script:
---------------
<?php
    ini_set('memory_limit', -1);
    $info = new SplFileInfo(str_repeat('a', 0x80001000).'.foo');

    var_dump(strlen($info->getExtension()));
?>

Expected result:
----------------
No crash.

Actual result:
--------------
gdb-peda$ b spl_directory.c:386
Breakpoint 1 at 0x8428f8: file /home/user/Desktop/php-7.0.11/ext/spl/spl_directory.c, line 386.

gdb-peda$ r ../test/string/test.php 
Starting program: /home/user/Desktop/php-7.0.11/sapi/cli/php ../test/string/test.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

 [----------------------------------registers-----------------------------------]
RAX: 0x7ffeeca00000 ('a' <repeats 200 times>...)
RBX: 0x0 
RCX: 0x6f ('o')
RDX: 0x7fffed278000 --> 0x0 
RSI: 0x7fff6cc00018 ('a' <repeats 200 times>...)
RDI: 0x7ffeeca00000 ('a' <repeats 200 times>...)
RBP: 0x7fffffffa6e0 --> 0x7fffffffa720 --> 0x7fffffffa770 --> 0x7fffffffa7a0 --> 0x7fffffffa7e0 --> 0x7fffffffa8f0 (--> ...)
RSP: 0x7fffffffa6b0 --> 0x1 
RIP: 0x8428f8 (<spl_filesystem_info_set_filename+137>:	)
R8 : 0x8000100 
R9 : 0x8000100 
R10: 0x9 ('\t')
R11: 0x206 
R12: 0x445010 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffe1a0 --> 0x2 
R14: 0x7fffed214030 --> 0x7fffed282160 --> 0xaafc2c (<ZEND_DO_FCALL_SPEC_HANDLER>:	push   rbp)
R15: 0x7fffed282160 --> 0xaafc2c (<ZEND_DO_FCALL_SPEC_HANDLER>:	push   rbp)
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8428ec <spl_filesystem_info_set_filename+125>:	
    mov    rax,QWORD PTR [rbp-0x20]
   0x8428f0 <spl_filesystem_info_set_filename+129>:	
    mov    rdx,QWORD PTR [rbp-0x18]
   0x8428f4 <spl_filesystem_info_set_filename+133>:	
    mov    QWORD PTR [rdx+0x28],rax
=> 0x8428f8 <spl_filesystem_info_set_filename+137>:	
    mov    rax,QWORD PTR [rbp-0x28]
   0x8428fc <spl_filesystem_info_set_filename+141>:	movsxd rdx,eax
   0x8428ff <spl_filesystem_info_set_filename+144>:	
    mov    rax,QWORD PTR [rbp-0x18]
   0x842903 <spl_filesystem_info_set_filename+148>:	
    mov    QWORD PTR [rax+0x30],rdx
   0x842907 <spl_filesystem_info_set_filename+152>:	
    jmp    0x842937 <spl_filesystem_info_set_filename+200>
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffa6b0 --> 0x1 
0008| 0x7fffffffa6b8 --> 0x80001004 
0016| 0x7fffffffa6c0 --> 0x7fff6cc00018 ('a' <repeats 200 times>...)
0024| 0x7fffffffa6c8 --> 0x7fffed278000 --> 0x0 
0032| 0x7fffffffa6d0 --> 0x80001004 
0040| 0x7fffffffa6d8 --> 0x7fffed279090 --> 0x800000002 
0048| 0x7fffffffa6e0 --> 0x7fffffffa720 --> 0x7fffffffa770 --> 0x7fffffffa7a0 --> 0x7fffffffa7e0 --> 0x7fffffffa8f0 (--> ...)
0056| 0x7fffffffa6e8 --> 0x8451c8 (<zim_spl_SplFileInfo___construct+144>:	)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, spl_filesystem_info_set_filename (intern=0x7fffed278000, 
    path=0x7fff6cc00018 'a' <repeats 200 times>..., len=0x80001004, 
    use_copy=0x1) at /home/user/Desktop/php-7.0.11/ext/spl/spl_directory.c:386
386		intern->file_name_len = (int)len;

gdb-peda$ p len
$1 = 0x80001004

gdb-peda$ n

 [----------------------------------registers-----------------------------------]
RAX: 0x7fffed278000 --> 0x0 
RBX: 0x0 
RCX: 0x6f ('o')
RDX: 0xffffffff80001004 
RSI: 0x7fff6cc00018 ('a' <repeats 200 times>...)
RDI: 0x7ffeeca00000 ('a' <repeats 200 times>...)
RBP: 0x7fffffffa6e0 --> 0x7fffffffa720 --> 0x7fffffffa770 --> 0x7fffffffa7a0 --> 0x7fffffffa7e0 --> 0x7fffffffa8f0 (--> ...)
RSP: 0x7fffffffa6b0 --> 0x1 
RIP: 0x842907 (<spl_filesystem_info_set_filename+152>:	)
R8 : 0x8000100 
R9 : 0x8000100 
R10: 0x9 ('\t')
R11: 0x206 
R12: 0x445010 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffe1a0 --> 0x2 
R14: 0x7fffed214030 --> 0x7fffed282160 --> 0xaafc2c (<ZEND_DO_FCALL_SPEC_HANDLER>:	push   rbp)
R15: 0x7fffed282160 --> 0xaafc2c (<ZEND_DO_FCALL_SPEC_HANDLER>:	push   rbp)
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8428fc <spl_filesystem_info_set_filename+141>:	movsxd rdx,eax
   0x8428ff <spl_filesystem_info_set_filename+144>:	
    mov    rax,QWORD PTR [rbp-0x18]
   0x842903 <spl_filesystem_info_set_filename+148>:	
    mov    QWORD PTR [rax+0x30],rdx
=> 0x842907 <spl_filesystem_info_set_filename+152>:	
    jmp    0x842937 <spl_filesystem_info_set_filename+200>
   0x842909 <spl_filesystem_info_set_filename+154>:	
    mov    rax,QWORD PTR [rbp-0x18]
   0x84290d <spl_filesystem_info_set_filename+158>:	
    mov    rdx,QWORD PTR [rax+0x28]
   0x842911 <spl_filesystem_info_set_filename+162>:	
    mov    rax,QWORD PTR [rbp-0x18]
   0x842915 <spl_filesystem_info_set_filename+166>:	
    mov    rax,QWORD PTR [rax+0x30]
                                                              JUMP is NOT taken
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffa6b0 --> 0x1 
0008| 0x7fffffffa6b8 --> 0x80001004 
0016| 0x7fffffffa6c0 --> 0x7fff6cc00018 ('a' <repeats 200 times>...)
0024| 0x7fffffffa6c8 --> 0x7fffed278000 --> 0x0 
0032| 0x7fffffffa6d0 --> 0x80001004 
0040| 0x7fffffffa6d8 --> 0x7fffed279090 --> 0x800000002 
0048| 0x7fffffffa6e0 --> 0x7fffffffa720 --> 0x7fffffffa770 --> 0x7fffffffa7a0 --> 0x7fffffffa7e0 --> 0x7fffffffa8f0 (--> ...)
0056| 0x7fffffffa6e8 --> 0x8451c8 (<zim_spl_SplFileInfo___construct+144>:	)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
388		while (intern->file_name_len > 1 && IS_SLASH_AT(intern->file_name, intern->file_name_len-1)) {

gdb-peda$ p intern->file_name_len
$2 = 0xffffffff80001004  // value after casting

gdb-peda$ c
Continuing.

Program received signal SIGSEGV, Segmentation fault.

 [----------------------------------registers-----------------------------------]
RAX: 0x7ffe6ca01003 
RBX: 0x0 
RCX: 0x6f ('o')
RDX: 0x7ffeeca00000 ('a' <repeats 200 times>...)
RSI: 0x7fff6cc00018 ('a' <repeats 200 times>...)
RDI: 0x7ffeeca00000 ('a' <repeats 200 times>...)
RBP: 0x7fffffffa6e0 --> 0x7fffffffa720 --> 0x7fffffffa770 --> 0x7fffffffa7a0 --> 0x7fffffffa7e0 --> 0x7fffffffa8f0 (--> ...)
RSP: 0x7fffffffa6b0 --> 0x1 
RIP: 0x84295c (<spl_filesystem_info_set_filename+237>:	)
R8 : 0x8000100 
R9 : 0x8000100 
R10: 0x9 ('\t')
R11: 0x206 
R12: 0x445010 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffe1a0 --> 0x2 
R14: 0x7fffed214030 --> 0x7fffed282160 --> 0xaafc2c (<ZEND_DO_FCALL_SPEC_HANDLER>:	push   rbp)
R15: 0x7fffed282160 --> 0xaafc2c (<ZEND_DO_FCALL_SPEC_HANDLER>:	push   rbp)
EFLAGS: 0x10207 (CARRY PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x842951 <spl_filesystem_info_set_filename+226>:	
    mov    rax,QWORD PTR [rax+0x30]
   0x842955 <spl_filesystem_info_set_filename+230>:	sub    rax,0x1
   0x842959 <spl_filesystem_info_set_filename+234>:	add    rax,rdx
=> 0x84295c <spl_filesystem_info_set_filename+237>:	
    movzx  eax,BYTE PTR [rax]
   0x84295f <spl_filesystem_info_set_filename+240>:	cmp    al,0x2f
   0x842961 <spl_filesystem_info_set_filename+242>:	
    je     0x842909 <spl_filesystem_info_set_filename+154>
   0x842963 <spl_filesystem_info_set_filename+244>:	
    mov    rax,QWORD PTR [rbp-0x18]
   0x842967 <spl_filesystem_info_set_filename+248>:	
    mov    rax,QWORD PTR [rax+0x28]
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffa6b0 --> 0x1 
0008| 0x7fffffffa6b8 --> 0x80001004 
0016| 0x7fffffffa6c0 --> 0x7fff6cc00018 ('a' <repeats 200 times>...)
0024| 0x7fffffffa6c8 --> 0x7fffed278000 --> 0x0 
0032| 0x7fffffffa6d0 --> 0x80001004 
0040| 0x7fffffffa6d8 --> 0x7fffed279090 --> 0x800000002 
0048| 0x7fffffffa6e0 --> 0x7fffffffa720 --> 0x7fffffffa770 --> 0x7fffffffa7a0 --> 0x7fffffffa7e0 --> 0x7fffffffa8f0 (--> ...)
0056| 0x7fffffffa6e8 --> 0x8451c8 (<zim_spl_SplFileInfo___construct+144>:	)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x000000000084295c in spl_filesystem_info_set_filename (intern=0x7fffed278000, 
    path=0x7fff6cc00018 'a' <repeats 200 times>..., len=0x80001004, 
    use_copy=0x1) at /home/user/Desktop/php-7.0.11/ext/spl/spl_directory.c:388
388		while (intern->file_name_len > 1 && IS_SLASH_AT(intern->file_name, intern->file_name_len-1)) {

gdb-peda$ bt
#0  0x000000000084295c in spl_filesystem_info_set_filename (
    intern=0x7fffed278000, path=0x7fff6cc00018 'a' <repeats 200 times>..., 
    len=0x80001004, use_copy=0x1)
    at /home/user/Desktop/php-7.0.11/ext/spl/spl_directory.c:388
#1  0x00000000008451c8 in zim_spl_SplFileInfo___construct (
    execute_data=0x7fffed214130, return_value=0x7fffed2140e0)
    at /home/user/Desktop/php-7.0.11/ext/spl/spl_directory.c:1118
#2  0x0000000000ab00e1 in ZEND_DO_FCALL_SPEC_HANDLER ()
    at /home/user/Desktop/php-7.0.11/Zend/zend_vm_execute.h:842
#3  0x0000000000aaef61 in execute_ex (ex=0x7fffed214030)
    at /home/user/Desktop/php-7.0.11/Zend/zend_vm_execute.h:414
#4  0x0000000000aaf072 in zend_execute (op_array=0x7fffed281000, 
    return_value=0x0)
    at /home/user/Desktop/php-7.0.11/Zend/zend_vm_execute.h:458
#5  0x0000000000a5014b in zend_execute_scripts (type=0x8, retval=0x0, 
    file_count=0x3) at /home/user/Desktop/php-7.0.11/Zend/zend.c:1427
#6  0x00000000009b8557 in php_execute_script (primary_file=0x7fffffffce20)
    at /home/user/Desktop/php-7.0.11/main/main.c:2494
#7  0x0000000000b18327 in do_cli (argc=0x2, argv=0x146e560)
    at /home/user/Desktop/php-7.0.11/sapi/cli/php_cli.c:974
#8  0x0000000000b194f5 in main (argc=0x2, argv=0x146e560)
    at /home/user/Desktop/php-7.0.11/sapi/cli/php_cli.c:1344
#9  0x00007ffff416f830 in __libc_start_main (main=0xb18cea <main>, argc=0x2, 
    argv=0x7fffffffe1a8, init=<optimized out>, fini=<optimized out>, 
    rtld_fini=<optimized out>, stack_end=0x7fffffffe198)
    at ../csu/libc-start.c:291
#10 0x0000000000445039 in _start ()


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-11-05 21:50 UTC] stas@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: stas
 [2016-11-05 21:50 UTC] stas@php.net
The fix for this bug has been committed.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.
 [2016-11-11 13:07 UTC] nguyenluan dot vnn at gmail dot com
-Status: Closed +Status: Assigned
 [2016-11-11 13:07 UTC] nguyenluan dot vnn at gmail dot com
Still crash in version 7.0.13. Please check again.
 [2016-11-11 13:07 UTC] nguyenluan dot vnn at gmail dot com
-Status: Assigned +Status: Open
 [2016-11-11 13:07 UTC] nguyenluan dot vnn at gmail dot com
Open again.
 [2016-11-14 11:40 UTC] nguyenluan dot vnn at gmail dot com
-Status: Open +Status: Closed
 [2016-11-14 11:40 UTC] nguyenluan dot vnn at gmail dot com
Fixed in PHP 7.1.0 RC6. Please close.

Thanks.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 09:01:26 2024 UTC