|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2015-02-12 08:43 UTC] php at bof dot de
Description:
------------
Using a self built PHP 5.6.5, opcache enabled:
switch(ARBITRARYCONSTANTS) misbehaves: goes to the default case, unless the matching thing is the first case.
opcache is enabled like this:
zend_extension=/opt/php/extensions/opcache.so
opcache.enable_cli=1
Also happens under mod_php without opcache.enable_cli. No other opcache settings made, but happens also with our usual production settings, so that should not matter
The result is usually what I show under "actual result", below, but on some runs I also see a segmentation fault, or the correct behaviour.
I can reproduce the problem when using global "const MYCONST = 'foo';", but apparently _not_ with a class constant (class foo { const MYCONST = 'foo'; }
Will create a debug build of PHP soon and try to capture a backtrace for a test run where it runs into a segmentation violation. Might take some time, though...
Test script:
---------------
<?php
define('MYCONST', 'foo');
function goodswitch() {
switch(MYCONST) {
case 'foo': return 'foo';
case 'bar': return 'bar';
default: return 'default';
}
}
function badswitch() {
switch(MYCONST) {
case 'bar': return 'bar';
case 'foo': return 'foo';
default: return 'default';
}
}
var_dump(goodswitch());
var_dump(badswitch());
?>
Expected result:
----------------
string(3) "foo"
string(3) "foo"
Actual result:
--------------
string(3) "foo"
string(7) "default"
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Oct 24 03:00:02 2025 UTC |
I cannot get it to segfault / dump core on an --enable-debug build. Weird. Tried it a few hundred times. However the issue is still there (outputs foo and default). With the production build, identical in all other regards, I can get it to segfault in one of about 10 runs. Here is a backtrace of such a run, for whatever that's worth: Core was generated by `php -d opcache.enable_cli=1 /home/patrick/webdev/switch_const_myconst.php'. Program terminated with signal 11, Segmentation fault. #0 0x0000000000000021 in ?? () (gdb) bt #0 0x0000000000000021 in ?? () #1 0x0000000000853d3b in zend_hash_destroy (ht=0x7f941c441e18) at /usr/src/phb/build/release-5.6.5/php-src/Zend/zend_hash.c:548 #2 0x0000000000844893 in _zval_dtor_func (zvalue=0x7f941c4401b0) at /usr/src/phb/build/release-5.6.5/php-src/Zend/zend_variables.c:45 #3 0x000000000087368a in _zval_dtor (execute_data=0x7f941c4401d0) at /usr/src/phb/build/release-5.6.5/php-src/Zend/zend_variables.h:35 #4 ZEND_FREE_SPEC_TMP_HANDLER (execute_data=0x7f941c4401d0) at /usr/src/phb/build/release-5.6.5/php-src/Zend/zend_vm_execute.h:7956 #5 0x00000000008b07c9 in execute_ex (execute_data=0x7f941c4401d0) at /usr/src/phb/build/release-5.6.5/php-src/Zend/zend_vm_execute.h:363 #6 0x00007f941467947b in xdebug_execute_ex (execute_data=0x7f941c4401d0) at /usr/src/phb/build/release-5.6.5/xdebug/xdebug.c:1437 #7 0x00000000008e7ac2 in zend_do_fcall_common_helper_SPEC ( execute_data=<value optimized out>) at /usr/src/phb/build/release-5.6.5/php-src/Zend/zend_vm_execute.h:592 #8 0x00000000008b07c9 in execute_ex (execute_data=0x7f941c4400e0) at /usr/src/phb/build/release-5.6.5/php-src/Zend/zend_vm_execute.h:363 #9 0x00007f941467947b in xdebug_execute_ex (execute_data=0x7f941c4400e0) at /usr/src/phb/build/release-5.6.5/xdebug/xdebug.c:1437 #10 0x00000000008472d4 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /usr/src/phb/build/release-5.6.5/php-src/Zend/zend.c:1341 #11 0x00000000007e3bfe in php_execute_script (primary_file=0x7fffaabc56f0) at /usr/src/phb/build/release-5.6.5/php-src/main/main.c:2584 #12 0x00000000008eaf89 in do_cli (argc=4, argv=0x1f00e90) at /usr/src/phb/build/release-5.6.5/php-src/sapi/cli/php_cli.c:994 #13 0x00000000008eb91c in main (argc=4, argv=0x1f00e90) at /usr/src/phb/build/release-5.6.5/php-src/sapi/cli/php_cli.c:1378valgrind has something to say on the issue! patrick@dev0:{dbg-5.6.5}> valgrind php -d opcache.enable_cli=1 ~/webdev/switch_const_myconst.php ==30622== Memcheck, a memory error detector ==30622== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al. ==30622== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info ==30622== Command: php -d opcache.enable_cli=1 /home/patrick/webdev/switch_const_myconst.php ==30622== Thu Feb 12 10:22:35 2015 (30622): Debug Loading blacklist file: '/opt/php/ini.d/opcache.blacklist' Thu Feb 12 10:22:35 2015 (30622): Message Cached script '/home/patrick/webdev/switch_const_myconst.php' string(3) "foo" ==30622== Conditional jump or move depends on uninitialised value(s) ==30622== at 0xA8A33C: compare_function (zend_operators.c:1602) ==30622== by 0xA8BE21: is_equal_function (zend_operators.c:1837) ==30622== by 0xAEA4E1: ZEND_CASE_SPEC_TMP_CONST_HANDLER (zend_vm_execute.h:9364) ==30622== by 0xAD67D9: execute_ex (zend_vm_execute.h:363) ==30622== by 0xCC31BE3: xdebug_execute_ex (xdebug.c:1437) ==30622== by 0xAD685E: zend_execute (zend_vm_execute.h:388) ==30622== by 0xAD7390: zend_do_fcall_common_helper_SPEC (zend_vm_execute.h:592) ==30622== by 0xADCB02: ZEND_DO_FCALL_SPEC_CONST_HANDLER (zend_vm_execute.h:2595) ==30622== by 0xAD67D9: execute_ex (zend_vm_execute.h:363) ==30622== by 0xCC31BE3: xdebug_execute_ex (xdebug.c:1437) ==30622== by 0xAD685E: zend_execute (zend_vm_execute.h:388) ==30622== by 0xA91EB9: zend_execute_scripts (zend.c:1341) ==30622== ==30622== Use of uninitialised value of size 8 ==30622== at 0xA8A353: compare_function (zend_operators.c:1602) ==30622== by 0xA8BE21: is_equal_function (zend_operators.c:1837) ==30622== by 0xAEA4E1: ZEND_CASE_SPEC_TMP_CONST_HANDLER (zend_vm_execute.h:9364) ==30622== by 0xAD67D9: execute_ex (zend_vm_execute.h:363) ==30622== by 0xCC31BE3: xdebug_execute_ex (xdebug.c:1437) ==30622== by 0xAD685E: zend_execute (zend_vm_execute.h:388) ==30622== by 0xAD7390: zend_do_fcall_common_helper_SPEC (zend_vm_execute.h:592) ==30622== by 0xADCB02: ZEND_DO_FCALL_SPEC_CONST_HANDLER (zend_vm_execute.h:2595) ==30622== by 0xAD67D9: execute_ex (zend_vm_execute.h:363) ==30622== by 0xCC31BE3: xdebug_execute_ex (xdebug.c:1437) ==30622== by 0xAD685E: zend_execute (zend_vm_execute.h:388) ==30622== by 0xA91EB9: zend_execute_scripts (zend.c:1341) ==30622== ==30622== Conditional jump or move depends on uninitialised value(s) ==30622== at 0xAD0D9C: _zval_dtor (zend_variables.h:32) ==30622== by 0xAE6F4E: ZEND_FREE_SPEC_TMP_HANDLER (zend_vm_execute.h:7956) ==30622== by 0xAD67D9: execute_ex (zend_vm_execute.h:363) ==30622== by 0xCC31BE3: xdebug_execute_ex (xdebug.c:1437) ==30622== by 0xAD685E: zend_execute (zend_vm_execute.h:388) ==30622== by 0xAD7390: zend_do_fcall_common_helper_SPEC (zend_vm_execute.h:592) ==30622== by 0xADCB02: ZEND_DO_FCALL_SPEC_CONST_HANDLER (zend_vm_execute.h:2595) ==30622== by 0xAD67D9: execute_ex (zend_vm_execute.h:363) ==30622== by 0xCC31BE3: xdebug_execute_ex (xdebug.c:1437) ==30622== by 0xAD685E: zend_execute (zend_vm_execute.h:388) ==30622== by 0xA91EB9: zend_execute_scripts (zend.c:1341) ==30622== by 0x9FBC55: php_execute_script (main.c:2584) ==30622== string(7) "default" ==30622== ==30622== HEAP SUMMARY: ==30622== in use at exit: 5,556 bytes in 45 blocks ==30622== total heap usage: 34,708 allocs, 34,663 frees, 5,475,889 bytes allocated ==30622== ==30622== LEAK SUMMARY: ==30622== definitely lost: 733 bytes in 26 blocks ==30622== indirectly lost: 0 bytes in 0 blocks ==30622== possibly lost: 0 bytes in 0 blocks ==30622== still reachable: 4,823 bytes in 19 blocks ==30622== suppressed: 0 bytes in 0 blocks ==30622== Rerun with --leak-check=full to see details of leaked memory ==30622== ==30622== For counts of detected and suppressed errors, rerun with: -v ==30622== Use --track-origins=yes to see where uninitialised values come from ==30622== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 6 from 6)The issue remains when I change the case "label" from a constant string to a variable; the valgrind output is slightly different then: Code: define('MYCONST', 'foo'); function goodswitch() { $foo = 'foo'; switch(MYCONST) { case $foo: return 'foo'; case 'bar': return 'bar'; default: return 'default'; } } function badswitch() { $foo = 'foo'; switch(MYCONST) { case 'bar': return 'bar'; case $foo: return 'foo'; default: return 'default'; } } var_dump(goodswitch()); var_dump(badswitch()); Valgrind: Thu Feb 12 10:44:21 2015 (4062): Debug Loading blacklist file: '/opt/php/ini.d/opcache.blacklist' Thu Feb 12 10:44:21 2015 (4062): Message Cached script '/home/patrick/webdev/switch_const_myconst.php' string(3) "foo" ==4062== Conditional jump or move depends on uninitialised value(s) ==4062== at 0xA8A33C: compare_function (zend_operators.c:1602) ==4062== by 0xA8BE21: is_equal_function (zend_operators.c:1837) ==4062== by 0xAF1508: ZEND_CASE_SPEC_TMP_CV_HANDLER (zend_vm_execute.h:12541) ==4062== by 0xAD67D9: execute_ex (zend_vm_execute.h:363) ==4062== by 0xAD685E: zend_execute (zend_vm_execute.h:388) ==4062== by 0xA91EB9: zend_execute_scripts (zend.c:1341) ==4062== by 0x9FBC55: php_execute_script (main.c:2584) ==4062== by 0xB4618E: do_cli (php_cli.c:994) ==4062== by 0xB47239: main (php_cli.c:1378) ==4062== ==4062== Use of uninitialised value of size 8 ==4062== at 0xA8A353: compare_function (zend_operators.c:1602) ==4062== by 0xA8BE21: is_equal_function (zend_operators.c:1837) ==4062== by 0xAF1508: ZEND_CASE_SPEC_TMP_CV_HANDLER (zend_vm_execute.h:12541) ==4062== by 0xAD67D9: execute_ex (zend_vm_execute.h:363) ==4062== by 0xAD685E: zend_execute (zend_vm_execute.h:388) ==4062== by 0xA91EB9: zend_execute_scripts (zend.c:1341) ==4062== by 0x9FBC55: php_execute_script (main.c:2584) ==4062== by 0xB4618E: do_cli (php_cli.c:994) ==4062== by 0xB47239: main (php_cli.c:1378) ==4062== ==4062== Conditional jump or move depends on uninitialised value(s) ==4062== at 0xAD0D9C: _zval_dtor (zend_variables.h:32) ==4062== by 0xAE6F4E: ZEND_FREE_SPEC_TMP_HANDLER (zend_vm_execute.h:7956) ==4062== by 0xAD67D9: execute_ex (zend_vm_execute.h:363) ==4062== by 0xAD685E: zend_execute (zend_vm_execute.h:388) ==4062== by 0xA91EB9: zend_execute_scripts (zend.c:1341) ==4062== by 0x9FBC55: php_execute_script (main.c:2584) ==4062== by 0xB4618E: do_cli (php_cli.c:994) ==4062== by 0xB47239: main (php_cli.c:1378) ==4062== string(7) "default"Playing around with the ordering of the cases: - leaving out default: altogether does not remove the issue - ordering the problematic case 'foo': behind the default does not remove the issue - putting the default: as the first thing does not remove the issue AND changes valgrind output a bit (two instead of three blocks of backtraces) This gives me a more minimal reproducer: define('OK', 'ok'); function badswitch() { switch(OK) { default: return 'bad'; case 'ok': return 'ok'; } } var_dump(badswitch()); with valgrind output Thu Feb 12 10:55:44 2015 (6761): Debug Loading blacklist file: '/opt/php/ini.d/opcache.blacklist' Thu Feb 12 10:55:44 2015 (6761): Message Cached script '/home/patrick/webdev/switch_const_myconst.php' ==6761== Conditional jump or move depends on uninitialised value(s) ==6761== at 0xA8A33C: compare_function (zend_operators.c:1602) ==6761== by 0xA8BE21: is_equal_function (zend_operators.c:1837) ==6761== by 0xAEA4E1: ZEND_CASE_SPEC_TMP_CONST_HANDLER (zend_vm_execute.h:9364) ==6761== by 0xAD67D9: execute_ex (zend_vm_execute.h:363) ==6761== by 0xAD685E: zend_execute (zend_vm_execute.h:388) ==6761== by 0xA91EB9: zend_execute_scripts (zend.c:1341) ==6761== by 0x9FBC55: php_execute_script (main.c:2584) ==6761== by 0xB4618E: do_cli (php_cli.c:994) ==6761== by 0xB47239: main (php_cli.c:1378) ==6761== ==6761== Use of uninitialised value of size 8 ==6761== at 0xA8A353: compare_function (zend_operators.c:1602) ==6761== by 0xA8BE21: is_equal_function (zend_operators.c:1837) ==6761== by 0xAEA4E1: ZEND_CASE_SPEC_TMP_CONST_HANDLER (zend_vm_execute.h:9364) ==6761== by 0xAD67D9: execute_ex (zend_vm_execute.h:363) ==6761== by 0xAD685E: zend_execute (zend_vm_execute.h:388) ==6761== by 0xA91EB9: zend_execute_scripts (zend.c:1341) ==6761== by 0x9FBC55: php_execute_script (main.c:2584) ==6761== by 0xB4618E: do_cli (php_cli.c:994) ==6761== by 0xB47239: main (php_cli.c:1378) ==6761== string(3) "bad"