php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #69643 Segmentation fault in i_zval_ptr_dtor() (zend_variables.h:56)
Submitted: 2015-05-15 20:28 UTC Modified: 2015-05-29 11:58 UTC
Votes:4
Avg. Score:4.8 ± 0.4
Reproduced:3 of 4 (75.0%)
Same Version:2 (66.7%)
Same OS:2 (66.7%)
From: berdir@php.net Assigned: laruence (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: master-Git-2015-05-15 (Git) OS: Ubuntu
Private report: No CVE-ID: None
 [2015-05-15 20:28 UTC] berdir@php.net
Description:
------------
We're working on making Drupal 8 compatible with PHP7.

Around 4 of our test have a segfault and the end of the test, during shutdown. This is relatively new (1-2weeks), they passed before.

Program received signal SIGSEGV, Segmentation fault.
i_zval_ptr_dtor (zval_ptr=0x7fffed5ffa80) at /home/berdir/tools/php-src/Zend/zend_variables.h:56
56			if (!Z_DELREF_P(zval_ptr)) {
(gdb) bt
#0  i_zval_ptr_dtor (zval_ptr=0x7fffed5ffa80) at /home/berdir/tools/php-src/Zend/zend_variables.h:56
#1  destroy_zend_class (zv=<optimized out>) at /home/berdir/tools/php-src/Zend/zend_opcode.c:260
#2  0x00000000007cb74c in _zend_hash_del_el_ex (prev=<optimized out>, p=0x136d440, idx=710, ht=0x113ddd0) at /home/berdir/tools/php-src/Zend/zend_hash.c:938
#3  _zend_hash_del_el (p=0x136d440, idx=710, ht=0x113ddd0) at /home/berdir/tools/php-src/Zend/zend_hash.c:962
#4  zend_hash_reverse_apply (ht=0x113ddd0, apply_func=apply_func@entry=0x7a6ee0 <clean_non_persistent_class>) at /home/berdir/tools/php-src/Zend/zend_hash.c:1532
#5  0x00000000007a772b in shutdown_executor () at /home/berdir/tools/php-src/Zend/zend_execute_API.c:351
#6  0x00000000007b6e2b in zend_deactivate () at /home/berdir/tools/php-src/Zend/zend.c:964
#7  0x0000000000758c22 in php_request_shutdown (dummy=<optimized out>) at /home/berdir/tools/php-src/main/main.c:1818
#8  0x0000000000854532 in do_cli (argc=-18992, argv=0x0) at /home/berdir/tools/php-src/sapi/cli/php_cli.c:1135
#9  0x00000000004372a0 in main (argc=-18992, argv=0x0) at /home/berdir/tools/php-src/sapi/cli/php_cli.c:1334

One of the failing tests is Drupal\migrate_drupal\Tests\d6\MigrateUserPictureFileTest.

Instructions on how to run the test are in https://bugs.php.net/bug.php?id=69371, for example.



Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-05-16 15:10 UTC] laruence@php.net
seems I can not reproduce it:

Drupal\migrate_drupal\Tests\d6\MigrateUserPictureFileTest     13 passes

Test run duration: 3 sec


thanks
 [2015-05-19 03:13 UTC] laruence@php.net
-Status: Open +Status: Feedback -Assigned To: +Assigned To: laruence
 [2015-05-21 21:56 UTC] berdir@php.net
Strange, now I also can't reproduce it with that test anymore.

Drupal\file\Tests\RemoteFileSaveUploadTest is still failing for me, however. But it seems to be a completely different problem, seems to be curl related again? 

gdb --args '/usr/local/bin/php7' './core/scripts/run-tests.sh' --url 'http://d8/' --php '/usr/local/bin/php7' --test-id 2123 --execute-test 'Drupal\file\Tests\RemoteFileSaveUploadTest'

(you might need a work

Program received signal SIGSEGV, Segmentation fault.
0x0000000000564861 in _php_curl_setopt (ch=ch@entry=0x7fffe4481780, option=<optimized out>, zvalue=zvalue@entry=0x7fffe405cae0) at /home/berdir/tools/php-src/ext/curl/interface.c:2563
2563						form_error = curl_formadd(&first, &last,
(gdb) bt
#0  0x0000000000564861 in _php_curl_setopt (ch=ch@entry=0x7fffe4481780, option=<optimized out>, zvalue=zvalue@entry=0x7fffe405cae0)
    at /home/berdir/tools/php-src/ext/curl/interface.c:2563
#1  0x000000000056552c in zif_curl_setopt_array (execute_data=<optimized out>, return_value=0x7fffed413920) at /home/berdir/tools/php-src/ext/curl/interface.c:2808
#2  0x0000000000850905 in ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER () at /home/berdir/tools/php-src/Zend/zend_vm_execute.h:692
#3  0x00000000007f8c0b in execute_ex (ex=<optimized out>) at /home/berdir/tools/php-src/Zend/zend_vm_execute.h:394
#4  0x0000000000853f97 in zend_execute (op_array=0x7fffed4931c0, return_value=<optimized out>) at /home/berdir/tools/php-src/Zend/zend_vm_execute.h:434
#5  0x00000000007b7cf5 in zend_execute_scripts (type=8, retval=0x7fffffffa2c3, retval@entry=0x0, file_count=3) at /home/berdir/tools/php-src/Zend/zend.c:1389
#6  0x000000000075a140 in php_execute_script (primary_file=0x7fffffffcad0) at /home/berdir/tools/php-src/main/main.c:2479
#7  0x00000000008558b9 in do_cli (argc=-479607560, argv=0x7fffffffa2c3) at /home/berdir/tools/php-src/sapi/cli/php_cli.c:967
#8  0x00000000004372a0 in main (argc=-479607560, argv=0x7fffffffa2c3) at /home/berdir/tools/php-src/sapi/cli/php_cli.c:1334
 [2015-05-26 23:24 UTC] berdir@php.net
I've tried to debug this a bit more and I think current is somehow messed up. Why and what it's supposed to be, I don't know:

(gdb) print current
$5 = (zval *) 0x7fffe3e7b4c0
(gdb) print *current
$6 = {value = {lval = 1, dval = 4.9406564584124654e-324, counted = 0x1, str = 0x1, arr = 0x1, obj = 0x1, res = 0x1, ref = 0x1, ast = 0x1, zv = 0x1, ptr = 0x1, ce = 0x1, func = 0x1, 
    ww = {w1 = 1, w2 = 0}}, u1 = {v = {type = 4 '\004', type_flags = 0 '\000', const_flags = 0 '\000', reserved = 0 '\000'}, type_info = 4}, u2 = {var_flags = 4294967295, 
    next = 4294967295, cache_slot = 4294967295, lineno = 4294967295, num_args = 4294967295, fe_pos = 4294967295, fe_iter_idx = 4294967295}}
(gdb) print current->value
$7 = {lval = 1, dval = 4.9406564584124654e-324, counted = 0x1, str = 0x1, arr = 0x1, obj = 0x1, res = 0x1, ref = 0x1, ast = 0x1, zv = 0x1, ptr = 0x1, ce = 0x1, func = 0x1, ww = {
    w1 = 1, w2 = 0}}
(gdb) print *current->value->str
Cannot access memory at address 0x1

This is the array of postfields that are processed here:
array(9) {
  ["file_test_replace"]=>
  int(1)
  ["file_subdir"]=>
  string(0) ""
  ["extensions"]=>
  string(0) ""
  ["is_image_file"]=>
  string(1) "1"
  ["op"]=>
  string(6) "Submit"
  ["form_build_id"]=>
  string(48) "form-8Jctuh1GUx5Te_wooBYvPLbOJhXOSUOgsQ-emHSKW8g"
  ["form_token"]=>
  string(43) "XcSxNC5I2nYo2-zg29Mo7rsmImYJWq7JNbK3WlwVZzc"
  ["form_id"]=>
  string(15) "_file_test_form"
  ["files[file_test_upload]"]=>
  object(CURLFile)#8517 (3) {
    ["name"]=>
    string(69) "/home/berdir/Projekte/d8/sites/simpletest/127071/files/image-test.png"
    ["mime"]=>
    string(0) ""
    ["postname"]=>
    string(0) ""
  }
}

I noticed that file_test_replace does seem to be an integer, which might be the cause for this. In fact, when I add an explicit string cast for the value, then it works!

So I guess current is optimized and in this case a zval for an int, not a string, but the code expects a string?

This means I can work around this in our tests, but this isn't supposed to break?
 [2015-05-28 16:05 UTC] laruence@php.net
Automatic comment on behalf of laruence
Revision: http://git.php.net/?p=php-src.git;a=commit;h=50e08d60b66d7cdc47f61fbe73b7ebfea8da0acc
Log: Attempt to fix #69643
 [2015-05-28 16:05 UTC] laruence@php.net
-Status: Feedback +Status: Closed
 [2015-05-28 20:07 UTC] berdir@php.net
I can confirm that this fixed now!

No more segfaults with php7 in our test suite. Two new test fails thought, looking into those now.
 [2015-05-28 22:20 UTC] berdir@php.net
Ok, this is annoying.

i found a way to reproduce the origin segfault. It only happens when running the tests with concurrency.

I was able to generate a core file for a non-packaged executable on ubuntu by doing this:

as root:
# echo "/tmp/core.%e.%p.%h.%t" > /proc/sys/kernel/core_pattern

Then run:
php7 core/scripts/run-tests.sh --repeat 20 --concurrency 8 --url http://d8/ --class "Drupal\migrate_drupal\Tests\d6\MigrateFieldTest"

You should get an output like this:
...
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes                                      
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes                                      
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes                                      
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes                                      
Segmentation fault (core dumped)
FATAL Drupal\migrate_drupal\Tests\d6\MigrateFieldTest: test runner returned a non-zero error code (139).
- Found database prefix 'simpletest866096' for test ID 1804.
Segmentation fault (core dumped)
Segmentation fault (core dumped)
FATAL Drupal\migrate_drupal\Tests\d6\MigrateFieldTest: test runner returned a non-zero error code (139).
- Found database prefix 'simpletest667328' for test ID 1800.
FATAL Drupal\migrate_drupal\Tests\d6\MigrateFieldTest: test runner returned a non-zero error code (139).
- Found database prefix 'simpletest325478' for test ID 1806.
Segmentation fault (core dumped)
FATAL Drupal\migrate_drupal\Tests\d6\MigrateFieldTest: test runner returned a non-zero error code (139).
- Found database prefix 'simpletest901902' for test ID 1803.
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes    
...

And then find the core dumps in /tmp.

(gdb) print zval_ptr
$1 = (zval *) 0x7fa473d0d0d8
(gdb) print *zval_ptr
$2 = {value = {lval = 139638785192025, dval = 6.8990726590384926e-310, counted = 0x7f0030303059, str = 0x7f0030303059, arr = 0x7f0030303059, obj = 0x7f0030303059, res = 0x7f0030303059, 
    ref = 0x7f0030303059, ast = 0x7f0030303059, zv = 0x7f0030303059, ptr = 0x7f0030303059, ce = 0x7f0030303059, func = 0x7f0030303059, ww = {w1 = 808464473, w2 = 32512}}, u1 = {v = {
      type = 8 '\b', type_flags = 12 '\f', const_flags = 0 '\000', reserved = 0 '\000'}, type_info = 3080}, u2 = {var_flags = 1953066601, next = 1953066601, cache_slot = 1953066601, 
    lineno = 1953066601, num_args = 1953066601, fe_pos = 1953066601, fe_iter_idx = 1953066601}}.
(gdb) print zval_ptr->value
$3 = {lval = 139638785192025, dval = 6.8990726590384926e-310, counted = 0x7f0030303059, str = 0x7f0030303059, arr = 0x7f0030303059, obj = 0x7f0030303059, res = 0x7f0030303059, 
  ref = 0x7f0030303059, ast = 0x7f0030303059, zv = 0x7f0030303059, ptr = 0x7f0030303059, ce = 0x7f0030303059, func = 0x7f0030303059, ww = {w1 = 808464473, w2 = 32512}}
(gdb) print zval_ptr->value->str
$4 = (zend_string *) 0x7f0030303059
(gdb) print *zval_ptr->value->str
Cannot access memory at address 0x7f0030303059
 [2015-05-29 03:05 UTC] laruence@php.net
What I got is:

$ php7 core/scripts/run-tests.sh --repeat 20 --concurrency 8  --sqlite '/tmp/test.sqlite'  --dburl 'sqlite://tmp/db.sqlite' --url http://d8/ --class "Drupal\migrate_drupal\Tests\d6\MigrateFieldTest"

Drupal test run
---------------

Tests to be run:
  - Drupal\migrate_drupal\Tests\d6\MigrateFieldTest

Test run started:
  Friday, May 29, 2015 - 03:01

Test summary
------------

Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest                1 passes             1 exceptions

Test run duration: 1 min
 [2015-05-29 06:15 UTC] berdir@php.net
If you get errors/exceptions, use --verbose --color instead of --concurrency to see what the problem is. My guess is that you're missing an extension or something like that.
 [2015-05-29 11:58 UTC] laruence@php.net
okey, now it runs as yours , but no segfault, I have tried both debug/no-debug version

$ php7 core/scripts/run-tests.sh --repeat 20 --concurrency 8 --sqlite /tmp/test.sqlite --dburl sqlite://tmp/db.sqlite  --url http://d8/ --class "Drupal\migrate_drupal\Tests\d6\MigrateFieldTest"

Drupal test run
---------------

Tests to be run:
  - Drupal\migrate_drupal\Tests\d6\MigrateFieldTest

Test run started:
  Friday, May 29, 2015 - 11:53

Test summary
------------

Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes
Drupal\migrate_drupal\Tests\d6\MigrateFieldTest               31 passes

Test run duration: 14 sec
 [2016-07-20 11:38 UTC] davey@php.net
Automatic comment on behalf of laruence
Revision: http://git.php.net/?p=php-src.git;a=commit;h=50e08d60b66d7cdc47f61fbe73b7ebfea8da0acc
Log: Attempt to fix #69643
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri May 10 15:01:35 2024 UTC