php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #29944 Function defined in switch, crashes
Submitted: 2004-09-02 04:48 UTC Modified: 2005-04-25 12:04 UTC
Votes:27
Avg. Score:4.4 ± 1.0
Reproduced:25 of 25 (100.0%)
Same Version:10 (40.0%)
Same OS:2 (8.0%)
From: norxh at binnews dot com Assigned: andi
Status: Closed Package: Reproducible crash
PHP Version: 5CVS-2005-03-07 OS: *
Private report: No CVE-ID:
 [2004-09-02 04:48 UTC] norxh at binnews dot com
Description:
------------
Crashes when run in cli or apache2 with no external modules.

Reproduce code:
---------------
<?PHP
$a = 1;
$b = "1";
switch ($a) {
	case 1:
		function foo($bar) {
			if (preg_match('/\d/', $bar)) return true;
			return false;
		}
		echo foo($b);
}		
?>

Expected result:
----------------
1

Actual result:
--------------
crash

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2004-09-02 08:32 UTC] derick@php.net
Although I see no point in doing this at all (it should not necessarily work), it shouldn't crash either. 

valgrind:
==2720== Conditional jump or move depends on uninitialised value(s)
==2720==    at 0x83062CB: zend_switch_free (zend_execute.c:200)
==2720==    by 0x8302A8D: zend_switch_free_handler (zend_execute.c:3222)
==2720==    by 0x82FDC88: execute (zend_execute.c:1391)
==2720==    by 0x830140F: zend_do_fcall_common_helper (zend_execute.c:2728)
==2720==    by 0x8301890: zend_do_fcall_by_name_handler (zend_execute.c:2810)
==2720==
==2720== Use of uninitialised value of size 4
==2720==    at 0x8305E29: zend_pzval_unlock_func (zend_execute.c:65)
==2720==    by 0x83062E6: zend_switch_free (zend_execute.c:205)
==2720==    by 0x8302A8D: zend_switch_free_handler (zend_execute.c:3222)
==2720==    by 0x82FDC88: execute (zend_execute.c:1391)
==2720==    by 0x830140F: zend_do_fcall_common_helper (zend_execute.c:2728)
==2720==
==2720== Invalid read of size 4
==2720==    at 0x8305E29: zend_pzval_unlock_func (zend_execute.c:65)
==2720==    by 0x83062E6: zend_switch_free (zend_execute.c:205)
==2720==    by 0x8302A8D: zend_switch_free_handler (zend_execute.c:3222)
==2720==    by 0x82FDC88: execute (zend_execute.c:1391)
==2720==    by 0x830140F: zend_do_fcall_common_helper (zend_execute.c:2728)
==2720==  Address 0x8 is not stack'd, malloc'd or (recently) free'd
==2720==
==2720== Process terminating with default action of signal 11 (SIGSEGV)
==2720==  Access not within mapped region at address 0x8
==2720==    at 0x8305E29: zend_pzval_unlock_func (zend_execute.c:65)
==2720==    by 0x83062E6: zend_switch_free (zend_execute.c:205)
==2720==    by 0x8302A8D: zend_switch_free_handler (zend_execute.c:3222)
==2720==    by 0x82FDC88: execute (zend_execute.c:1391)
==2720==    by 0x830140F: zend_do_fcall_common_helper (zend_execute.c:2728)
==2720==


GDB:
0x08305e29 in zend_pzval_unlock_func (z=0x0)
    at /dat/dev/php/php-5.0dev/Zend/zend_execute.c:65
65              z->refcount--;
(gdb) bt
#0  0x08305e29 in zend_pzval_unlock_func (z=0x0)
    at /dat/dev/php/php-5.0dev/Zend/zend_execute.c:65
#1  0x083062e7 in zend_switch_free (opline=0x85bd95c, Ts=0x85bdfbc)
    at /dat/dev/php/php-5.0dev/Zend/zend_execute.c:205
#2  0x08302a8e in zend_switch_free_handler (execute_data=0xbfffd400,
    opline=0x85bd95c, op_array=0x85bded8)
    at /dat/dev/php/php-5.0dev/Zend/zend_execute.c:3222
#3  0x082fdc89 in execute (op_array=0x85bded8)
    at /dat/dev/php/php-5.0dev/Zend/zend_execute.c:1391
#4  0x08301410 in zend_do_fcall_common_helper (execute_data=0xbfffd4f0,
    opline=0x85bc4cc, op_array=0x85b7f5c)
    at /dat/dev/php/php-5.0dev/Zend/zend_execute.c:2728
#5  0x08301891 in zend_do_fcall_by_name_handler (execute_data=0xbfffd4f0,
    opline=0x85bc4cc, op_array=0x85b7f5c)
    at /dat/dev/php/php-5.0dev/Zend/zend_execute.c:2810
#6  0x082fdc89 in execute (op_array=0x85b7f5c)
    at /dat/dev/php/php-5.0dev/Zend/zend_execute.c:1391
#7  0x082da17f in zend_execute_scripts (type=8, retval=0x0, file_count=3)
    at /dat/dev/php/php-5.0dev/Zend/zend.c:1061
#8  0x08293dc7 in php_execute_script (primary_file=0xbffff930)
    at /dat/dev/php/php-5.0dev/main/main.c:1629
#9  0x0830a856 in main (argc=1, argv=0xbffffa04)
    at /dat/dev/php/php-5.0dev/sapi/cli/php_cli.c:943


Assinging to Andi.
 [2004-09-02 08:36 UTC] derick@php.net
This is only a problem in PHP 5.0.x (and not PHP 5.1.x-dev).
 [2004-11-10 15:53 UTC] sami at sipponen dot com
<?
switch ($_GET["test"]) {
  default:
    function testfunc() {
	}
  }
testfunc();
?>

This code crashes PHP 5.1.0-DEV Windows Version.
 [2004-12-16 21:18 UTC] edwin at phpfreakz dot nl
I didn't have any problems with declaring functions in a switch statement with Apache 2/PHP 5.0.1, but after installing PHP 5.0.3 php crashes. You don't get any errors, it just doesn't work.

I'm using Windows XP Pro with SP2.
 [2005-03-04 15:17 UTC] kameshj at fastmail dot fm
Problem is in CG(switch_cond_stack) that is shared by two op_arrays(One which has original switch and another one being the function declararion inside a case).


Case 1
----------------
<?php
function foo()
{
echo "hi";
}
?>
op_array of foo
ZEND_ECHO
ZEND_FETCH_CONSTANT
ZEND_RETURN
ZEND_HANDLE_EXCEPTION

Case 2(Segfault case)
----------------
<?php
$a=1;
switch($a)
{
case 1:
function foo()
{
echo "hi";
}
}
?>
op_array of foo
ZEND_ECHO
ZEND_FETCH_CONSTANT
ZEND_SWITCH_FREE
ZEND_RETURN
ZEND_HANDLE_EXCEPTION

In Case 2
ZEND_SWITCH_FREE opcode is getting included in the function foo's op_array.

This is done by zend_do_return in zend_compile.c with the following code
zend_stack_apply(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_switch_expr);

In zend_do_return of foo of Case 2,
While executing zend_stack_apply,
CG(switch_cond_stack) has 2 entries as follows,
foo's seperator dummy switch_cond(at top)
main op_array's switch case(at bottom)

"main op_array's switch case(at bottom)" is generating ZEND_SWITCH_FREE opcode.
I feel the switch_cond_stack to be op_array specific rather than keeping it at compiler_globals as it is now.
 [2005-04-02 12:05 UTC] dmhouse at gmail dot com
I have a reduced test case for this bug.

<?php

$foo = 'bar';

switch ($foo) {
	
	case 'bar':
		function foobar() {
			$variable = 1;
		}
		
		foobar();
	break;
	
}

?>

Things necessary for Apache to segfault:
* The function must be defined inside a case statement that is executed.
* A variable must be set to a value within the function.
* The function must be called.

I'm running PHP 5.0.3 (built from source, but I doubt that matters) on Apache 2. Bug is reproducible through Apache and through CLI.
 [2005-04-23 23:31 UTC] tingle at virtuanews dot co dot uk
I have just tried this with the latest CVS (after spending 4 hours bug finding!).  This bug is still in CVS.

Exactly the same as is shown here, the following will crash apache:

<?php

$do = 1;

switch ($do) {

default:

  function test_function()
  {
  	return 'Hello World';
  }

  echo test_function();
}

?>


This crashes both apache 1 and apache 2 on windows xp, macosx and linux based systems.  I was testing on the CVS from 23/04/05.
 [2005-04-25 12:04 UTC] dmitry@php.net
Fixed in CVS HEAD, PHP_5_0, PHP_4_3. PHP_4_3 seems already had fix for this problem but improper one.
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Fri Apr 18 15:02:26 2014 UTC