Opened 8 years ago

Closed 8 years ago

Last modified 7 years ago

#19 closed defect (fixed)

inheritance problem

Reported by: judas_iscariote Owned by: moo
Priority: major Milestone: 1.0.1
Component: cacher Version: 1.0
Keywords: Cc: soporte@…
Application: PHP Version:
Other Exts: SAPI:
Probability: Blocked By:
Blocking:

Description

Hi the following code produces wrong results and segfaults.

<?php

abstract class Foo {

protected function & a (){}

abstract function & b ();

}

class Bar extends Foo {

 protected function &a(){}

 public function &b()
 {
     $retval =& $this->a();
 }

}

$bar = new Bar();
$bar->b();
?>
  • Expected result :

Notice: Only variable references should be returned by reference in /srv/www/htdocs/bug2.php on line 13 Notice: Only variable references should be returned by reference in /srv/www/htdocs/bug2.php on line 18

  • Actual result :

at the first call : see expected result.

at the second call : Fatal error: Call to protected method Bar::a() from context 'Bar' in bug.php on line 17 and the apache child segfaults :(

Change History (10)

comment:1 Changed 8 years ago by moo

  • Resolution set to fixed
  • Status changed from new to closed

ripped reproducable source:

<?php

error_reporting(E_ALL);

class Foo {
    protected function a() { echo "foo::a()"; }
}

class Bar extends Foo {

    protected function a() { echo "bar::a()"; }

    public function b()
    {
        $this->a();
    }
}

$bar = new Bar();
$bar->b();

?>

Temp Patch pending

  • utils.c

     
    305305       CG(zend_lineno) = ZESW(0, cep->line_start); 
    306306       zend_error(E_ERROR, "Cannot redeclare class %s", (char *) cep->name); 
    307307   } 
     308   if (cep->parent) { 
     309       zend_do_inheritance(cep, cep->parent); 
     310   } 
    308311   ZESW(return (xc_cest_t *) stored_ce_ptr, NOTHING); 
    309312} 
    310313/* }}} */ 
  • processor/processor.m4

     
    488488       PROC_CLASS_ENTRY_P(scope) 
    489489   ') 
    490490   DISPATCH(zend_uint, fn_flags) 
    491    /* useless */ 
    492    COPY(prototype) 
     491   COPYNULL(prototype) 
    493492   STRUCT_ARRAY_I(num_args, zend_arg_info, arg_info) 
    494493   DISPATCH(zend_uint, num_args) 
    495494   DISPATCH(zend_uint, required_num_args) 

can u pls try the patch? i can't commit yet, as the svn is moving and marked readonly.

comment:2 Changed 8 years ago by judas_iscariote

that worked Moo.. thank you ¡¡ ;-)

comment:3 Changed 8 years ago by judas_iscariote

  • Resolution fixed deleted
  • Status changed from closed to reopened

reopened because it causes side effects.

comment:4 Changed 8 years ago by moo

  • Resolution set to fixed
  • Status changed from reopened to closed

here's the new patch, pls revert the patch above

$ svn di utils.c processor/processor.m4
(make sure there's no other changed made by yourself)
$ svn revert utils.c processor/processor.m4

readable patch:

  • processor/processor.m4

     
    362362   COPY(handle_property_get) 
    363363   COPY(handle_property_set) 
    364364#endif 
    365    dnl must after SETNULL(constructor) 
     365   dnl must do after SETNULL(constructor) and dst->parent 
    366366   STRUCT(HashTable, function_table, HashTable_zend_function) 
    367367   IFRESTORE(`dst->function_table.pDestructor = (dtor_func_t) destroy_zend_function;') 
    368368') 
     
    488488       PROC_CLASS_ENTRY_P(scope) 
    489489   ') 
    490490   DISPATCH(zend_uint, fn_flags) 
    491    /* useless */ 
    492    COPY(prototype) 
     491   dnl mark it as -1 on store, and lookup parent on restore 
     492   IFSTORE(`dst->prototype = src->prototype ? (zend_function *) -1 : NULL; DONE(prototype)', ` 
     493           IFRESTORE(`do { 
     494               zend_function *parent; 
     495               if (src->prototype != NULL 
     496                && zend_u_hash_find(&(processor->active_class_entry_dst->parent->function_table), 
     497                       UG(unicode) ? IS_UNICODE : IS_STRING, 
     498                       src->function_name, strlen(src->function_name) + 1, 
     499                       (void **) &parent) == SUCCESS) { 
     500                   /* see do_inherit_method_check() */ 
     501                   if ((parent->common.fn_flags & ZEND_ACC_ABSTRACT)) { 
     502                     dst->prototype = parent; 
     503                   } 
     504                   else { 
     505                       dst->prototype = parent->common.prototype; 
     506                   } 
     507               } 
     508               else { 
     509                   dst->prototype = NULL; 
     510               } 
     511               DONE(prototype) 
     512           } while (0); 
     513           ', ` 
     514               COPYNULL(prototype) 
     515           ') 
     516   ') 
    493517   STRUCT_ARRAY_I(num_args, zend_arg_info, arg_info) 
    494518   DISPATCH(zend_uint, num_args) 
    495519   DISPATCH(zend_uint, required_num_args) 

copy-able patch:

Index: processor/processor.m4
===================================================================
--- processor/processor.m4  (revision 88)
+++ processor/processor.m4  (working copy)
@@ -362,7 +362,7 @@
    COPY(handle_property_get)
    COPY(handle_property_set)
 #endif
-   dnl must after SETNULL(constructor)
+   dnl must do after SETNULL(constructor) and dst->parent
    STRUCT(HashTable, function_table, HashTable_zend_function)
    IFRESTORE(`dst->function_table.pDestructor = (dtor_func_t) destroy_zend_function;')
 ')
@@ -488,8 +488,32 @@
        PROC_CLASS_ENTRY_P(scope)
    ')
    DISPATCH(zend_uint, fn_flags)
-   /* useless */
-   COPY(prototype)
+   dnl mark it as -1 on store, and lookup parent on restore
+   IFSTORE(`dst->prototype = src->prototype ? (zend_function *) -1 : NULL; DONE(prototype)', `
+           IFRESTORE(`do {
+               zend_function *parent;
+               if (src->prototype != NULL
+                && zend_u_hash_find(&(processor->active_class_entry_dst->parent->function_table),
+                       UG(unicode) ? IS_UNICODE : IS_STRING,
+                       src->function_name, strlen(src->function_name) + 1,
+                       (void **) &parent) == SUCCESS) {
+                   /* see do_inherit_method_check() */
+                   if ((parent->common.fn_flags & ZEND_ACC_ABSTRACT)) {
+                     dst->prototype = parent;
+                   }
+                   else {
+                       dst->prototype = parent->common.prototype;
+                   }
+               }
+               else {
+                   dst->prototype = NULL;
+               }
+               DONE(prototype)
+           } while (0);
+           ', `
+               COPYNULL(prototype)
+           ')
+   ')
    STRUCT_ARRAY_I(num_args, zend_arg_info, arg_info)
    DISPATCH(zend_uint, num_args)
    DISPATCH(zend_uint, required_num_args)

pls test it as i don't have time to install those big butt oop php-apps, feel free to reopen. thanks

gotta get svn+ssh account from Jan.. :P

comment:5 Changed 8 years ago by moo

  • Milestone set to 1.0.1

comment:6 Changed 8 years ago by judas_iscariote

  • Resolution fixed deleted
  • Status changed from closed to reopened

test still segafaults with read only protection OFF.

comment:7 Changed 8 years ago by moo

commited in [89]

comment:8 Changed 8 years ago by moo

  • Component changed from component1 to cacher

comment:9 Changed 8 years ago by judas_iscariote

in fact this and the "nasty toString issue" still segafaults, but only with read only protection OFF. :P

comment:10 Changed 8 years ago by moo

  • Resolution set to fixed
  • Status changed from reopened to closed

in [89], and the segfalt was fixed in [94]

Note: See TracTickets for help on using tickets.