Does PHP do any parsing on the php.ini file?
Asked Answered
S

2

25

Running PHP Version 7.1.30 under RHEL 7.7.

I'm wanting to bump memory_limit, but wasn't sure if I had the syntax right (i.e. 256M or 256MB). So to start with I put a bad value "Hugo" in as the memory_limit setting. The trouble with this is the result of phpinfo() (run under httpd) literally has the string "Hugo" in place, i.e.:

enter image description here

So this has me somewhat concerned that PHP doesn't actually do any sanity checking for the value(s). (If the value provided was bad I would expect it to revert to a default, e.g.)

Can anyone comment on this - in particular, how do you know whether PHP will be enforcing things (if an arbitary string can be provided).

Shamrao answered 21/1, 2020 at 21:34 Comment(6)
Excellent question.Cachucha
From this: php.net/manual/en/faq.using.php#faq.using.shorthandbytes I'd assume it's the same as (int) 'HUGO'; // => 0. Which starts to fail on my machine at 2MB of memory used.Oliviero
For the record, the correct syntax is memory_limit 256M.Groundsill
@Oliviero I think you should public your answer. It's a good explanationDoss
@MaksymFedorov I'm hesitant as I've no real reference for my assumption. For now it's just an observation.Oliviero
@Oliviero You seem to be correct. Using memory_get_usage(TRUE) and memory_get_peak_usage(TRUE) seem to show that memory limit is 2MB. One way to surely know is by debugging PHP in gdb as memory_limit property for the interpreter isn't exposed in PHPPriddy
P
20

The confusing thing here is that the setting looks like an integer with some special syntax, but is internally defined as a string. The string is then parsed into a separate global variable whenever the value is changed. Crucially, the result of parsing the string to an integer isn't saved back to the settings table, so when you call phpinfo(), you see the original input, not the parsed value.

You can see this in the source:

The supported syntax is ultimately defined in zend_atol, which:

  1. parses the string for a numeric value, ignoring any additional text
  2. looks at the last character of the string, and multiplies the preceding value if it is g, G, m, M, k, or K

A value with no digits at the start will be parsed as zero. When setting the global variable, this will set the memory limit to the minimum allowed, based on the constant ZEND_MM_CHUNK_SIZE.

You can see the effect by setting the memory limit, then running a loop that quickly allocates a large amount of memory and seeing what comes out in the error message. For instance:

# Invalid string; sets to compiled minimum
php -r 'ini_set("memory_limit", "HUGO"); while(true) $a[]=$a;'
# -> PHP Fatal error:  Allowed memory size of 2097152 bytes exhausted

# Number followed by a string; takes the number
php -r 'ini_set("memory_limit", "4000000 HUGO"); while(true) $a[]=$a;'
# -> PHP Fatal error:  Allowed memory size of 4000000 bytes exhausted

# Number followed by a string, but ending in one of the recognised suffixes
# This finds both the number and the suffix, so is equivalent to "4M", i.e. 4MiB
php -r 'ini_set("memory_limit", "4 HUGO M"); while(true) $a[]=$a;'
# -> PHP Fatal error:  Allowed memory size of 4194304 bytes exhausted
Praefect answered 27/1, 2020 at 12:28 Comment(3)
Thank you @Praefect for that great assessment. Should one report this kind of thing in any sort of bugtracker? I find the response that phpinfo() generates highly counter-intuitive. And some debug output for what php does when it encounters unexpected values wouldn't go amiss, either.Cachucha
@Cachucha I guess you could raise a feature request on bugs.php.net, or send a message to the Internals mailing list which is where most co-ordination happens. I found a similar request from several years ago, but it doesn't seem to have had any response.Praefect
Thanks again, will look into that! :)Cachucha
H
0

First thing first, We first need to understand how PHP.ini work in the way of interpretation workflow. memory_limit is directives for PHP.

when using with PHP function you have to do something like this ini_set(‘memory_limit’,’256MB’). So, this function will temporarily set your value to the interpreter variable. If you see closer then you can get the two columns One is for the Local and One is for global. That shows the capability of the values to the individual respectively.

But, When you defined for global you need to set as a suffix with K, M, G respectively. If we exceed this value using apache .htaccess it requires the same for the PHP fpm.

Hermaherman answered 27/1, 2020 at 10:31 Comment(1)
I would like to kindly point out that the OP is not asking how to set the memory limit :)Kellby

© 2022 - 2024 — McMap. All rights reserved.