#47577 [NEW]: { should be an escapable special - when paired with a trailing $

From: Date: Thu, 05 Mar 2009 18:38:53 +0000
Subject: #47577 [NEW]: { should be an escapable special - when paired with a trailing $
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-134441@lists.php.net to get a copy of this message
From: bob at trivectus dot com Operating system: Mac OS X PHP version: 5.2.9 PHP Bug Type: Strings related Bug description: { should be an escapable special - when paired with a trailing $ 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. -- Edit bug report at http://bugs.php.net/?id=47577&edit=1 -- Try a CVS snapshot (PHP 5.2): http://bugs.php.net/fix.php?id=47577&r=trysnapshot52 Try a CVS snapshot (PHP 5.3): http://bugs.php.net/fix.php?id=47577&r=trysnapshot53 Try a CVS snapshot (PHP 6.0): http://bugs.php.net/fix.php?id=47577&r=trysnapshot60 Fixed in CVS: http://bugs.php.net/fix.php?id=47577&r=fixedcvs Fixed in CVS and need be documented: http://bugs.php.net/fix.php?id=47577&r=needdocs Fixed in release: http://bugs.php.net/fix.php?id=47577&r=alreadyfixed Need backtrace: http://bugs.php.net/fix.php?id=47577&r=needtrace Need Reproduce Script: http://bugs.php.net/fix.php?id=47577&r=needscript Try newer version: http://bugs.php.net/fix.php?id=47577&r=oldversion Not developer issue: http://bugs.php.net/fix.php?id=47577&r=support Expected behavior: http://bugs.php.net/fix.php?id=47577&r=notwrong Not enough info: http://bugs.php.net/fix.php?id=47577&r=notenoughinfo Submitted twice: http://bugs.php.net/fix.php?id=47577&r=submittedtwice register_globals: http://bugs.php.net/fix.php?id=47577&r=globals PHP 4 support discontinued: http://bugs.php.net/fix.php?id=47577&r=php4 Daylight Savings: http://bugs.php.net/fix.php?id=47577&r=dst IIS Stability: http://bugs.php.net/fix.php?id=47577&r=isapi Install GNU Sed: http://bugs.php.net/fix.php?id=47577&r=gnused Floating point limitations: http://bugs.php.net/fix.php?id=47577&r=float No Zend Extensions: http://bugs.php.net/fix.php?id=47577&r=nozend MySQL Configuration Error: http://bugs.php.net/fix.php?id=47577&r=mysqlcfg

« previous php.bugs (#134441) next »