krakjoe / componere

Complex Type Composition and Manipulation

Home Page:http://docs.php.net/intro.componere

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Segfault in PHP 7.3 With OpCache and abstract classes

vityank opened this issue · comments

Componer version: Latest from 'develop' branch
Tested PHP Versions: 7.1.33/7.3.14
Affected PHP Versions: 7.3.14
Reproduce script: Not available - Can not yet reduce the code to get the problem.
Important note: The affected code does NOT call anything from componere, i.e the initialization of componere shared module somehow breaks the PHP engine in memory. PHP 7.1 with componere doesn't suffer from this issue.
OpCache status: Default for PHP 7.3 which is 0x7FFEBFFF,
Tested with OPCache disabled - Problem does not occur.

I've reduced the problematic opcache flags to:
0x000000a0 SCCP+DFA

The following patch fixed this issue for me:

index fdbb699..cc33619 100644
--- a/componere.c
+++ b/componere.c
@@ -46,6 +46,9 @@ static inline void php_componere_optimizer_adjust()
        /* disable merging constants */
        optimizer &= ~(1<<10);

+       /* disable constant propagation */
+       optimizer &= ~(1<<7);
+
        value = strpprintf(0, "0x%08X", (unsigned int) optimizer);

        zend_alter_ini_entry(key, value, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);

Description:
Very strange and inconsistent behaviour with some extended abstract classes.
Abstract class has static prop which will hold instances of implementing classes.
Implementing class via static method getInstance creates new object version and stores into origAbstClass::staticProp if not created already.

Here 2 possiblities can happen:
a) We get PHP Fatal error: Uncaught Error: Cannot instantiate abstract class TestA
if there is no 'error_log' call inside getInstance
b) class name(TestB) printed then segfault with the BT i provided at the end of post(From PHP code it crashes then looping classe's properties).

Sample code(Not reproducing, but part of affected flow):

abstract class TestA
{
static $gInstances = array();

public function fn1()
{
    echo __METHOD__;
}

public function fn2()
{
    echo __METHOD__;
}

abstract protected function afn1();
abstract protected function _afn2();

public function fn3a()
{
    $this->_afn2();
}

public function fn3()
{
    $this->fn3a();
    echo __METHOD__;
}

}

class TestB extends TestA
{
const TEST_CON = 'Gonna fail';
static public function getInstance()
{
$cl = CLASS;
error_log("Cl=$cl\n");
if (!isset(TestA::$gInstances[$cl]))
TestA::$gInstances[$cl] = new $cl();

    return TestA::$gInstances[$cl];
}

protected function afn1()
{
    echo __METHOD__;
}
protected function _afn2()
{
    echo __METHOD__;
}

}

$a = [
'useCnt' => TestB::TEST_CON
];
TestB::getInstance()->fn3($a);

BT on fault:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000633579 in zend_update_class_constants (class_type=0x21c9620)
at php-7.3.14/Zend/zend_API.c:1170
1170 ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
(gdb) bt
#0 0x0000000000633579 in zend_update_class_constants (class_type=0x21c9620)
at php-7.3.14/Zend/zend_API.c:1170
#1 0x0000000000633acd in object_and_properties_init (arg=arg@entry=0x7f4b3ee1e020,
class_type=class_type@entry=0x21c9620, properties=properties@entry=0x0)
at php-7.3.14/Zend/zend_API.c:1320
#2 0x0000000000633b47 in object_init_ex (arg=arg@entry=0x7f4b3ee1e020,
class_type=class_type@entry=0x21c9620)
at php-7.3.14/Zend/zend_API.c:1343
#3 0x00000000006a67c7 in ZEND_NEW_SPEC_VAR_UNUSED_HANDLER ()
at php-7.3.14/Zend/zend_vm_execute.h:27605
#4 0x00000000006b202f in execute_ex (ex=0x0)
at php-7.3.14/Zend/zend_vm_execute.h:58417
#5 0x00000000006b7438 in zend_execute (op_array=op_array@entry=0x7f4b21cd75b0,
return_value=return_value@entry=0x7f4b3ee1dfd0)
at php-7.3.14/Zend/zend_vm_execute.h:60939
#6 0x00000000006321f4 in zend_execute_scripts (type=type@entry=8, retval=0x7f4b3ee1dfd0,
retval@entry=0x0, file_count=file_count@entry=3)
at php-7.3.14/Zend/zend.c:1568
#7 0x00000000005d5dd0 in php_execute_script (
primary_file=primary_file@entry=0x7ffc68549720)
at php-7.3.14/main/main.c:2639
#8 0x000000000043a00c in main (argc=, argv=)
at php-7.3.14/sapi/fpm/fpm/fpm_main.c:1950
(gdb)