开发者

Segfault instantiating class in custom PHP extension in C

I'm developing my own PHP extension with a class in it. I recently upgraded from Ubuntu 9.04 to 9.10 and the extension broke. I since tried to update to 10.04 to see if it fixes it as my dev environment is 10.04 and it works fine on there. The only major difference from what I can understand is the server is 64 bit and my laptop 32 bit architecture. I have PHP version 5.3.2-1ubuntu4.5 (Zend build 20090626).

I have tried running my test PHP file:

<?php
$server =  "http://localhost/";
$port = 1214;
$f = new PPKeyClient($server, $port);
var_dump($f);

In GDB:

root@node:/etc/php5/conf.d# gdb php
GNU gdb (GDB) 7.1-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
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".
For bug reporting instructions, please see:
...
Reading symbols from /usr/bin/php...Reading symbols from /usr/lib/debug/usr/bin/php5...done.
done.
(gdb) run -f /var/www/test.php 
Starting program: /usr/bin/php -f /var/www/test.php
[Thread debugging using libthread_db enabled]
[New Thread 0x7fffef15b710 (LWP 9228)]
[Thread 0x7fffef15b710 (LWP 9228) exited]
1
Program received signal SIGSEGV, Segmentation fault.
0x00000000006e7767 in zend_do_fcall_common_helper_SPEC (execute_data=0x7fff00000000)
    at /build/buildd/php5-5.3.2/Zend/zend_vm_execute.h:371
371 /build/buildd/php5-5.3.2/Zend/zend_vm_execute.h: No such file or directory.
 in /build/buildd/php5-5.3.2/Zend/zend_vm_execute.h
(gdb) bt
#0  0x00000000006e7767 in zend_do_fcall_common_helper_SPEC (execute_data=0x7fff00000000)
    at /build/buildd/php5-5.3.2/Zend/zend_vm_execute.h:371
#1  0x00000000006bec20 in execute (op_array=0xfef1b0) at /build/buildd/php5-5.3.2/Zend/zend_vm_execute.h:104
#2  0x000000000069694d in zend_execute_scripts (type=0, retval=0x7fffffffbf90, file_count=3)
    at /build/buildd/php5-5.3.2/Zend/zend.c:1266
#3  0x0000000000642598 in php_execute_script (primary_file=0x2) at /build/buildd/php5-5.3.2/main/main.c:2288
#4  0x0000000000727a56 in main (argc=0, argv=0x1) at /build/buildd/php5-5.3.2/sapi/cli/php_cli.c:1196
(gdb) 

And the relevant bits from the extension:

PHP_MINIT_FUNCTION(pp)
{
        // Register PPKeyClient class
        zend_class_entry ce;
        INIT_CLASS_ENTRY(ce, "PPKeyClient", pp_functions);
        PPKeyClient_ce = zend_register_internal_class(&ce TSRMLS_CC);
        PPKeyClient_ce->create_object = PPKeyClient_object_new;
        memcpy(&PPKeyClient_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
        PPKeyClient_handlers.clone_obj = NULL;
        return SUCCESS;
}

zend_object_value PPKeyClient_object_new(zend_class_entry *ce TSRMLS_DC)
{
        zend_object_value retval;
        PPKeyClient_object *intern;

        // TODO - only instantiate look at
        // http://stackoverflow.com/questions/1906565/php-extension-library-accessing-php-superglobals
        // or google for http://www.google.co.uk/search?hl=en&safe=off&q=superglobals+in+php+extensions&aq=f&aqi=&aql=&oq=&gs_rfai=

        intern = ecalloc(1, sizeof(PPKeyClient_object));
        zend_object_std_init(&(intern->std), ce TSRMLS_CC);
        zend_hash_copy(intern->std.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));

        intern->last_curl_result = PPKC_NO_REQUEST;

        retval.handle = zend_objects_store_put(intern, PPKeyClient_object_dtor, NULL, NULL TSRMLS_CC);
        retval.handlers = &PPKeyClient_handlers;
        return retval;
}

PHP_METHOD(PPKeyClient, __construct)
{
        PPKeyClient_object *intern;
        char *url, *ssl_ca_crt = NULL;
        int port = 80, url_len, ssl_ca_crt_len = 0, ua_len = 0;

        if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls", &url, &url_len, &port, &ssl_ca_crt, &ssl_ca_crt_len) == SUCCES$
        {
                intern = (PPKeyClient_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
//              intern->port = port;

//              intern->baseurl = estrndup(url, url_len);
//              intern->baseurl_len = url_len;
//       开发者_开发问答       intern->ssl_ca_crt = estrndup(ssl_ca_crt, ssl_ca_crt_len);
//              intern->ssl_ca_crt_len = ssl_ca_crt_len;
//              intern->useragent = "PP KeyClient (PPExt#" PHP_PRIVATE_PASSWORDS_EXTNAME " v" PHP_PRIVATE_PASSWORDS_VERSION ")";
        }
}

I know that commenting the intern = (PPKeyClient_object*)zend_object_store_get_object... line makes it work, but obviously I can't set the values from the constructor without that.

I'm so lost and would appreciate any help finding what's up!


I saw some Ubuntu versions that brings libsafe installed, if this was the case with Ubuntu 9.04 maybe the error was always there...

It is because libsafe can "avoid" some buffer overflows, double free and some other bugs.

I'm not familiar with PHP extensions... is getThis() a function from the PHP API or is yours? if it's yours can you send it?


I can't remember exactly how I fixed this - I think @SlappyTheFish was right - something to do with 64 bitness. I later re-installed the server to be 32-bit and I believe that fixed it, so essentially the problem wasn't solved but I worked around it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜