unread
I am trying to modify yaf extension.
i try to write code to foreach functions of an object and try to execute them.
but i got segment fault. i have no idea where i was wrong.
I want to implement
foreach ($funcName in $obj) {
call_user_func([$obj, $funcName]);
}
my code snippet was here
/** {{{ proto public Yaf_Application::bootstrap(void)
*/
PHP_METHOD(yaf_application, bootstrap) {
zend_string *bootstrap_path;
uint retval = 1;
zend_class_entry *ce;
yaf_application_t *self = getThis();
zval bootstrap;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &bootstrap,
yaf_bootstrap_ce) == FAILURE) {
if (!(ce = zend_hash_str_find_ptr(EG(class_table),
YAF_DEFAULT_BOOTSTRAP_LOWER, sizeof(YAF_DEFAULT_BOOTSTRAP_LOWER) - 1))) {
if (YAF_G(bootstrap)) {
bootstrap_path = zend_string_copy(YAF_G(bootstrap));
} else {
bootstrap_path = strpprintf(0, "%s%c%s.%s",
ZSTR_VAL(YAF_G(directory)), DEFAULT_SLASH, YAF_DEFAULT_BOOTSTRAP,
ZSTR_VAL(YAF_G(ext)));
}
if (!yaf_loader_import(bootstrap_path, 0)) {
php_error_docref(NULL, E_WARNING, "Couldn't find bootstrap file %s",
ZSTR_VAL(bootstrap_path));
retval = 0;
} else if (UNEXPECTED((ce = zend_hash_str_find_ptr(EG(class_table),
YAF_DEFAULT_BOOTSTRAP_LOWER, sizeof(YAF_DEFAULT_BOOTSTRAP_LOWER) - 1))
== NULL)) {
php_error_docref(NULL, E_WARNING, "Couldn't find class %s in %s",
YAF_DEFAULT_BOOTSTRAP, ZSTR_VAL(bootstrap_path));
retval = 0;
} else if (UNEXPECTED(!instanceof_function(ce, yaf_bootstrap_ce))) {
php_error_docref(NULL, E_WARNING,
"Expect a %s instance, %s give", ZSTR_VAL(yaf_bootstrap_ce->name),
ZSTR_VAL(ce->name));
retval = 0;
}
zend_string_release(bootstrap_path);
}
if (UNEXPECTED(!retval)) {
RETURN_FALSE;
}
else {
zend_string *func;
yaf_dispatcher_t *dispatcher;
object_init_ex(&bootstrap, ce);
dispatcher = zend_read_property(yaf_application_ce,
self, ZEND_STRL(YAF_APPLICATION_PROPERTY_NAME_DISPATCHER), 1, NULL);
ZEND_HASH_FOREACH_STR_KEY(&(ce->function_table), func) {
/* cann't use ZEND_STRL in strncasecmp, it cause a compile failed in VS2009 */
if (strncasecmp(ZSTR_VAL(func), YAF_BOOTSTRAP_INITFUNC_PREFIX,
sizeof(YAF_BOOTSTRAP_INITFUNC_PREFIX) - 1)) {
continue;
}
zend_call_method(&bootstrap, ce, NULL, ZSTR_VAL(func), ZSTR_LEN(func),
NULL, 1, dispatcher, NULL);
/** an uncaught exception threw in function call */
if (UNEXPECTED(EG(exception))) {
zval_ptr_dtor(&bootstrap);
RETURN_FALSE;
}
} ZEND_HASH_FOREACH_END();
zval_ptr_dtor(&bootstrap);
}
}
else { // my code start here
zend_string *func;
yaf_dispatcher_t *dispatcher;
zval *funcval;
ce = Z_OBJCE_P(&bootstrap);
dispatcher = zend_read_property(yaf_application_ce,
self, ZEND_STRL(YAF_APPLICATION_PROPERTY_NAME_DISPATCHER), 1, NULL);
ZEND_HASH_FOREACH_STR_KEY(&(ce->function_table), func) {
/* cann't use ZEND_STRL in strncasecmp, it cause a compile failed in VS2009 */
if (strncasecmp(ZSTR_VAL(func), YAF_BOOTSTRAP_INITFUNC_PREFIX,
sizeof(YAF_BOOTSTRAP_INITFUNC_PREFIX) - 1)) {
continue;
}
ZVAL_STRING(funcval, &func);
call_user_function(&(ce)->function_table, &bootstrap, funcval, NULL, 0, NULL);
/** an uncaught exception threw in function call */
if (UNEXPECTED(EG(exception))) {
zval_ptr_dtor(&bootstrap);
RETURN_FALSE;
}
} ZEND_HASH_FOREACH_END();
zval_ptr_dtor(&bootstrap);
} //my code end
RETURN_ZVAL(self, 1, 0);
}
/* }}} */
I put it on github
https://gist.github.com/netroby/1fce94f023a9a45c28be0881e8429e48
And the gdb report like
gdb /usr/bin/php
huzhifeng@devdocker ~ $ gdb /usr/bin/php
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /usr/bin/php...(no debugging symbols found)...done.
(gdb) source ./workspace/php-src/.gdbinit
(gdb) run workspace/yaf-framework/public/cli.php
Starting program: /usr/bin/php workspace/yaf-framework/public/cli.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x00007fffee9010b5 in zim_yaf_application_bootstrap
(execute_data=<optimized out>, return_value=0x7ffff3813260)
at /home/huzhifeng/workspace/yaf/yaf_application.c:592
warning: Source file is more recent than executable.
592
(gdb) bt
#0 0x00007fffee9010b5 in zim_yaf_application_bootstrap
(execute_data=<optimized out>, return_value=0x7ffff3813260)
at /home/huzhifeng/workspace/yaf/yaf_application.c:592
#1 0x00005555557a2c9a in dtrace_execute_internal ()
#2 0x0000555555837940 in ?? ()
#3 0x00005555557f2f8b in execute_ex ()
#4 0x00005555557a2b31 in dtrace_execute_ex ()
#5 0x0000555555846d57 in zend_execute ()
#6 0x00005555557b2d33 in zend_execute_scripts ()
#7 0x00005555557535a0 in php_execute_script ()
#8 0x0000555555848a17 in ?? ()
#9 0x00005555556380a4 in main ()
(gdb) zbacktrace
Attempt to extract a component of a value that is not a structure.
(gdb) set print object on
(gdb) set print pretty on
(gdb) ptype *return_value
type = struct _zval_struct {
zend_value value;
union {
struct {...} v;
uint32_t type_info;
} u1;
union {
uint32_t var_flags;
uint32_t next;
uint32_t cache_slot;
uint32_t lineno;
uint32_t num_args;
uint32_t fe_pos;
uint32_t fe_iter_idx;
} u2;
}
(gdb) print *return_value;
Invalid character ';' in expression.
(gdb) print *return_value
$1 = {
value = {
lval = 0,
dval = 0,
counted = 0x0,
str = 0x0,
arr = 0x0,
obj = 0x0,
res = 0x0,
ref = 0x0,
ast = 0x0,
zv = 0x0,
ptr = 0x0,
ce = 0x0,
func = 0x0,
ww = {
w1 = 0,
w2 = 0
}
},
u1 = {
v = {
type = 1 '\001',
type_flags = 0 '\000',
const_flags = 0 '\000',
reserved = 0 '\000'
},
type_info = 1
},
u2 = {
var_flags = 0,
next = 0,
cache_slot = 0,
lineno = 0,
num_args = 0,
fe_pos = 0,
fe_iter_idx = 0
}
}
Appreciate your time.
Netroby