php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79044 Curly Braces Throw T_LNUMBER Error
Submitted: 2019-12-29 15:52 UTC Modified: 2019-12-29 23:42 UTC
From: thebluewalrus at gmail dot com Assigned:
Status: Not a bug Package: *General Issues
PHP Version: 7.4.1 OS: Mac OSX 10.12.4
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please !
Your email address:
MUST BE VALID
Solve the problem:
3 + 28 = ?
Subscribe to this entry?

 
 [2019-12-29 15:52 UTC] thebluewalrus at gmail dot com
Description:
------------
Using curly braces and a backreference in double quotes in regex replacement produces a 'T_LNUMBER' error for an invalid variable name. This behavior is inconsistent with other behavior though, e.g. uncurled the "variable" doesn't throw parser error.

Test script:
---------------
Correct behavior:

preg_replace('/(a)/', "$1test", 'a');

Incorrect behavior:

preg_replace('/(a)/', "{$1}test", 'a');

Expected result:
----------------
In regex context this behaviors is incorrect because '{$3}' should produce '{capture group three value}', as it does outside the curly braces.

Actual result:
--------------
Parse error: syntax error, unexpected '1' (T_LNUMBER), expecting variable (T_VARIABLE) or '{' or '$'

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-12-29 16:23 UTC] bugreports at gmail dot com
you can't have variables starting with a number in PHP

-----------------------

Correct behavior:
preg_replace('/(a)/', "$1test", 'a');

i would say this is not correct behavior and should trhow the same error becasue you can't have a variable $1test nor can you have $1

-----------------------

php > $1test = 'test';

Parse error: syntax error, unexpected '1' (T_LNUMBER), expecting variable (T_VARIABLE) or '{' or '$' in php shell code on line 1
 [2019-12-29 21:21 UTC] thebluewalrus at gmail dot com
Yes, I agree I would expect '"$1"' and '"{$1}"' to behave the same but they don't. I think one or the other is functioning incorrectly. Simplifying the "correct" example it still executes:

preg_replace('/(a)/', "$1", 'a');
 [2019-12-29 22:44 UTC] requinix@php.net
-Status: Open +Status: Not a bug -Type: Feature/Change Request +Type: Bug -Package: Compile Failure +Package: *General Issues
 [2019-12-29 22:44 UTC] requinix@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

https://www.php.net/manual/en/language.types.string.php#language.types.string.parsing

When PHP reads the simple syntax it sees the '$' and takes
> as many tokens as possible to form a valid variable name

No tokens means no variable and PHP ignores it.

Complex syntax works differently as it
> allows for the use of complex expressions

With complex syntax PHP sees '{$' and everything up to the closing '}' is used. In other words, PHP looks for a valid expression - the kind you use in your regular code, but with the obvious limitation that it has to start with a dollar sign.

"$1" is not a valid expression, and PHP raises the same syntax error that it would as if you wrote that outside of a string.
 [2019-12-29 23:10 UTC] bugreports at gmail dot com
irrelevant, the second one should throw the same error than the first and that can even throw at compile time

php > echo $1test;
Parse error: syntax error, unexpected '1' (T_LNUMBER), expecting variable (T_VARIABLE) or '{' or '$' in php shell code on line 1

php > echo "$1test";
$1test
 [2019-12-29 23:42 UTC] requinix@php.net
> irrelevant
By all means, please invent a time machine and go back a couple decades to tell the people developing PHP that they should have done this differently. That way people in the other timeline won't have to deal with such utterly ridiculous behavior. I know that for me, personally, if I were to fork PHP, prohibiting writing "$1" is at the top of my list of things to change.

Meanwhile for those of us in this timeline, that's how it is. Unless, of course, you have a compelling reason why PHP should suddenly break functionality that has been allowed since basically forever?
If you actually do despite my sarcasm, go ahead and start working on an RFC for it. I'm sure everyone will love it.
 [2019-12-30 00:04 UTC] bugreports at gmail dot com
> Unless, of course, you have a compelling reason why 
> PHP should suddenly break functionality that has 
> been allowed since basically forever?

well, nobody right in his mind would write "$1test" instead "\$1test" and call that simply *udenfeined* hehavior given that yiu are supposed to escape $ within double quotes and undefined behavior by it's definition can change at whatever point in time
 [2020-01-01 16:53 UTC] thebluewalrus at gmail dot com
So the 'complex syntax' is not as advanced as the regular variable processor but the behavior of the 'complex syntax' will not be corrected because that is how it has been for ages?

It would seem to me that

\{\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\}

would be better than

\{\$[^}]+?\}

which is what I presume the regular variable processor uses. If it's not a variable it shouldn't process it. I can't see how this would break past functionality, Previously the complex failed in instance where it shouldn't have.
 [2020-01-01 21:05 UTC] a at b dot c dot de
Wouldn't that mean munging the input to PCRE, because it's the library specifying the use of "$1" to refer to pattern replacements? (And you can blame Perl for that.) Don't forget to also handle its use of {} to disambiguate between ${1}0 and $10.

Just one MORE reason to prefer single quotes when writing string literals in those function calls.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 14:01:29 2024 UTC