php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #47577 { should be an escapable special character when paired with a trailing $
Submitted: 2009-03-05 18:38 UTC Modified: 2020-12-14 12:34 UTC
Votes:4
Avg. Score:3.8 ± 0.8
Reproduced:3 of 3 (100.0%)
Same Version:1 (33.3%)
Same OS:1 (33.3%)
From: bob at trivectus dot com Assigned:
Status: Suspended Package: Scripting Engine problem
PHP Version: 5.2.9 OS: *
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: bob at trivectus dot com
New email:
PHP Version: OS:

 

 [2009-03-05 18:38 UTC] bob at trivectus dot com
Description:
------------
Prior to 5.1.1, PHP always treated { as a special character that was
escapable. From 5.1.1 on, it's never treated as a special, escapable
character. Both behaviors are wrong in that both produce inconsistent
results when the { character is used in strings. The correct behavior
is to treat { as a special, escapable character only in the specific
case that it's immediately followed by a $.

The inconsistent behavior was discussed in bug 37263, but that bug did 
not directly address the core issue.

Reproduce code:
---------------
Dbeckham in bug 37263 is right: either { is a special character that
should be escapable as can any other special character, or it's a
normal character that doesn't affect string processing. Right now,
it's an incomprehensible mix of both. Another example that hits the
problem from a different direction is use of curly braces in PCRE
expressions, where they're are used to tell the engine the minimum and
maximum number of times the preceding pattern should be repeated to be
a match. Assume we're trying to do a replace with this PCRE search
pattern:

	/a{2,5}b/

Now, in our PHP context, assume the 2 and 5 are variables:

	$min = 2;
	$max = 5;

The most obvious syntax for the preg_replace call is:

	$foo = preg_replace("/a{$minCount,$maxCount}b/", 'x', $foo);

However, it won't work. Neither do any of these alternatives that a 
reasonable programmer might try:

	$foo = preg_replace("/a\{$minCount,$maxCount}b/", 'x', $foo);

	$foo = preg_replace("/a{\$minCount,$maxCount}b/", 'x', $foo);

	$foo = preg_replace("/a\{\$minCount,$maxCount}b/", 'x', $foo);

To get this to work, one must use this:

	$foo = preg_replace("/a{{$minCount},$maxCount}b/", 'x', $foo);

Yes, I know it's documented that { is not a special character, but a
documented design bug is still very much a design bug. But the problem
is, { *is* a special character when followed by a $. The need to
document how to handle the situations where you don't want the {
processed--and how, even now, those situations are only partly
documented--illustrates that PHP's approach here is ill-thought.

I think the root of this problem is that PHP treats { as special only
when it's paired with a $. This means it's special in some cases and
not special in others, which in turn means that always making it
escapable (the pre-5.1.1 behavior) or always making it not escapable
(the current behavior) are both inherently going to be wrong in some
situations. The correct solution is to make { an escapable special
character in exactly those situations when it is, in fact, special.
Namely, when it's immediately followed by a $. When the preceding { is
escaped, PHP should attempt to interpret the $ expression just as it
would without the {. When the { is not followed by a $ and thus is not
special, it should not be escapable. Thus:

	$world = 'foo';
	"hello $world" => "hello foo"
	"hello {$world}" => "hello foo"
	"hello \{$world}" => "hello {foo}"
	"hello {\$world}" => "hello {$world}"
	"hello \{\$world}" => "hello \{$world}"

The result is completely self-consistent and consistent with the rest
of PHP's escaping behavior, which means there aren't exceptions to
document and confuse the poor programmer just trying to write some
code.


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-04-08 18:14 UTC] jani@php.net
-Package: Feature/Change Request +Package: Scripting Engine problem
 [2016-01-16 13:47 UTC] danack@php.net
-Status: Open +Status: Verified
 [2016-01-16 13:47 UTC] danack@php.net
The TL:DR version: the programmer wants the code to output "/a{2,5}b/", but this cannot be achieved with the current syntax.

$minCount = 2;
$maxCount = 5;

echo "/a\{$minCount,$maxCount}b/";
// output is /a\{2,5}b/

echo "/a{$minCount,$maxCount}b/";
//PHP Parse error:  syntax error, unexpected ',', expecting '}
 [2020-12-14 12:34 UTC] cmb@php.net
-Status: Verified +Status: Suspended
 [2020-12-14 12:34 UTC] cmb@php.net
I fail to see why it would be hard to think of

    echo "/a{{$minCount},{$maxCount}}b/";

Anyhow, changing this now long-standing behavior would be a BC
break, and as such needs to be discussed on the internals mailing
list.  If you, or anybody else, is still interested in this,
please forward the request to that mailing list.  For the time
being, I'm suspending this ticket.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Oct 31 23:01:28 2024 UTC