php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #71300 Segfault in zend_fetch_string_offset
Submitted: 2016-01-07 06:47 UTC Modified: 2016-01-07 15:00 UTC
From: stas@php.net Assigned: laruence
Status: Closed Package: Reproducible crash
PHP Version: 7.0.2RC1 OS: Darwin
Private report: No CVE-ID:
 [2016-01-07 06:47 UTC] stas@php.net
Description:
------------
The following code segaults on 7.x, doesn't on 5.x. Original report by Brian Carpenter.

Test script:
---------------
<?php
for($s=STR;26>$x-=!$c=$s[$$x];)
	echo $$s = $s[$$x++] = ++$c;


Expected result:
----------------
(a lot of garbage, no segfault)

Actual result:
--------------
TUS1VT1WU1XV1YW1ZX1AY1BZ1CA1DB1EC1FD1GE1HF1IG1JH1KI1LJ1MK1NL1OM1PN1QO1RP1SQ1TR1US1VT1WU1XV1YW1ZX1AY1BZ1CA1DB1EC1FD1GE1HF1IG1JH1KI1LJ1MK1NL1OM1PN1QO1RP1SQ1TR1US1VT1WU1XV1YW1ZX1AY1BZ1CA1DB1EC1FD1GE1HF1IG1JH1KI1LJ1MK1NL1OM1PN1QO1RP1SQ1TR1US1VT1WU1XV1YW1ZX1AY1BZ1CA1DB1EC1FD1GE1HF1IG1JH1KI1LJ1MK1NL1OM1PN1QO1RP1SQ1TR1US1VT1WU1XV1YW1ZX1AY1BZ1CA1DB1EC1FD1GE1HF1IG1JH1KI1LJ1MK1NL1OM1PN1QO1R-
Program received signal SIGSEGV, Segmentation fault.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-01-07 06:48 UTC] stas@php.net
-Assigned To: +Assigned To: laruence
 [2016-01-07 06:48 UTC] stas@php.net
Backtrace:

Program received signal SIGSEGV, Segmentation fault.
0x0000000100713591 in zend_mm_alloc_small (heap=<optimized out>, size=386504, bin_num=<optimized out>, heap=<optimized out>, size=386504, bin_num=<optimized out>)
    at /Users/smalyshev/php-7.0/Zend/zend_alloc.c:1291
1291			heap->free_slot[bin_num] = p->next_free_slot;
(gdb) bt
#0  0x0000000100713591 in zend_mm_alloc_small (heap=<optimized out>, size=386504, bin_num=<optimized out>, heap=<optimized out>, size=386504, bin_num=<optimized out>)
    at /Users/smalyshev/php-7.0/Zend/zend_alloc.c:1291
#1  zend_mm_alloc_heap (heap=<optimized out>, size=<optimized out>, heap=<optimized out>, size=<optimized out>) at /Users/smalyshev/php-7.0/Zend/zend_alloc.c:1358
#2  _emalloc (size=32) at /Users/smalyshev/php-7.0/Zend/zend_alloc.c:2442
#3  0x00000001007609cc in zend_string_alloc (len=3, persistent=0) at /Users/smalyshev/php-7.0/Zend/zend_string.h:121
#4  zend_string_init (str=0x103478eb8 "1R-", len=3, persistent=0) at /Users/smalyshev/php-7.0/Zend/zend_string.h:157
#5  zend_string_dup (s=0x103478ea0, persistent=0) at /Users/smalyshev/php-7.0/Zend/zend_string.h:177
#6  _zval_copy_ctor_func (zvalue=0x103415090) at /Users/smalyshev/php-7.0/Zend/zend_variables.c:226
#7  0x00000001008f5234 in zend_fetch_string_offset (container=<optimized out>, dim=<optimized out>, type=<optimized out>, container=<optimized out>, 
    dim=<optimized out>, type=<optimized out>) at /Users/smalyshev/php-7.0/Zend/zend_execute.c:1688
#8  ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_HANDLER (execute_data=0x103415030) at /Users/smalyshev/php-7.0/Zend/zend_vm_execute.h:39361
#9  0x000000010080c4a4 in execute_ex (ex=0x103415030) at /Users/smalyshev/php-7.0/Zend/zend_vm_execute.h:417
#10 0x000000010080cf88 in zend_execute (op_array=0x1034742a0, return_value=0x0) at /Users/smalyshev/php-7.0/Zend/zend_vm_execute.h:458
#11 0x0000000100765667 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /Users/smalyshev/php-7.0/Zend/zend.c:1428
#12 0x000000010068a33f in php_execute_script (primary_file=0x7fff5fbfed40) at /Users/smalyshev/php-7.0/main/main.c:2471
#13 0x000000010094083b in do_cli (argc=2, argv=0x103300cb0) at /Users/smalyshev/php-7.0/sapi/cli/php_cli.c:974
#14 0x000000010093f3a3 in main (argc=2, argv=0x103300cb0) at /Users/smalyshev/php-7.0/sapi/cli/php_cli.c:1345
(gdb)
 [2016-01-07 09:13 UTC] laruence@php.net
An simple fix would be:
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 44ae08d..bd34074 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -2535,8 +2535,8 @@ void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
        switch (var_ast->kind) {
                case ZEND_AST_VAR:
                case ZEND_AST_STATIC_PROP:
-                   zend_compile_var(&var_node, var_ast, BP_VAR_W);
                        zend_compile_expr(&expr_node, expr_ast);
+                 zend_compile_var(&var_node, var_ast, BP_VAR_W);
                        zend_emit_op(result, ZEND_ASSIGN, &var_node, &expr_node);
                        return;
                case ZEND_AST_DIM:


but this will break the evaluate order of assign operator (from right-to-left to left-to-rgith).

so I am not sure, need think another way maybe :<
 [2016-01-07 10:17 UTC] nikic@php.net
@laruence: This is what delayed_compile_var is for (not sure if it support delayed simple fetches yet): To keep order of evaluation of dependent expressions, but do the actual FETCH_Ws last.
 [2016-01-07 14:38 UTC] laruence@php.net
yeah, that is what I was trying, but I find another problem with +=.

digging that togther
 [2016-01-07 15:00 UTC] laruence@php.net
okey, that one became more complicated, I submit a new entry in #71303, will fix this one soon
 [2016-01-07 15:05 UTC] laruence@php.net
Automatic comment on behalf of laruence@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=16a2b47394a3f8c3d7c2b8eaba59da0e4beca171
Log: Fixed bug #71300 (Segfault in zend_fetch_string_offset)
 [2016-01-07 15:05 UTC] laruence@php.net
-Status: Assigned +Status: Closed
 [2016-07-20 11:34 UTC] davey@php.net
Automatic comment on behalf of laruence@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=16a2b47394a3f8c3d7c2b8eaba59da0e4beca171
Log: Fixed bug #71300 (Segfault in zend_fetch_string_offset)
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Tue Aug 29 15:01:52 2017 UTC