Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 329753 - dev-lang/php-5.3.2 segfaults on arm (strict-aliasing issue)
Summary: dev-lang/php-5.3.2 segfaults on arm (strict-aliasing issue)
Alias: None
Product: Gentoo Linux
Classification: Unclassified
Component: Current packages (show other bugs)
Hardware: ARM Linux
: High normal (vote)
Assignee: PHP Bugs
Depends on:
Blocks: 312775
  Show dependency tree
Reported: 2010-07-24 22:35 UTC by Siarhei Siamashka
Modified: 2010-07-27 14:06 UTC (History)
1 user (show)

See Also:
Package list:
Runtime testing required: ---


Note You need to log in before you can comment on or make changes to this bug.
Description Siarhei Siamashka 2010-07-24 22:35:52 UTC
dev-lang/php-5.3.2 fails to build on arm with -O2 optimization options in CFLAGS. 

Analyzing gdb backtrace and the generated code for 'zend_ptr_stack_clear_multiple' function makes it clear that the cause is a pointer aliasing issue. Searching php bugtracker shows that this bug has been reported already and it describes the problem precisely:

Program terminated with signal 11, Segmentation fault.
#0  zval_delref_p (zval_ptr=0xbedc8ebc) at /var/tmp/portage/dev-lang/php-5.3.2/work/php-5.3.2/Zend/zend.h:385
385             return --pz->refcount__gc;
(gdb) bt
#0  zval_delref_p (zval_ptr=0xbedc8ebc) at /var/tmp/portage/dev-lang/php-5.3.2/work/php-5.3.2/Zend/zend.h:385
#1  _zval_ptr_dtor (zval_ptr=0xbedc8ebc) at /var/tmp/portage/dev-lang/php-5.3.2/work/php-5.3.2/Zend/zend_execute_API.c:433
#2  0x0022cd1c in zend_vm_stack_clear_multiple (execute_data=0x79a120) at /var/tmp/portage/dev-lang/php-5.3.2/work/php-5.3.2/Zend/zend_execute.h:316
#3  zend_do_fcall_common_helper_SPEC (execute_data=0x79a120) at /var/tmp/portage/dev-lang/php-5.3.2/work/php-5.3.2/Zend/zend_vm_execute.h:403
#4  0x00227428 in execute (op_array=0x7762c8) at /var/tmp/portage/dev-lang/php-5.3.2/work/php-5.3.2/Zend/zend_vm_execute.h:104
#5  0x00205f44 in zend_execute_scripts (type=8, retval=<value optimized out>, file_count=3) at /var/tmp/portage/dev-lang/php-5.3.2/work/php-5.3.2/Zend/zend.c:1194
#6  0x001bb934 in php_execute_script (primary_file=<value optimized out>) at /var/tmp/portage/dev-lang/php-5.3.2/work/php-5.3.2/main/main.c:2260
#7  0x002875a4 in main (argc=<value optimized out>, argv=<value optimized out>) at /var/tmp/portage/dev-lang/php-5.3.2/work/php-5.3.2/sapi/cli/php_cli.c:1192

static inline void zend_vm_stack_clear_multiple(TSRMLS_D)
        void **p = EG(argument_stack)->top - 1;
        int delete_count = (int)(zend_uintptr_t) *p;

        while (--delete_count>=0) {
                zval *q = *(zval **)(--p);
                *p = NULL;
        zend_vm_stack_free_int(p TSRMLS_CC);

Dump of assembler code for function zend_vm_stack_clear_multiple:
0x001fb900 <zend_vm_stack_clear_multiple+0>:    push    {r4, r5, r6, r7, r8, r9, r10, lr}
0x001fb904 <zend_vm_stack_clear_multiple+4>:    ldr     r9, [pc, #112]  ; 0x1fb97c <zend_vm_stack_clear_multiple+124>
0x001fb908 <zend_vm_stack_clear_multiple+8>:    sub     sp, sp, #8
0x001fb90c <zend_vm_stack_clear_multiple+12>:   ldr     r3, [r9, #444]  ; 0x1bc
0x001fb910 <zend_vm_stack_clear_multiple+16>:   ldr     r4, [r3]
0x001fb914 <zend_vm_stack_clear_multiple+20>:   ldr     r10, [r4, #-4]
0x001fb918 <zend_vm_stack_clear_multiple+24>:   sub     r8, r4, #4
0x001fb91c <zend_vm_stack_clear_multiple+28>:   subs    r5, r10, #1
0x001fb920 <zend_vm_stack_clear_multiple+32>:   bmi     0x1fb950 <zend_vm_stack_clear_multiple+80>
0x001fb924 <zend_vm_stack_clear_multiple+36>:   add     r7, sp, #4
^ here r7 register points to 'q' variable
0x001fb928 <zend_vm_stack_clear_multiple+40>:   mov     r6, #0
0x001fb92c <zend_vm_stack_clear_multiple+44>:   str     r6, [r4, #-8]
0x001fb930 <zend_vm_stack_clear_multiple+48>:   mov     r0, r7
0x001fb934 <zend_vm_stack_clear_multiple+52>:   str     r6, [sp, #4]
^ here the content of 'q' variable is cleared to zero
0x001fb938 <zend_vm_stack_clear_multiple+56>:   bl      0x1fb874 <_zval_ptr_dtor>
^ one of the first things that '_zval_ptr_dtor' function does is dereferencing zero pointer
0x001fb93c <zend_vm_stack_clear_multiple+60>:   subs    r5, r5, #1
0x001fb940 <zend_vm_stack_clear_multiple+64>:   sub     r4, r4, #4
0x001fb944 <zend_vm_stack_clear_multiple+68>:   bpl     0x1fb92c <zend_vm_stack_clear_multiple+44>
0x001fb948 <zend_vm_stack_clear_multiple+72>:   ldr     r3, [r9, #444]  ; 0x1bc
0x001fb94c <zend_vm_stack_clear_multiple+76>:   sub     r8, r8, r10, lsl #2
0x001fb950 <zend_vm_stack_clear_multiple+80>:   add     r2, r3, #16
0x001fb954 <zend_vm_stack_clear_multiple+84>:   cmp     r8, r2
0x001fb958 <zend_vm_stack_clear_multiple+88>:   strne   r8, [r3]
0x001fb95c <zend_vm_stack_clear_multiple+92>:   beq     0x1fb968 <zend_vm_stack_clear_multiple+104>
0x001fb960 <zend_vm_stack_clear_multiple+96>:   add     sp, sp, #8
0x001fb964 <zend_vm_stack_clear_multiple+100>:  pop     {r4, r5, r6, r7, r8, r9, r10, pc}
0x001fb968 <zend_vm_stack_clear_multiple+104>:  mov     r0, r3
0x001fb96c <zend_vm_stack_clear_multiple+108>:  ldr     r3, [r3, #8]
0x001fb970 <zend_vm_stack_clear_multiple+112>:  str     r3, [r9, #444]  ; 0x1bc
0x001fb974 <zend_vm_stack_clear_multiple+116>:  bl      0x1ed154 <_efree>
0x001fb978 <zend_vm_stack_clear_multiple+120>:  b       0x1fb960 <zend_vm_stack_clear_multiple+96>
0x001fb97c <zend_vm_stack_clear_multiple+124>:  strdeq  r6, [r7], #-240 ; 0xffffff10

Reproducible: Always

Steps to Reproduce:
Comment 1 Siarhei Siamashka 2010-07-24 22:38:55 UTC
Actually bug 295682 *might* be caused by the same issue, but I'm not completely sure (SIGBUS instead of segfault and somewhat similar, but not precisely the same backtrace). Hence reported this issue separately.
Comment 2 Matti Bickel (RETIRED) gentoo-dev 2010-07-25 00:14:00 UTC
Does using the patch described upstream fix the issue for you? It wasn't clear from your report.

Otherwise, thanks for digging into this.
Comment 3 Siarhei Siamashka 2010-07-25 08:12:47 UTC
(In reply to comment #2)
> Does using the patch described upstream fix the issue for you? It wasn't clear
> from your report.

Yes, it does fix the issue.

Though it might have been better to have that problematic line changed to "zval *q = (zval *) *(--p);" (still have the cast, but do it after pointer dereference, not before). I'm not familiar with php, but this particular header file uses BEGIN_EXTERN_C macro, which implies that it might be used from C++ code sometimes. And the patch from php bugtracker fails to compile as C++ without adding the explicit cast.
Comment 4 Matti Bickel (RETIRED) gentoo-dev 2010-07-27 14:06:49 UTC
I've included your fix into the php-5.3.3 patch tarball. Please reopen this bug if the issue is not fixed.