php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79921 memory exhausted, on array definition, in require
Submitted: 2020-08-01 08:21 UTC Modified: 2020-08-03 17:18 UTC
From: chandleg at wizardsworks dot org Assigned:
Status: Wont fix Package: Scripting Engine problem
PHP Version: 7.2.32 OS: Slackware Linux
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: chandleg at wizardsworks dot org
New email:
PHP Version: OS:

 

 [2020-08-01 08:21 UTC] chandleg at wizardsworks dot org
Description:
------------
I have a 10006 line "config" file, which is an array set for data values.
The format is: array(int, int, int, float, array, array, array)
Exerpt:

<?php
$star_map = array (
array(-587, 418, -182, 849.85998846869, array(2, 2), array(5.96541E+29, 5.96541E+29), array(278538822.144, 278538822.144),
array(-949, 457, -877, 1603.2251869279, array(2, 2), array(5.96541E+29, 5.96541E+29), array(278538822.144, 278538822.144),
array(1087, -401, 144, 1543.9799221492, array(2, 2), array(5.96541E+29, 5.96541E+29), array(278538822.144, 278538822.144),

........

array(-685, 113, -82, 972.20059658488, array(2), array(5.96541E+29), array(278538822.144),
array(554, 244, -57, 785.54503371863, array(2, 2), array(5.96541E+29, 5.96541E+29), array(278538822.144, 278538822.144),
array(1022, -77, -865, 1684.3969247182, array(2, 2), array(5.96541E+29, 5.96541E+29), array(278538822.144, 278538822.144),
);
?>


Test script:
---------------
<?php
require "./config.php";
?>

Expected result:
----------------
I would expect it to properly import the inline code.

Actual result:
--------------
redacted:~/public_html/game/tmp$ php index.php
PHP Parse error:  memory exhausted in ./chart.php on line 2500


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-08-01 08:28 UTC] chandleg at wizardsworks dot org
I meant to mention the array format is variable
array of:
array(int, int, int, float, array, array, array)
Where each 3rd level array is of 1-3 elements, but the same number of elements of the other arrays in the 2nd level.

Also the 100006 line file is 1.2Meg.

It appears to be running out of stack/heap trying to load it, but I thought that arrays in PHP were unlimited size, the best calculation I have on this, is it should be around 22Meg in memory.

It's tossing "memory exhausted" in the parser, not in the running, so I'm wondering what the limit for either a require, or an array is.

I am fairly certain I have function files I include larger than 10,000 lines, and I am extremely certain I have arrays with element counts over 300,000.
 [2020-08-01 15:22 UTC] cmb@php.net
-Status: Open +Status: Feedback -Package: Unknown/Other Function +Package: Scripting Engine problem -Assigned To: +Assigned To: cmb
 [2020-08-01 15:22 UTC] cmb@php.net
Does that also happen with any of the actively supported PHP
versions[1]?

[1] <https://www.php.net/supported-versions.php>
 [2020-08-01 21:42 UTC] chandleg at wizardsworks dot org
-Status: Feedback +Status: Assigned
 [2020-08-01 21:42 UTC] chandleg at wizardsworks dot org
I genuinely don't know.  Of all the machines I have this one has the latest version of PHP installed.
I can drop the config file in a place to test, if someone who does have a machine laying around with a newer version installed wants to try.
 [2020-08-01 21:43 UTC] chandleg at wizardsworks dot org
Alternatively I can also post the code used to generate the file itself.
 [2020-08-02 09:56 UTC] cmb@php.net
-Status: Assigned +Status: Open -Assigned To: cmb +Assigned To:
 [2020-08-02 09:56 UTC] cmb@php.net
> Alternatively I can also post the code used to generate the file
> itself.

That may be helpful.
 [2020-08-03 05:13 UTC] chandleg at wizardsworks dot org
This will generate a config, one which should result in 10006 lines of output, which can be redirected to a file.
I run it: php create.php >config.php


<?php

$num_stars = 10000;
$star_map = array();

$width = 2500;
$height = 1000;
$x_origin = ( $width / 2 );
$y_origin = ( $height / 2 );

$sol_radius = 696347055.36;
$sol_mass = 1.98847 * pow(10, 30);
$light_year = 9.4607 * pow(10, 15);
$G = 6.67408 * pow(10, -11);
$c = 299792458;
#### BlackHole, Class D, Class M, Class K, Class, G, Class F, Class A, Class B, Class O
$star_radius = array(0, ( 2.765945676 * pow(10, -27) ), 0.4, 0.9, 1.1, 1.3, 2.5, 7, 15);
$star_mass = array(0, 1.4, 0.3, 0.8, 1.1, 1.7, 3.2, 18, 60);

#### 1-800 Binary, 801-819% Trinary, 820-900% Single
$star_systems_chart = array(array(1, 158), array(159, 979), array(980, 1000));

#### BlackHole, Class D, Class M, Class K, Class, G, Class F, Class A, Class B, Class O
$star_system_distribution_chart = array(array(1, 100000), array(100001, 150000), array(150001, 866964), array(866965, 936965), array(936966, 971996), array(971996, 991996), array(991997, 998997), array(998998, 999998), array(999999, 1000000));


#$star_colors = array( $BlackHole, $Neutron, $Class_M, $Class_K, $Class_G, $Class_F, $Class_A, $Class_B, $Class_O );

function find_in_chart ( $value, $chart )
  {
    for ( $x = 0; $x < count($chart); $x = $x + 1 )
      {
        if (( $value >= $chart[$x][0] ) and ( $value <= $chart[$x][1] ))
          {
            return $x;
          }
        else
          {
          }
      }
  }

function devation ( $value, $low, $high )
  {
    $dev = rand(( $low / 100 ), ( $high / 100 ));
    return ( $value + ( $value * $dev ) );
  }

function blackhole ( )
  {
    global $G, $c, $sol_radius, $sol_mass;
    $mass = ( rand(3, 70) * $sol_mass );
    $radius = (( 2 * $mass * $G ) / pow($c, 2));
    return array($mass, $radius);
  }

function array_output ( $tmp_array )
  {
    $tmp = "array(";
    foreach ( $tmp_array as $key => $value )
      {
        $tmp = $tmp . $value . ", ";
      }
    return trim($tmp, ", ") . "), ";
  }

echo "<?php\n\$star_map = array (\n";
for ( $x = 1; $x <= $num_stars; $x = $x + 1 )
  {
    $i = rand(( 1 - $x_origin ), $x_origin);
    $j = rand(( 1 - $y_origin ), $y_origin);
    $k = rand(-1000, 1000);
#### Calculate distance between origin and end of vector
    $distance = sqrt(pow($i, 2) + pow($i, 2) + pow($k, 2));
#### 1-800 Binary, 801-819% Trinary, 820-900% Single, 901-908 Neutron Star, 909-1000 BlackHole
    $star_system_count = rand(1, 1000);
    $stars = ( find_in_chart($star_system_count, $star_systems_chart) + 1 );
    $star_system = array();
    $masses = array();
    $radius = array();
    for ( $y = 1 ; $y <= $stars; $y = $y + 1 )
      {
#        $class = rand(0, 6);
####    Class
        $Class = find_in_chart(rand(1, 1000000), $star_system_distribution_chart);
        $star_system[$y] = $Class;
        if ( $Class != 0 )
          {
####        Mass
            $masses[$y] = devation($sol_mass * $star_mass[$Class], -10, 10);
####        Radius
            $radius[$y] = devation($sol_radius * $star_radius[$Class], -10, 10);
          }
        else
          {
            $tmp = blackhole();
            $masses[$y] = $tmp[0];
            $radius[$y] = $tmp[1];
          }
      }

    $star_map[] = array($i, $j, $k, $distance, $star_system, $masses, $radius);
    echo "array($i, $j, $k, $distance, ";
    echo array_output($star_system);
    echo array_output($masses);
    echo array_output($radius);
    echo "\n";
  }
echo ");\n?>\n"

?>
 [2020-08-03 08:48 UTC] nikic@php.net
-Status: Open +Status: Wont fix
 [2020-08-03 08:48 UTC] nikic@php.net
I can reproduce the issue with the provided script. The problem is that your generated code missing a ")," at the end of each line, which means that instead of generating a simple array of arrays, it generates a 10000-level deeply nested array, and the parser runs out of parser stack memory. Now we *could* raise YYMAXDEPTH from the default of 10000, but given that the generated code is incorrect (and would fail to parse anyway in the end), this example does not seem like a good motivation to do so.
 [2020-08-03 17:18 UTC] chandleg at wizardsworks dot org
You are completely correct, and I am _very_ sorry to have wasted your time...
I had the following code in there at some point, and through a revision change/merge it got stomped out...  I can't believe I didn't see that.

    echo array_output($masses);
    echo trim(array_output($radius), ", ");
    echo "),\n";
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Thu Jul 03 17:01:33 2025 UTC