Hi
The php.ini file parser (as used by
parse_ini_file()) supports
constant resolution, including core predefined constants. However, the
current behavior with undefined constants is inconsistent with PHP 8's
strict handling of undefined constants in regular PHP code.
How would PHP differentiate between “constants” and “unquoted strings”,
the latter of which are explicitly supported (and encouraged) by the INI
file format?
Best regards
Tim Düsterhus
Hi
The php.ini file parser (as used by
parse_ini_file()) supports
constant resolution, including core predefined constants. However, the
current behavior with undefined constants is inconsistent with PHP 8's
strict handling of undefined constants in regular PHP code.How would PHP differentiate between “constants” and “unquoted strings”, the latter of which are explicitly supported (and encouraged) by the INI file format?
As it does today, no change. If you use a word that would expand to a constant name as it does today, you need to quote it.
This preparatory step - if required - can be done in advance and the configuration file remains forwards / backwards compatible so can be used across versions (e.g. configuration file templates).
Best,
-- hakre
Hi
As it does today, no change. If you use a word that would expand to a constant name as it does today, you need to quote it.
That was not what I was asking for.
You are proposing to warn for undefined constants. How do you plan to
warn only for undefined constants, but not for unquoted strings?
Best regards
Tim Düsterhus
Hi
As it does today, no change. If you use a word that would expand to a constant name as it does today, you need to quote it.
That was not what I was asking for.
You are proposing to warn for undefined constants. How do you plan to warn only for undefined constants, but not for unquoted strings?
Best regards
Tim Düsterhus
Hi Tim,
Thanks for the clarification, and my apologies—my previous, shorter
answer missed the mark. Let me outline my understanding in greater
detail.
As noted in the implementation notes, I looked into
zend_ini_get_constant() and saw that the zend-ini parser doesn't
handle all unquoted strings, but only those matching IS_CONSTANT_AST,
which stems from:
CONSTANT [a-zA-Z_][a-zA-Z0-9_]*
My proposal is to apply the same test (Z_OPT_CONSTANT(tmp)) before
probing for the constant's existence (currently done via c = zend_get_constant(Z_STR_P(name)) != 0). This would address the current
ordering flaw in the parser as an incidental improvement.
More importantly, regarding your question, I've now looked more closely
at the CONSTANT regex and realize I was mistaken: I had assumed it
matched uppercase-only names, but it actually includes both upper- and
lowercase letters.
So, there would indeed be a change compared to my earlier answer: I now
propose using only uppercase names for constant resolution (and thus for
the warning you asked about). This would mean:
-
Allowing unquoted strings with lowercase characters to pass through
unchanged. -
Restricting constant name resolution to a pattern like:
CONSTANT_NAME [A-Z_][A-Z0-9_]*
...possibly with a minimum length greater than one, as shown.
In my view, this improves clarity in configuration contexts--at this
level, case-folding to lowercase shouldn't be necessary. That said,
your perspective may differ, and perhaps this was exactly the point you
were raising.
This revised understanding also suggests a more granular approach to
differentiating cases, enabling richer behavior. But first, I'd
appreciate your feedback on this more detailed reply.
Best regards,
Hans
So, there would indeed be a change compared to my earlier answer: I now
propose using only uppercase names for constant resolution (and thus for
the warning you asked about). This would mean:
Allowing unquoted strings with lowercase characters to pass through
unchanged.Restricting constant name resolution to a pattern like:
CONSTANT_NAME [A-Z_][A-Z0-9_]*
...possibly with a minimum length greater than one, as shown.
I don't think this kind of pattern matching is the right way to go. It's
perfectly normal in INI files to have all sorts of strings which aren't
quoted; looking through the samples provided in the source, I spotted this:
user_agent=PHP
No regex is going to recognise that that should be interpreted as "PHP",
not constant("PHP").
As I think I mentioned in an earlier message, the specific problem
raised seems to be more to do with string-to-int conversion, rather than
the INI parsing itself. Even if the invalid constant is surrounded by
quotes, this is not a useful setting:
error_reporting = "X_ERROR"|E_WARNING|E_PARSE|E_NOTICE
Maybe the part of the parser that handles operators is what needs a
behaviour change instead?
--
Rowan Tommins
[IMSoP]
Hi
Am 2025-10-20 20:17, schrieb Rowan Tommins [IMSoP]:
I don't think this kind of pattern matching is the right way to go.
It's perfectly normal in INI files to have all sorts of strings which
aren't quoted; looking through the samples provided in the source, I
spotted this:user_agent=PHP
No regex is going to recognise that that should be interpreted as
"PHP", not constant("PHP").
I agree with that. Supporting bare strings is a key feature and randomly
warning for some of them is going to be even more confusing than just
some of them randomly getting replaced by a different value just because
they happen to match a constant. In fact this made me realize that
parse_ini_*() is unsafe, because it doesn't just support internal
constants, but also constants defined in userland. I have thus just
proposed a new warning to be added to the documentation:
https://github.com/php/doc-en/pull/4946.
Given that the primary purpose of the constant support seems to be the
E_* constants for error_reporting, it might be best to instead only
support a small allow-list of safe constants in INI files.
Best regards
Tim Düsterhus
Hi
Am 2025-10-20 20:17, schrieb Rowan Tommins [IMSoP]:
I don't think this kind of pattern matching is the right way to go.
It's perfectly normal in INI files to have all sorts of strings which
aren't quoted; looking through the samples provided in the source, I
spotted this:user_agent=PHP
No regex is going to recognise that that should be interpreted as
"PHP", not constant("PHP").I agree with that. Supporting bare strings is a key feature and
randomly warning for some of them is going to be even more confusing
than just some of them randomly getting replaced by a different value
just because they happen to match a constant. In fact this made me
realize thatparse_ini_*()is unsafe, because it doesn't just
support internal constants, but also constants defined in userland.
I have thus just proposed a new warning to be added to the
documentation: https://github.com/php/doc-en/pull/4946.Given that the primary purpose of the constant support seems to be the
E_* constants forerror_reporting, it might be best to instead only
support a small allow-list of safe constants in INI files.
Another possible way would be to introduce a special syntax for
constants - just like we already have for environment variables.
Best regards
Tim Düsterhus