php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #35733 preg_replace() distroys $GLOBALS
Submitted: 2005-12-19 15:01 UTC Modified: 2005-12-19 19:33 UTC
Votes:1
Avg. Score:4.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: gerhard at tinned-software dot net Assigned:
Status: Not a bug Package: PCRE related
PHP Version: 5.1.1 OS: WinXP/Linux
Private report: No CVE-ID: None
 [2005-12-19 15:01 UTC] gerhard at tinned-software dot net
Description:
------------
PHP 5 PCRE Bug!?

We have in our program a function to log all $GLOBALS variables. This function 
calls itself recursive to log all variables of a array and all its sub-arrays.

This function is working fine in PHP 4.0.1 and up to 4.3.10 (the highest of our 
test configuration.)

Since PHP5 (different versions) it was not working anymore when you call the function with $GLOBALS as 
parameter. The logfile contained only one line ...
|-> GLOBALS = Array

After some hours i go it working by replacing the preg_replace() function with
the ereg_replace() function.

The problem shows as follows:
After calling function preg_replace() the $GLOBALS array contails only 1 element
which is $GLOBALS. (i cheched it with count($GLOBALS);) after that the check 
is_array() is always returning "1" instead of true or false.

after replacing the ...
preg_replace("/\r*\n/", " ", $entry); 
... with  ...
ereg_replace("\n", " ", $entry); 
ereg_replace("\r", " ", $entry); 
... the function is working without problems. PHP must be configured correctly 
because this function preg_replace() is used very often in our program. This 
function is also workinf fine when called with any other array. Only when 
$GLOBALS is used to call this function it shows this behaviour.

We checked this behaviour with different PHP4.x (everything was working) and some versions of PHP5 (on all the same problem - last tested version 5.1.1). And also on different OS (Linux, MacOSX, WinXP, Win2000).



Reproduce code:
---------------
<?php
/*****************************************************************************/
/* This file is part of Tinned-Mail.                                         */
/*****************************************************************************/

array_log($GLOBALS);

function array_log($array, $level = 0){
    // create level space
    $level_space = "";
    for($i=0; $i < $level; $i++){
        $level_space .= "    ";
    }
    
    // print array entries 
    foreach($array as $key => $value){
        $entry = $value;
        $entry = preg_replace("/\r*\n/", " ", $entry);
        $entry2 = "$level_space|-> $key = $entry\n";
    	$FILE = fopen("array.log", "a");
    	fwrite($FILE, $entry2);
    	fclose($FILE);
    	echo is_array($value);
        if(is_array($value)){
            if($key == "GLOBALS"){ continue; }
            array_log($value, $level + 1);
        }
    }
}

?>

Expected result:
----------------
Logfile with PHP 5.1.1:
|-> GLOBALS = Array

Logfile with 4.x.x (as it should look like):
|-> HTTP_ENV_VARS = Array
    |-> DBROOT = /dev/null
    |-> BOOT_FILE = /boot/vmlinuz
    |-> HOSTNAME = mail
    |-> CONSOLE = /dev/console
    |-> LD_LIBRARY_PATH = :/lib
    .
    .
    .
|-> HTTP_POST_FILES = Array
|-> GLOBALS = Array
|-> GATEWAY_INTERFACE = CGI/1.1
|-> SERVER_PROTOCOL = HTTP/1.0
|-> REQUEST_METHOD = GET
|-> QUERY_STRING = 
.
.
.



Actual result:
--------------
Replace ...
$entry = preg_replace("/\r*\n/", " ", $entry);
... With ...
$entry = ereg_replace("\r", "", $entry);
$entry = ereg_replace("\n", " ", $entry);

After changing it to ereg_replace() it is working with PHP4.0.1, 4.3.10 and 5.1.1



Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-12-19 15:12 UTC] tony2001@php.net
$GLOBALS contains reference to itself.
In your code you're effectively converting all the elements to strings with preg_replace(), so GLOBALS itself becomes string too.
Not a bug.
 [2005-12-19 16:21 UTC] gerhard at tinned-software dot net
with preg_replace i only remove newlines from a string which contains the content of the variable! $value contains the content of the variable and is copied to $entry ... only $entry is changed not the $value which is used to check if it is an array and which is aslo used to call the function recursive!
foreach($array as $key => $value){
        $entry = $value;

how can this damage the $GLOBALS??? ... and if this is not a bug, way it is working with PHP4.x???
 [2005-12-19 16:27 UTC] sniper@php.net
If it worked in PHP 4 it's a bug there. Don't play around with GLOBALS like that. It's expected behaviour to work unexpectedly.
 [2005-12-19 16:29 UTC] tony2001@php.net
>$value contains the content of the variable and is copied to $entry
.. and since $entry is a reference, $value is a reference too.
It doesn't work in PHP4 either.
Add var_dump($GLOBALS); at the end of your code and you'll see it. 
It's expected.
 [2005-12-19 19:33 UTC] gerhard at tinned-software dot net
Way should $entry be a reference??
And when $entry is a reference and this is the correct behaviour, way is it then working with ereg_replace function???

If it is only a reference, how to make a real copy of it??
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 14:01:29 2024 UTC