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
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
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 10:01:28 2024 UTC