php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #68484 zend_parse_parameters returns an invalid resource pointer
Submitted: 2014-11-23 08:45 UTC Modified: 2014-11-23 10:16 UTC
From: jrhodes at redpointsoftware dot com dot au Assigned:
Status: Not a bug Package: Reproducible crash
PHP Version: 5.4.35 OS: openSUSE 13
Private report: No CVE-ID: None
 [2014-11-23 08:45 UTC] jrhodes at redpointsoftware dot com dot au
Description:
------------
Originally reported at https://bugzilla.redhat.com/show_bug.cgi?id=1167069.  At first I believed this was an issue with libvirt's PHP bindings, but after further investigation I'm somewhat sure this is a bug in PHP itself.

After expanding the parameter parsing call libvirt is making in "libvirt_network_set_active", it is effectively performing:

---------------------------------------------
PHP_FUNCTION(libvirt_network_set_active)                                                                                               
{                                                                                                                                      
        php_libvirt_network *network = NULL;                                                                                           
        zval *znetwork;
        unsigned int act = 0;                                                                                                          
        
        reset_error(TSRMLS_C);                                                                                                         
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &znetwork, &act) == FAILURE) {                                      
                set_error("Invalid arguments" TSRMLS_CC);                                                                              
                RETURN_FALSE;
        }

---------------------------------------------

After receiving a segmentation fault when zend_fetch_resource is called (not shown), I added the following code immediately after the above code snippet:

---------------------------------------------
        if (znetwork == NULL) {
                printf("znetwork is NULL.\n");                                                                                         
        } else {                                                                                                                       
                printf("znetwork is not NULL.\n");                                                                                     
        }
        
        zend_uchar tt;
        tt = znetwork->type;
---------------------------------------------

Under this scenario, I get a segmentation fault when "type" is accessed (effectively imitating the Z_TYPE_P macro used in zend_fetch_resource).  "znetwork is not NULL." is printed out, indicating the pointer is not null, but is also not valid.

However, when I change the parameter signature from "rl" to "rb", like so:

---------------------------------------------
PHP_FUNCTION(libvirt_network_set_active)                                                                                               
{                                                                                                                                      
        php_libvirt_network *network = NULL;                                                                                           
        zval *znetwork;
        zend_bool act = 0;                                                                                                          
        
        reset_error(TSRMLS_C);                                                                                                         
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rb", &znetwork, &act) == FAILURE) {                                      
                set_error("Invalid arguments" TSRMLS_CC);                                                                              
                RETURN_FALSE;
        }

---------------------------------------------

the segmentation fault no longer occurs.  This indicates that the source of invalid resource pointer is impacted by the type of the second parameter.

Test script:
---------------
<?php

$conn = libvirt_connect('connection_uri', false);

$network = libvirt_network_get($conn, 'network_name_here');

// This will return an error stating that it expected 2 parameters (the
// documentation states it only accepts 1 parameter, but that doesn't
// make much sense for this function call).
libvirt_network_set_active($network);

// Both of these calls will cause a segmentation fault.
libvirt_network_set_active($network, true);
libvirt_network_set_active($network, 1);

?>

Expected result:
----------------
libvirt's PHP extension should not crash (and perform it's expected behaviour).

Actual result:
--------------
Warning: libvirt_network_set_active() expects exactly 2 parameters, 1 given in /home/james/Projects/Phabricator/libvirt_tests/active_network.php on line 10

Warning: libvirt_network_set_active(): Invalid arguments in /home/james/Projects/Phabricator/libvirt_tests/active_network.php on line 10

Program received signal SIGSEGV, Segmentation fault.
0x000000000068bd4c in zend_fetch_resource (passed_id=passed_id@entry=0x7fffffffa228, default_id=default_id@entry=-1, resource_type_name=resource_type_name@entry=0x7ffff6092cb1 "Libvirt virtual network", found_resource_type=found_resource_type@entry=0x0, 
    num_resource_types=num_resource_types@entry=1) at /root/php-5.4.35/Zend/zend_list.c:126
126     /root/php-5.4.35/Zend/zend_list.c: No such file or directory.
(gdb) bt
#0  0x000000000068bd4c in zend_fetch_resource (passed_id=passed_id@entry=0x7fffffffa228, default_id=default_id@entry=-1, resource_type_name=resource_type_name@entry=0x7ffff6092cb1 "Libvirt virtual network", found_resource_type=found_resource_type@entry=0x0, 
    num_resource_types=num_resource_types@entry=1) at /root/php-5.4.35/Zend/zend_list.c:126
#1  0x00007ffff60889ea in zif_libvirt_network_set_active (ht=2, return_value=0x7ffff7fbf068, return_value_ptr=<optimized out>, this_ptr=<optimized out>, return_value_used=<optimized out>) at libvirt-php.c:7569
#2  0x0000000000720f78 in zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7f87060) at /root/php-5.4.35/Zend/zend_vm_execute.h:643
#3  0x00000000006a285c in execute (op_array=0x7ffff7fbe5f0) at /root/php-5.4.35/Zend/zend_vm_execute.h:410
#4  0x000000000067dffe in zend_execute_scripts (type=type@entry=8, retval=retval@entry=0x0, file_count=file_count@entry=3) at /root/php-5.4.35/Zend/zend.c:1329
#5  0x0000000000621349 in php_execute_script (primary_file=primary_file@entry=0x7fffffffc6d0) at /root/php-5.4.35/main/main.c:2502
#6  0x0000000000722df4 in do_cli (argc=4, argv=0x7fffffffdaa8) at /root/php-5.4.35/sapi/cli/php_cli.c:989
#7  0x00000000004298b8 in main (argc=4, argv=0x7fffffffdaa8) at /root/php-5.4.35/sapi/cli/php_cli.c:1365

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-11-23 10:16 UTC] nikic@php.net
-Status: Open +Status: Not a bug
 [2014-11-23 10:16 UTC] nikic@php.net
You're using a l (for "long") parameter, but pass an "unsigned int act" to it. On platforms where the size of int and long differ this will cause memory corruption. As arguments are pushed to the stack in reverse order it also affects the resource argument.
 [2014-11-23 11:08 UTC] jrhodes at redpointsoftware dot com dot au
Thanks for the explanation; it's highly appreciated.  I'll pass this back over to the libvirt-php bug tracker.
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Sun Nov 29 08:01:23 2020 UTC