php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #25916 get_browser() -> PHP Fatal error: Nesting level too deep - recursive dependency?
Submitted: 2003-10-20 03:39 UTC Modified: 2003-12-04 03:59 UTC
From: thetaphi@php.net Assigned:
Status: Closed Package: Scripting Engine problem
PHP Version: 4.3.5 OS: Solaris 9
Private report: No CVE-ID:
 [2003-10-20 03:39 UTC] thetaphi@php.net
Description:
------------
The following error occurs sometimes on the ext/standard function get_browser():
[20/Oct/2003:08:54:59] info (13034):  for host p5084725C.dip.t-dialin.net trying to GET /index.php, php4_execute reports: PHP Fatal error: Nesting level too deep - recursive dependency? in /pangaea/htdocs/www.pangaea.de/index.php on line 28  

Line 28 contains the call to get_browser(). All other PHP functions do not fail. In other scripts which use get_browser() the error also occurs.

The problem is: You cannot reproduce it, because it happens only on heavy server load and when it happens the first time it does not go away until server restart.

PHP runs on SunONE with NSAPI, so compiled with ZTS.

I would debug the code and fix the error; but my problem is that I do not know WHERE in get_browser the error occurs.

Uwe

Reproduce code:
---------------
<?php
    // look if referer comes from google and extract search query
    // http://www.google.de/search?sourceid=navclient&hl=de&q=%22age%2C+error%22+pangaea
    // http://www.google.de/search?q=%22age,+error%22+pangaea&hl=de&lr=&ie=UTF-8&filter=0
    if (isset($_GET['query'])) {
        $query=$_GET['query'];
    } else {
        if (isset($_SERVER['HTTP_REFERER']) && preg_match('/^http:\/\/.*?google\..*?\/search\?(.*?)$/i', $_SERVER['HTTP_REFERER'], $matches)) {
            $a = split ('&', $matches[1]);
            for ($i=0; $i<count($a); $i++) {
                $b = split ('=', $a[$i]);
                $name=urldecode ($b[0]);
                $value=urldecode ($b[1]);
                switch ($name) {
                    case 'q':
                        $query=$value;
                        break;
                    case 'ie':
                        $encoding=$value;
                        break;
                }
            }
        }
        if (isset($query) && isset($encoding)) $query=mb_convert_encoding($query, "ISO-8859-1", $encoding);    
    }

    // detect browser
    $browser=get_browser();
    
    // if not crawler redirect user to homepage (do not forget to transmit query because referer can get invalid after redirect)
    if ((!$browser->crawler) && isset($_SERVER['PATH_INFO'])) {
        if (isset($query)) {
            header("Location: http://".$_SERVER['HTTP_HOST']."/?query=".urlencode($query));
        } else {
            header("Location: http://".$_SERVER['HTTP_HOST']."/");
        }
        exit();
    }

    // if a crawler like google is visiting: prepare keyword list to display and extract page number
    if ($browser->crawler) {
        $page=0;
        if (isset($_SERVER['PATH_INFO'])) {
            if (preg_match('/^\/(.*?)\.html$/', $_SERVER['PATH_INFO'], $matches)) {
                $page=$matches[1];
            } else {
                header("HTTP/1.0 404 Not Found");
                exit();
            }
        }
        $lines=file("../globals/googlelist.txt");
        if ($page*1000>=count($lines)) {
            header("HTTP/1.0 404 Not Found");
            exit();
        }
    }
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
...


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2003-11-19 10:57 UTC] jay@php.net
The browscap extension definitely leaks, but as far as I 
know, it's only during module startup/shutdown, and it's 
been like that since forever. I've never seen it blow up 
like this, but I can try to reproduce on Solaris 8 with 
iPlanet. Is there anything special that needs to be done 
besides hammering the test script with requests? 
 
I've been meaning to take another look at the browscap 
stuff, that extension has kind of been disowned... 
 
J 
 [2003-11-19 11:04 UTC] thetaphi@php.net
There are no special things to do. But the interesting thing is the following: since i replaced get_browser() by get_browser($_SERVER['HTTP_USER_AGENT']) it does not seem to crash anymore. So there must be some problem with reading the $_SERVER superglobal in the extension. But I am not sure, just a hint.
 [2003-12-03 11:27 UTC] thetaphi@php.net
last comment is not correct :( It happens also with parameter to get_browser($ua). The line with the error is always the one of get_browser.
 [2003-12-03 11:48 UTC] thetaphi@php.net
Looking through the code says to me that this error can only happen in zend_hash_apply_with_arguments(&browser_hash, (apply_func_args_t) browser_reg_compare, 2, lookup_browser_name, &found_browser_entry); (line 257), because in this function uses the recursion safety macros HASH_PROTECT_RECURSION(ht);

Could it be that this is a multithreading issue (if more than one thread uses the get_browser function simultan?). NSAPI is a multithreaded webserver.

Uwe
 [2003-12-04 03:59 UTC] thetaphi@php.net
This bug has been fixed in CVS.

In case this was a PHP problem, snapshots of the sources are packaged
every three hours; this change will be in the next snapshot. You can
grab the snapshot at http://snaps.php.net/.
 
In case this was a documentation problem, the fix will show up soon at
http://www.php.net/manual/.

In case this was a PHP.net website problem, the change will show
up on the PHP.net site and on the mirror sites in short time.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Fri Apr 18 10:03:03 2014 UTC