Repository navigation
Quote non-token characters in matchFormatPattern - #141
Merged
kylekatarnls merged 3 commits intoSep 6, 2026
Merged
Conversation
kylekatarnls
reviewed
Sep 5, 2026
kylekatarnls
reviewed
Sep 5, 2026
Contributor
|
I confirm that it was not initially intended that The "modifier" in this context refers to the non-date characters listed in https://www.php.net/manual/en/datetimeimmutable.createfromformat.php#datetimeimmutable.createfromformat.parameters However I suspect some might have misinterpreted this as a feature, may have think that I'll add a warning in the release since it can be a breaking change for a minority of users. I still proceed as I think the number of use cases where a format would contain multiple in a row the same unit must be quite small. |
hasFormatWithModifiers() interpolated the format string into the final PCRE pattern without quoting it: parentheses, quantifiers, alternation and anchors coming from the format had a regex meaning instead of matching literally. hasFormat() quoted its input while its sibling did not, so the two validators disagreed on identical inputs. Wrap token-generated fragments between null-byte sentinels during the substitution pass, then quote every remaining byte of the pattern, resolving backslash escapes to their literal target first.
Concatenate the leading-escapes capture instead of interpolating it, and drop the by-reference foreach: the loop already writes through $chunks[$index], so the reference and its trailing unset() were both unused.
kylekatarnls
force-pushed
the
fix/quote-match-format-pattern
branch
from
September 6, 2026 15:01
825ce2a to
15bd6b6
Compare
kylekatarnls
approved these changes
Sep 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
hasFormatWithModifiers()interpolated the format string into the final PCRE pattern without quoting it. Only format letters and modifiers were replaced; every other byte (parentheses, quantifiers, alternation, anchors) kept its regex meaning, so a caller-supplied format could alter the structure of the validation pattern rather than match literally:The inconsistency with
hasFormat()also meant the two validators disagreed on identical inputs.How it is fixed
matchFormatPattern()now wraps each token-generated regex fragment between null-byte sentinels during the substitution pass, then quotes every remaining byte of the pattern. Backslash escapes in the format (\T,\.) still resolve to their literal target, and token fragments (d,#,*,?,!,|,+) keep their regex meaning. Raw null bytes in the format are stripped before processing so they cannot collide with the sentinels.Behavior change to be aware of: a format containing unescaped regex metacharacters that used to be interpreted as pattern syntax (e.g.
.*,(a|b)) will now only match those characters literally. This matches whathasFormat()already did and whatcreateFromFormat()escape semantics imply.