php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #39036 Unsetting key of foreach() yields segmentation fault
Submitted: 2006-10-04 12:49 UTC Modified: 2006-10-05 11:46 UTC
From: Bjorn dot Wiberg at its dot uu dot se Assigned:
Status: Closed Package: Reproducible crash
PHP Version: 5.1.6 OS: AIX 5.2.0 ML8
Private report: No CVE-ID: None
 [2006-10-04 12:49 UTC] Bjorn dot Wiberg at its dot uu dot se
Description:
------------
Two foreach() iterations after each other, where the second one unsets "non-whitelisted" variables, yields a segmentation fault when it hits the variable "key" (which has been used both in the first foreach() loop and the second one).

Removing the first foreach() loop makes the problem disappear. Adding "key" to the whitelist so that it doesn't get unset from inside the foreach loop makes the problem go away.

Sorry for the PHP version 5.1.5 -- others have found the same problem on FreeBSD with PHP 5.1.6, and also reported that it is gone in PHP 5.2 snapshot. I've come across the problem with PHP 5.1.5 on a Debian Linux on x86.

But why did it happen? Just wanted to ensure that this "case" has been thought of somewhere along the possible bugfixes of foreach() etc.

The problem appears in recent versions of phpMyAdmin (2.9.0.1 and 2.9.0.2) where this code is used for security purposes.

Best regards,
Bj?rn

Reproduce code:
---------------
http://www.anst.uu.se/bwiberg/php/foreach_segfault.php.txt

Expected result:
----------------
That the script finished with the text "Finished.".

Actual result:
--------------
The script segfaults (both when run through Apache 2 + PHP as handler), and through CLI PHP:

php ./foreach_segfault.php.txt:
---8<---
Current date and time is: Wed, 04 Oct 2006 12:43:42 UTC<BR>Defined variables before unsetting:<BR><BR><PRE>Array
(
    [GLOBALS] => Array
        (
            [GLOBALS] => Array
/../
    [dummy] => dummy
    [key] => key
)
</PRE><PRE>Investigating variable GLOBALS...<BR>Investigating variable _ENV...<BR>Investigating variable HTTP_ENV_VARS...<BR>Not in whitelist array, so unsetting variable HTTP_ENV_VARS...<BR>Finished unsetting variable HTTP_ENV_VARS.<BR>Investigating variable argv...<BR>Not in whitelist array, so unsetting variable argv...<BR>Finished unsetting variable argv.<BR>Investigating variable argc...<BR>Not in whitelist array, so unsetting variable argc...<BR>Finished unsetting variable argc.<BR>Investigating variable _POST...<BR>Investigating variable HTTP_POST_VARS...<BR>Not in whitelist array, so unsetting variable HTTP_POST_VARS...<BR>Finished unsetting variable HTTP_POST_VARS.<BR>Investigating variable _GET...<BR>Investigating variable HTTP_GET_VARS...<BR>Not in whitelist array, so unsetting variable HTTP_GET_VARS...<BR>Finished unsetting variable HTTP_GET_VARS.<BR>Investigating variable _COOKIE...<BR>Investigating variable HTTP_COOKIE_VARS...<BR>Not in whitelist array, so unsetting variable HTTP_COOKIE_VARS...<BR>Finished unsetting variable HTTP_COOKIE_VARS.<BR>Investigating variable _SERVER...<BR>Investigating variable HTTP_SERVER_VARS...<BR>Not in whitelist array, so unsetting variable HTTP_SERVER_VARS...<BR>Finished unsetting variable HTTP_SERVER_VARS.<BR>Investigating variable _FILES...<BR>Investigating variable HTTP_POST_FILES...<BR>Not in whitelist array, so unsetting variable HTTP_POST_FILES...<BR>Finished unsetting variable HTTP_POST_FILES.<BR>Investigating variable _REQUEST...<BR>Investigating variable dummy...<BR>Not in whitelist array, so unsetting variable dummy...<BR>Finished unsetting variable dummy.<BR>Investigating variable key...<BR>Not in whitelist array, so unsetting variable key...<BR>Segmentation fault (core dumped)
--->8---

---8<---
GNU gdb 5.0-aix51-020209
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "powerpc-ibm-aix5.2.0.0"...
Core was generated by `php'.
Program terminated with signal 11, Segmentation fault.
bt full
#0  zend_inline_hash_func (arKey=0x5a5a5a5a <Address 0x5a5a5a5a out of bounds>, nKeyLength=1515870811) at /usr/local/src/php-5.1.5/Zend/zend_hash.h:252
252                     hash = ((hash << 5) + hash) + *arKey++;
(gdb) bt full
#0  zend_inline_hash_func (arKey=0x5a5a5a5a <Address 0x5a5a5a5a out of bounds>, nKeyLength=1515870811) at /usr/local/src/php-5.1.5/Zend/zend_hash.h:252
        hash = 5381
#1  0x100a02a0 in ZEND_UNSET_VAR_SPEC_CV_HANDLER (execute_data=0x2ff20d88) at /usr/local/src/php-5.1.5/Zend/zend_vm_execute.h:22
        ex = (zend_execute_data *) 0x2ff20d88
        hash_value = 808700068
        opline = (zend_op *) 0x3033c8a4
        tmp = {value = {lval = 804391336, dval = 9.7360492442591142e-78, str = {val = 0x2ff209a8 "/?\r?H\"\"(\020\004??get", len = 0}, ht = 0x2ff209a8, obj = {handle = 804391336, handlers = 0x0}}, 
  refcount = 268825616, type = 48 '0', is_ref = 51 '3'}
        varname = (zval *) 0x3033854c
        opline = (zend_op *) 0x3033c8a4
        tmp = {value = {lval = 804391336, dval = 9.7360492442591142e-78, str = {val = 0x2ff209a8 "/?\r?H\"\"(\020\004??get", len = 0}, ht = 0x2ff209a8, obj = {handle = 804391336, handlers = 0x0}}, 
  refcount = 268825616, type = 48 '0', is_ref = 51 '3'}
        varname = (zval *) 0x3033854c
#2  0x100a0214 in ZEND_UNSET_VAR_SPEC_CV_HANDLER (execute_data=0x0) at /usr/local/src/php-5.1.5/Zend/zend_vm_execute.h:20
        opline = (zend_op *) 0x3033c8a4
        tmp = {value = {lval = 808038760, dval = 1.1094452222986143e-76, str = {val = 0x3029b168 <Address 0x3029b168 out of bounds>, len = 808621468}, ht = 0x3029b168, obj = {handle = 808038760, 
      handlers = 0x3032959c}}, refcount = 0, type = 0 '\000', is_ref = 0 '\000'}
        varname = (zval *) 0x3033854c
#3  0x1004eef4 in execute (op_array=0x30337c0c) at /usr/local/src/php-5.1.5/Zend/zend_vm_execute.h:92
        execute_data = {opline = 0x2ff229ea, function_state = {function_symbol_table = 0x301eaae0, function = 0x30329678, reserved = {0x0, 0x30329cc8, 0x303384f8, 0xd01f263c}}, fbc = 0x301ce974, 
  op_array = 0x2ff20a48, object = 0xf11ded04, Ts = 0x3033ab6c, CVs = 0x10, original_in_execution = 0 '\000', symbol_table = 0x6000000, prev_execute_data = 0xdeadbeef, old_error_reporting = 0x2ff20a28}
#4  0x10014f5c in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /usr/local/src/php-5.1.5/Zend/zend.c:1109
        files = 0x2ff20d88 "03Ȥ"
        i = 808680460
        file_handle = (zend_file_handle *) 0x2ff20d48
        orig_op_array = (zend_op_array *) 0x0
        local_retval = (zval *) 0x0
#5  0x10006ea4 in php_execute_script (primary_file=0x70726f63) at /usr/local/src/php-5.1.5/main/main.c:1737
        realfile = "?\032?0????\000\000\000\000?\031\216?/?\020??\035?\004?\037:?0\034?t/?\020??\035?\0040.\035(nfin", '\000' <repeats 12 times>, "????\000\000\000\000/?\026C\000\000\000\000\000\000\000 \000\000\000=\000\000\000\0000,???\032ը/?\021(D\"BD?(?`init/?\021(\000\000\000\0060-?\230\000\000\000\005/?\021@", '\000' <repeats 16 times>, "?\032?,\000\000\000\000\000\000\000 \000\000\000=0,???\032?0?\032ը/?\036XB\"BH?(?l1\000\000\005\000\000\006`\000\000\000\004atanh\000?t"...
        orig_bailout = {-249899608, 804393064, 808328456, 808233448, 0, 2, 0, -249652936, 804392920, -249697020, -803220412, 0, 0, 0, 0, -1, 0, 0, 0, 0, -249899584, 0, 808233384, 6, 804393000, 606224964, 
  -803264964, 808233400, 804393000, -249697020, -803264964, -249652936, 804393016, -249697020, 0, 0, 804393032, 804393064, 808301800, 808301752, -249899036, 24, 808233384, 6, 804393176, 24, -802632136, 
  -249985232, 804393080, -249697020, -802585548, 805366132, 804393096, -249697020, -803263728, 11, 804393112, -249697020, 808301800, 22528, 1668247156, 1768846693, 0, 32}
        orig_bailout_set = 0 '\000'
        prepend_file_p = (zend_file_handle *) 0x0
        append_file_p = (zend_file_handle *) 0x0
        prepend_file = {type = 0 '\000', filename = 0x302e1d00 <Address 0x302e1d00 out of bounds>, opened_path = 0x2e1d00 <Address 0x2e1d00 out of bounds>, handle = {fd = -249652936, fp = 0xf11e9938, stream = {
      handle = 0xf11e9938, reader = 0x2ff20f98, closer = 0xf11ded04 <__lc_charmap_ptr>, fteller = 0x302e1d40, interactive = 5008}}, free_filename = 0 '\000'}
        append_file = {type = 0 '\000', filename = 0x0, opened_path = 0x0, handle = {fd = -249652936, fp = 0xf11e9938, stream = {handle = 0xf11e9938, reader = 0, closer = 0xffffffff, fteller = 0xffffffff, 
      interactive = 24}}, free_filename = 47 '/'}
        old_cwd = 0x6 ""
        retval = 1836343155
#6  0x100022a4 in main (argc=2, argv=0x2ff2292c) at /usr/local/src/php-5.1.5/sapi/cli/php_cli.c:1093
        orig_bailout = {0 <repeats 64 times>}
        exit_status = 0
        c = 1515870810
        file_handle = {type = 2 '\002', filename = 0x2ff229ea "./foreach_segfault.php.txt", opened_path = 0x30337afc <Address 0x30337afc out of bounds>, handle = {fd = -249983288, fp = 0xf1198ec8, stream = {
      handle = 0xf1198ec8, reader = 0x301bc3f8 <__dbargs+2260>, closer = 0x301bc404 <__dbargs+2272>, fteller = 0x301bc3ec <__dbargs+2248>, interactive = 0}}, free_filename = 0 '\000'}
        behavior = 1
        reflection_what = 0xa0002 <Address 0xa0002 out of bounds>
        orig_optind = 1
        orig_optarg = 0x0
        arg_free = 0x2ff229ea "./foreach_segfault.php.txt"
        arg_excp = (char **) 0x5a5a00
        script_file = 0x2ff229ea "./foreach_segfault.php.txt"
        global_vars = {head = 0x0, tail = 0x0, count = 0, size = 4, dtor = 0, persistent = 0 '\000', traverse_ptr = 0x19}
        interactive = 0
        module_started = 1
        lineno = 1
        exec_direct = 0x0
        exec_run = 0x0
        exec_begin = 0x0
        exec_end = 0x0
        param_error = 0x0
        hide_argv = 0
#7  0x10000204 in __start ()
No symbol table info available.
(gdb) quit
--->8---

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-10-04 13:00 UTC] tony2001@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5.2-latest.tar.gz
 
For Windows:
 
  http://snaps.php.net/win32/php5.2-win32-latest.zip

Cannot reproduce.
 [2006-10-04 13:25 UTC] kian dot mohageri at gmail dot com
Just to chime in, I experienced this same issue with PHP 5.1.6 on FreeBSD 6.1.  I tested the 5.2 snapshot though, and the issue was gone.

I couldn't find a bug for it, though, so I'm not sure when it got fixed.  There were a few somewhat similar reports though relating to unset().

The following code will produce it every time -- but as I said, this is fixed in the 5.2 snapshot I tried (200610040230).

<?php

$key = 'asdf';

foreach (get_defined_vars() as $key => value) {
    unset($$key);
}

?>
 [2006-10-05 11:42 UTC] Bjorn dot Wiberg at its dot uu dot se
Confirmed OK with php5.2-200610050830 (5.2.0RC5-dev).

Wondering if there is some changelog entry for foreach() or unset() which may explain the old (segfaulting) behavior? Otherwise there is a chance that the bug is still latent and may resurface at a later time.

Best regards,
Bj?rn
 [2006-10-05 11:46 UTC] tony2001@php.net
No, there is no changelog entry, but I've added a test for it, so it won't appear unnoticed anymore.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Mar 29 15:01:28 2024 UTC