I've run into a segmentation fault situation when calling call_user_function() 
in an extension I'm developing. I can reproduce the fault reliably when trying 
to pass 4 arguments to my user function. The strange (to me anyway) thing is 
that it doesn't crash when passing 3 or fewer arguments. Can anyone point out 
what might be causing this error? Here's my source code:

void async_callback(getdns_context *context,
                    getdns_callback_type_t callbackType,
                    getdns_dict *response,
                    void *userArg, getdns_transaction_t transID)
{
    int phpResult = 0;
    zval *userArgs, **hashData;
    zval *clientArgs[4];
    zval cbType, dictVal, funcName, retVal, transIDVal;
    char *phpCallback = NULL;
    HashTable *arrayHash;
    HashPosition hashPtr;

    userArgs = (zval *) userArg;
    arrayHash = Z_ARRVAL_P(userArgs);
    zend_hash_internal_pointer_reset_ex(arrayHash, &hashPtr);
    if (zend_hash_get_current_data_ex(arrayHash, (void**) &hashData, &hashPtr) 
== SUCCESS) {
        phpCallback = (char *) Z_STRVAL_PP(hashData);
    }
    else {
        php_error_docref(NULL TSRMLS_DC, E_ERROR, "Invalid callback 
parameters!");
        return;
    }

    ZVAL_STRING(&funcName, phpCallback, 0);

    clientArgs[0] = &dictVal;
    ZVAL_LONG(clientArgs[0], (long) response);

    clientArgs[1] = &cbType;
    ZVAL_LONG(clientArgs[1], (long) callbackType);

    clientArgs[2] = userArgs;

    clientArgs[3] = &transIDVal;
    ZVAL_STRING(clientArgs[3], "0000000000000000", 1);

    phpResult = call_user_function(EG(function_table), NULL,
                   &funcName, &retVal, 4, clientArgs TSRMLS_DC);
    if (phpResult == FAILURE) {
        php_error_docref(NULL TSRMLS_DC, E_ERROR, "Callback failed!");
    }
}

Here's the stack trace produced when running my PHP client program that calls 
into this extension and passes the name of the user function:

Program received signal SIGSEGV, Segmentation fault.
0x00000000006c8570 in gc_remove_from_buffer (root=0x7ffff5a364f4 
<evmap_io_del+212>) at /projects/php/php-5.6.5/Zend/zend_gc.h:189
189             root->next->prev = root->prev;
(gdb) bt
#0  0x00000000006c8570 in gc_remove_from_buffer (root=0x7ffff5a364f4 
<evmap_io_del+212>) at /projects/php/php-5.6.5/Zend/zend_gc.h:189
#1  gc_remove_zval_from_buffer (zv=zv@entry=0x7fffffffa350) at 
/projects/php/php-5.6.5/Zend/zend_gc.c:265
#2  0x000000000069a6d8 in i_zval_ptr_dtor (zval_ptr=0x7fffffffa350) at 
/projects/php/php-5.6.5/Zend/zend_execute.h:78
#3  zend_vm_stack_clear_multiple (nested=0) at 
/projects/php/php-5.6.5/Zend/zend_execute.h:308
#4  zend_call_function (fci=fci@entry=0x7fffffffa280, fci_cache=<optimized 
out>, fci_cache@entry=0x0)
    at /projects/php/php-5.6.5/Zend/zend_execute_API.c:886
#5  0x000000000069abae in call_user_function_ex 
(function_table=function_table@entry=0xdfd130, object_pp=<optimized out>, 
function_name=<optimized out>, 
    retval_ptr_ptr=retval_ptr_ptr@entry=0x7fffffffa318, param_count=<optimized 
out>, params=params@entry=0x7ffff7fd40a0, no_separation=no_separation@entry=1, 
    symbol_table=symbol_table@entry=0x0) at 
/projects/php/php-5.6.5/Zend/zend_execute_API.c:617
#6  0x000000000069ac02 in call_user_function (function_table=0xdfd130, 
object_pp=object_pp@entry=0x0, 
function_name=function_name@entry=0x7fffffffa390, 
    retval_ptr=retval_ptr@entry=0x7fffffffa3b0, 
param_count=param_count@entry=4, params=params@entry=0x7fffffffa3f0)
    at /projects/php/php-5.6.5/Zend/zend_execute_API.c:590
#7  0x00007ffff60aab23 in async_callback (context=<optimized out>, 
callbackType=GETDNS_CALLBACK_COMPLETE, response=0xff6860, 
userArg=0x7ffff7fcf930, 
    transID=<optimized out>) at /projects/getdns-php-bindings/phpgetdns.c:1191
#8  0x00007ffff57ed682 in ub_process () from 
/usr/lib/x86_64-linux-gnu/libunbound.so.2
#9  0x00007ffff5c780fa in priv_getdns_context_ub_read_cb (userarg=0xf476d0) at 
./context.c:985
#10 0x00007ffff5a278b4 in event_base_loop () from 
/usr/lib/x86_64-linux-gnu/libevent_core-2.0.so.5
#11 0x00007ffff60adc03 in zif_php_getdns_context_run (ht=<optimized out>, 
return_value=0x7ffff7fd3d40, return_value_ptr=<optimized out>, 
    this_ptr=<optimized out>, return_value_used=<optimized out>) at 
/projects/getdns-php-bindings/phpgetdns.c:3606
#12 0x000000000074d68e in zend_do_fcall_common_helper_SPEC 
(execute_data=<optimized out>) at 
/projects/php/php-5.6.5/Zend/zend_vm_execute.h:558
#13 0x00000000006e4108 in execute_ex (execute_data=0x7ffff7f9a590) at 
/projects/php/php-5.6.5/Zend/zend_vm_execute.h:363
#14 0x00000000006ab330 in zend_execute_scripts (type=type@entry=8, 
retval=retval@entry=0x0, file_count=file_count@entry=3)
    at /projects/php/php-5.6.5/Zend/zend.c:1341
#15 0x0000000000649255 in php_execute_script 
(primary_file=primary_file@entry=0x7fffffffcac0) at 
/projects/php/php-5.6.5/main/main.c:2584
#16 0x000000000074f2ef in do_cli (argc=2, argv=0xdfc540) at 
/projects/php/php-5.6.5/sapi/cli/php_cli.c:994
#17 0x0000000000426670 in main (argc=2, argv=0xdfc540) at 
/projects/php/php-5.6.5/sapi/cli/php_cli.c:1378
(gdb) up
#1  gc_remove_zval_from_buffer (zv=zv@entry=0x7fffffffa350) at 
/projects/php/php-5.6.5/Zend/zend_gc.c:265
265             GC_REMOVE_FROM_BUFFER(root_buffer);
(gdb) up
#2  0x000000000069a6d8 in i_zval_ptr_dtor (zval_ptr=0x7fffffffa350) at 
/projects/php/php-5.6.5/Zend/zend_execute.h:78
78                      GC_REMOVE_ZVAL_FROM_BUFFER(zval_ptr);
(gdb) up
#3  zend_vm_stack_clear_multiple (nested=0) at 
/projects/php/php-5.6.5/Zend/zend_execute.h:308
308                     i_zval_ptr_dtor(q ZEND_FILE_LINE_CC TSRMLS_CC);
(gdb) up
#4  zend_call_function (fci=fci@entry=0x7fffffffa280, fci_cache=<optimized 
out>, fci_cache@entry=0x0)
    at /projects/php/php-5.6.5/Zend/zend_execute_API.c:886
886             zend_vm_stack_clear_multiple(0 TSRMLS_CC);
(gdb) up
#5  0x000000000069abae in call_user_function_ex 
(function_table=function_table@entry=0xdfd130, object_pp=<optimized out>, 
function_name=<optimized out>, 
    retval_ptr_ptr=retval_ptr_ptr@entry=0x7fffffffa318, param_count=<optimized 
out>, params=params@entry=0x7ffff7fd40a0, no_separation=no_separation@entry=1, 
    symbol_table=symbol_table@entry=0x0) at 
/projects/php/php-5.6.5/Zend/zend_execute_API.c:617
617             return zend_call_function(&fci, NULL TSRMLS_CC);
(gdb) up
#6  0x000000000069ac02 in call_user_function (function_table=0xdfd130, 
object_pp=object_pp@entry=0x0, 
function_name=function_name@entry=0x7fffffffa390, 
    retval_ptr=retval_ptr@entry=0x7fffffffa3b0, 
param_count=param_count@entry=4, params=params@entry=0x7fffffffa3f0)
    at /projects/php/php-5.6.5/Zend/zend_execute_API.c:590
590             ex_retval = call_user_function_ex(function_table, object_pp, 
function_name, &local_retval_ptr, param_count, params_array, 1, NULL TSRMLS_CC);
(gdb) up
#7  0x00007ffff60aab23 in async_callback (context=<optimized out>, 
callbackType=GETDNS_CALLBACK_COMPLETE, response=0xff6860, 
userArg=0x7ffff7fcf930, 
    transID=<optimized out>) at /projects/getdns-php-bindings/phpgetdns.c:1191
1191        phpResult = call_user_function(EG(function_table), NULL,
(gdb)

Any thoughts? From what I can see in gdb the variable with value 0x7fffffffa350 
is the second element of the clientArgs array:

(gdb) print clientArgs
$1 = {0x7fffffffa370, 0x7fffffffa350, 0x7ffff7fcf930, 0x7fffffffa3d0}
(gdb)

Thank you,
Scott

--
PECL development discussion Mailing List (http://pecl.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to