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 (profile)
Status: Closed Package: Reproducible crash
PHP Version: 5CVS-2005-03-07 OS: *
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: norxh at binnews dot com
New email:
PHP Version: OS:

 

 [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

Pull Requests

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-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 14 16:01:26 2024 UTC