php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #58120 my_copy_zval_ptr does not check for my_copy_zval result being NULL
Submitted: 2008-03-26 07:10 UTC Modified: 2008-03-28 16:18 UTC
From: davidf at sjsoft dot com Assigned:
Status: Closed Package: APC (PECL)
PHP Version: 5.1.6 OS: Fedora Core 6
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: davidf at sjsoft dot com
New email:
PHP Version: OS:

 

 [2008-03-26 07:10 UTC] davidf at sjsoft dot com
Description:
------------
In apc_compile.c, my_copy_zval_ptr calls my_copy_zval to get a value dst_new. This is then compared to *dst and if it is different, *dst is deallocated and adjusted to point to dst_new.

The problem is that my_copy_zval can return NULL, in which case *dst is changed to NULL, and the setting of the refcount than segfaults.

(Note: this was originally detected using APC 3.0.16, but on inspection of the code the same problem is present in 3.0.17)

GDB backtrace:
Program terminated with signal 11, Segmentation fault.
#0  my_copy_zval_ptr (dst=0x2aaabed7a990, src=0x555557566a90, allocate=<value optimized out>, deallocate=0x2aaab8672280 <apc_sma_free>)
    at /usr/src/debug/APC-3.0.16/apc_compile.c:265
265         (*dst)->refcount = (*src)->refcount;

(full backtrace under Actual Results)

Variables using gdb coredump:
# this shows that dst was NULL on initial entry
local_dst_alloc = 1
dst_new = (zval *) 0x0
*src = (const zval *) 0x555557566a38
*dst = (zval *) 0x0
# 9 == IS_CONSTANT_ARRAY
(*src)->type = 9 '\t'
(*src)->value.ht = (HashTable *) 0x555557b75ae8

So for this case my_copy_zval returns NULL by using the CHEC K macro - if my_copy_hashtable returns NULL, so will my_copy_zval, and then the segfault will occur.


Reproduce code:
---------------
# In my_copy_zval_ptr
   dst_new = my_copy_zval(*dst, *src, allocate, deallocate);
    if(dst_new != *dst) {
        deallocate(*dst);
        *dst = dst_new;
    }

    Z_SET_REFCOUNT_PP(dst, Z_REFCOUNT_PP(src));

# In my_copy_zval
    case IS_CONSTANT_ARRAY:

        CHECK(dst->value.ht =
            my_copy_hashtable(NULL,
                              src->value.ht,
                              (ht_copy_fun_t) my_copy_zval_ptr,
                              (ht_free_fun_t) my_free_zval_ptr,
                              1,
                              allocate, deallocate));


Expected result:
----------------
No segfault :-)

Actual result:
--------------
Segfault; full backtrace:

Thread 1 (process 6632):
#0  my_copy_zval_ptr (dst=0x2aaabed7a990, src=0x555557566a90, allocate=<value optimized out>, deallocate=0x2aaab8672280 <apc_sma_free>)
    at /usr/src/debug/APC-3.0.16/apc_compile.c:265
#1  0x00002aaab866e098 in my_copy_hashtable_ex (dst=0x2aaabed245b8, src=<value optimized out>, copy_fn=0x2aaab866f7c0 <my_copy_zval_ptr>,
    free_fn=0x2aaab866d9a0 <my_free_zval_ptr>, holds_ptrs=1, allocate=0x2aaab86720d0 <apc_sma_malloc>, deallocate=0x2aaab8672280 <apc_sma_free>,
    check_fn=0x2aaab866dc50 <my_check_copy_default_property>) at /usr/src/debug/APC-3.0.16/apc_compile.c:972
#2  0x00002aaab866e8ea in apc_copy_new_classes (op_array=0x555558486fe8, old_count=95, allocate=0x2aaab86720d0 <apc_sma_malloc>,
    deallocate=0x2aaab8672280 <apc_sma_free>) at /usr/src/debug/APC-3.0.16/apc_compile.c:752
#3  0x00002aaab86710ef in my_compile_file (h=0x7fff780b1e90, type=8) at /usr/src/debug/APC-3.0.16/apc_main.c:461
#4  0x00002aaab5f77cb9 in ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER (execute_data=0x7fff780b2340) at /usr/src/debug/php-5.1.6/Zend/zend_vm_execute.h:1924
#5  0x00002aaab5f71dfc in execute (op_array=0x55555664fd68) at /usr/src/debug/php-5.1.6/Zend/zend_vm_execute.h:92
#6  0x00002aaab5f779fa in ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER (execute_data=0x7fff780b3030) at /usr/src/debug/php-5.1.6/Zend/zend_vm_execute.h:1971
#7  0x00002aaab5f71dfc in execute (op_array=0x555557beb7c8) at /usr/src/debug/php-5.1.6/Zend/zend_vm_execute.h:92
#8  0x00002aaab5f54efe in zend_execute_scripts (type=8, retval=<value optimized out>, file_count=3) at /usr/src/debug/php-5.1.6/Zend/zend.c:1109
#9  0x00002aaab5f19f57 in php_execute_script (primary_file=0x7fff780b55a0) at /usr/src/debug/php-5.1.6/main/main.c:1738
#10 0x00002aaab5fd23d6 in php_handler (r=0x555555d87f28) at /usr/src/debug/php-5.1.6/sapi/apache2handler/sapi_apache2.c:586
#11 0x000055555557dafa in ap_run_handler (r=0x555555d87f28) at /usr/src/debug/httpd-2.2.6/server/config.c:157
#12 0x0000555555580f8c in ap_invoke_handler (r=0x555555d87f28) at /usr/src/debug/httpd-2.2.6/server/config.c:372
#13 0x000055555558bb58 in ap_process_request (r=0x555555d87f28) at /usr/src/debug/httpd-2.2.6/modules/http/http_request.c:258
#14 0x0000555555588de0 in ap_process_http_connection (c=0x555555d404d8) at /usr/src/debug/httpd-2.2.6/modules/http/http_core.c:184
#15 0x0000555555584eb2 in ap_run_process_connection (c=0x555555d404d8) at /usr/src/debug/httpd-2.2.6/server/connection.c:43
#16 0x000055555558f7cb in child_main (child_num_arg=<value optimized out>) at /usr/src/debug/httpd-2.2.6/server/mpm/prefork/prefork.c:640
#17 0x000055555558fa5a in make_child (s=0x5555557b3d30, slot=1) at /usr/src/debug/httpd-2.2.6/server/mpm/prefork/prefork.c:736
#18 0x000055555558fb10 in startup_children (number_to_start=7) at /usr/src/debug/httpd-2.2.6/server/mpm/prefork/prefork.c:754
#19 0x0000555555590648 in ap_mpm_run (_pconf=<value optimized out>, plog=<value optimized out>, s=<value optimized out>)
    at /usr/src/debug/httpd-2.2.6/server/mpm/prefork/prefork.c:975
#20 0x000055555556b08b in main (argc=1, argv=0x7fff780b5bd8) at /usr/src/debug/httpd-2.2.6/server/main.c:730

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-03-26 07:17 UTC] davidf at sjsoft dot com
Patch that should fix this here and at http://davidf.sjsoft.com/files/APC-my_copy_zval-segfault.patch

--- apc_compile.c.orig  2008-03-26 00:46:41.000000000 -0500
+++ apc_compile.c       2008-03-26 07:03:48.000000000 -0500
@@ -296,7 +296,10 @@
         if(local_dst_alloc) deallocate(dst);
         return NULL;
     }
-    dst_new = my_copy_zval(*dst, *src, allocate, deallocate);
+    if(!(dst_new = my_copy_zval(*dst, *src, allocate, deallocate))) {
+        if(local_dst_alloc) deallocate(dst);
+        return NULL;
+    }
     if(dst_new != *dst) {
         deallocate(*dst);
         *dst = dst_new;
 [2008-03-28 16:06 UTC] rasmus@php.net
Fixed in CVS, thanks.
 [2008-03-28 16:18 UTC] rasmus@php.net
(part of 3.0.18)
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Sep 20 22:01:26 2024 UTC