php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #47623 array_shift() fails with @ operator
Submitted: 2009-03-11 12:56 UTC Modified: 2016-03-27 20:12 UTC
Votes:8
Avg. Score:3.9 ± 0.9
Reproduced:7 of 7 (100.0%)
Same Version:5 (71.4%)
Same OS:5 (71.4%)
From: Henry at huis-stijl dot nl Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 5.*, 6CVS (2009-04-30) 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: Henry at huis-stijl dot nl
New email:
PHP Version: OS:

 

 [2009-03-11 12:56 UTC] Henry at huis-stijl dot nl
Description:
------------
Script was working perfectly on PHP 4 when updated to PHP5.2.9 I found an error. I was filling a array in the session and looped it with array_shift until the arry was empty. 
This loop kept giving me the first value but did not erased it from te original arry.

Reproduce code:
---------------
$row = array_shift(@$_SESSION['villas']);

Expected result:
----------------
1. $row getting the first element from $_SESSION['villas']
2. $_SESSION['villas'] to get lost the first element.


Actual result:
--------------
1. $row getting the first element from $_SESSION['villas']
2. $_SESSION['villas'] did not lost the first element and was unchanged


I cann bypass this failure by using:
$arr_temp = @$_SESSION['villas'];
$row = array_shift($arr_temp);
$_SESSION['villas'] = $arr_temp;
unset($arr_temp);



Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-03-11 14:07 UTC] Henry at huis-stijl dot nl
<?php
	session_start();
	ini_set('session.cache_limiter', 'private');
// ? 2009 Huis-stijl, Henry Hekman

	$_SESSION['villas'] = array
		(
			1 => array(1,2,3),
			2 => array(2,3,4),
			3 => array(3,4,5),
			4 => array(4,5,6),
		);

	While(@$_SESSION['villas'] != array())
		{
			$row = array_shift(@$_SESSION['villas']);
			print_r($row);
		}// einde while

?>

on php 4 i get
Array ( [0] => 1 [1] => 2 [2] => 3 ) Array ( [0] => 2 [1] => 3 [2] => 4 ) Array ( [0] => 3 [1] => 4 [2] => 5 ) Array ( [0] => 4 [1] => 5 [2] => 6 )

on phph 5.2.9 i get a loop that doesnt end
Array ( [0] => 1 [1] => 2 [2] => 3 ) Array ( [0] => 1 [1] => 2 [2] => 3 ) Array ( [0] => 1 [1] => 2 [2] => 3 ) Array ( [0] => 1 [1] => 2 [2] => 3 ) Array ( [0] => 1 [1] => 2 [2] => 3 ) Array ( [0] => 1 [1] => 2 [2] => 3 ) Array ( [0] => 1 [1] => 2 [2] => 3 ) Array ( [0] => 1 [1] => 2 [2] => 3 ) Array ( [0] => 1 [1] => 2 [2] => 3 ) Array ( [0] => 1 [1] => 2 [2] => 3 ) Array ( [0] => 1 [1] => 2 [2] => 3 ) Array ( [0] => 1 [1] => 2 [2] => 3 ) Array ( [0] => 1 [1] => 2 [2] => 3 )
 [2009-03-16 16:26 UTC] jani@php.net
If you remove those @'s, what does it output..?
 [2009-03-16 22:11 UTC] Henry at huis-stijl dot nl
Tried with and without the @ same output.
 [2009-04-13 18:23 UTC] jani@php.net
This has nothing to do with sessions. Simplified script:

<?php

$foo['villas'] = array('a','b','c');

while($foo['villas'] != array())
{
  $row = array_shift(@$foo['villas']); // Removing @ makes it work..
  var_dump($foo);
}
?>


 [2010-05-05 20:56 UTC] whatrevolution at yahoo dot com
<?php

$_SESSION['villas'] = array
(
	1 => array(1,2,3),
	2 => array(2,3,4),
	3 => array(3,4,5),
	4 => array(4,5,6),
);
/*
 *  ONE:
*/
/*
	While(@$_SESSION['villas'] != array())
		{
			$row = array_shift(@$_SESSION['villas']);
			print_r($row);
		}// einde while
*/

/*
 *  TWO:
*/
/*
while($foo['villas'] != array())
{
  $row = array_shift(@$foo['villas']); // Removing @ makes it work..
  var_dump($foo);
}
*/

/*
 *  THREE:
*/
//I cann bypass this failure by using:
$arr_temp = @$_SESSION['villas'];
$row = array_shift($arr_temp);
$_SESSION['villas'] = $arr_temp;
unset($arr_temp);
var_dump($_SESSION['villas']); 

?>

Result:

One and Two, same as described before.

Three:

array
  0 => 
    array
      0 => int 2
      1 => int 3
      2 => int 4
  1 => 
    array
      0 => int 3
      1 => int 4
      2 => int 5
  2 => 
    array
      0 => int 4
      1 => int 5
      2 => int 6


PHP Version 5.2.10-2ubuntu6.4

System 	Linux 2.6.31-20-generic x86_64
Build Date 	Jan 6 2010 22:36:47
Server API 	Apache 2.0 Handler 
PHP API 	20041225
PHP Extension 	20060613
Zend Extension 	220060519
Debug Build 	no
Thread Safety 	disabled
Zend Memory Manager 	enabled 

Apache/2.2.12 (Ubuntu)
 [2010-05-28 16:35 UTC] laruence at yahoo dot com dot cn
Hi, I found the same bug in php 5.2.8(linux)
and I also find out why:

in php complie phase,
@$var -> expr_without_variable;
//code
expr_without_variable:
...
   |   '@' { zend_do_begin_silence(&$1 TSRMLS_CC); }
       expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; }

while:
$var  -> variable
then this different cause the znode's difference
//
non_empty_function_call_parameter_list:
        expr_without_variable   { Z_LVAL($$.u.constant) = 1;  
zend_do_pass_param(&$1, ZEND_SEND_VAL, Z_LVAL($$.u.constant) TSRMLS_CC); }
    |   variable                { Z_LVAL($$.u.constant) = 1;  
zend_do_pass_param(&$1, ZEND_SEND_VAR, Z_LVAL($$.u.constant) TSRMLS_CC); }

then in zend_so_pass_param:
ZEND_SEND_VAR gen opcode:"SEND_REF", ZEND_SEND_VAR gen opcode:"SEND_VAR_NO_REF"

so when use @, cause param send without ref.

you can find more info on : http://www.laruence.com/2010/05/28/1565.html
 [2010-06-01 04:05 UTC] laruence at yahoo dot com dot cn
errata:

//then in zend_do_pass_param:
ZEND_SEND_VAR gen opcode:"SEND_REF", ZEND_SEND_VAL gen opcode:"SEND_VAR_NO_REF"
 [2016-03-27 20:12 UTC] nikic@php.net
-Status: Verified +Status: Not a bug
 [2016-03-27 20:12 UTC] nikic@php.net
As array_shift() uses by-reference argument passing and an error suppression expression is not a variable, this behavior is correct. Note that it throws the usual "only variables can be passed by reference" notice.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Oct 07 12:01:27 2024 UTC