php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #8339 new preg_replace back reference handling not working
Submitted: 2000-12-20 11:58 UTC Modified: 2001-01-18 09:47 UTC
From: padraic at renaghan dot com Assigned:
Status: Closed Package: PCRE related
PHP Version: 4.0.4 OS: RedHat Linux 7
Private report: No CVE-ID: None
 [2000-12-20 11:58 UTC] padraic at renaghan dot com
phpinfo() reports:
  PHP Version 4.0.4
  './configure' '--with-mysql' '--with-apxs=/usr/local/apache/bin/apxs' 
  '--enable-rule=EAPI' '--with-imap' '--with-curl=/usr' 
  '--with-config-file-path=/etc' '--enable-track-vars=yes' 
  '--disable-debug'
  
I'm suddenly having problems with my PHPLIB template based application.
The problem seems to be due to the new 4.0.4 back reference handling in
preg_replace.

Test code:
  error_reporting(E_ALL);
  print(preg_replace("/{FOO}/","$7.50","Amount is {FOO}"));

Under PHP 4.0.2 the result is:
  Amount is $7.50

Under PHP 4.0.4 the result is:
  Amount is .50

No errors or warnings reported in either case.

I reviewed the Changelog for 4.0.4 and found:
  Modified preg_replace() to accept Perl-style $n backreferences 
  in addition to \\n ones. (Andrei) 
  Modified preg_replace() to ignore backreferences that refer 
  to non-existing subpatterns. (Andrei)

The second Changelog entry seems to disagree with a statement in the
PCRE Pattern Syntax Manual section which states:
  However, if the decimal number following  the  backslash  is
  less  than  10,  it is always taken as a back reference, and
  causes an error only if there are not  that  many  capturing
  left  parentheses in the entire pattern. In other words, the
  parentheses that are referenced need not be to the  left  of
  the  reference  for  numbers  less  than 10. See the section
  entitled "Backslash" above for further details of  the  han-
  dling of digits following a backslash.
  
The manual seems to say that back references without corresponding
sub-patterns should generate an error/warning while the Changelog
seems to say that a back reference without a corresponding
sub-pattern is ignored.

The behavior of 4.0.4 (using my example code) seems to be that
the a back reference without a corresponding sub-pattern is
not ignored but treated as a back reference without reporting
an error warning. Note that change the replacement to "$17.50"
which makes the back reference greater than 10 still results
in a result of "Amount is .50".

The above indicates to me that there is either a problem
in the 4.0.4 code or the text of the manual.

I attempted to workaround this in 4.0.4 with the following code:
  error_reporting(E_ALL);
  print(preg_replace("/{FOO}/","\$7.50","Amount is {FOO}"));

Reading the PCRE Syntax Manual section made me think that I
could escape the "$" with a "\". That didn't work. The result
of the above code in 4.0.4 is:
  Amount is .50
  
Adding a space between the "$" and the "7" does stop the back
reference issue, but leaves me with a space in my output
which I really don't want.

Am I missing something here or have I found a problem.

Thanks for your help.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2001-01-17 22:54 UTC] padraic at renaghan dot com
Thoughts?
It has been a month since I submitted this.
Is it a real problem?
Did I do something incorrect?

Thanks.

 [2001-01-18 09:47 UTC] andrei@php.net
The backreferences used in the replacement string are not handled by the underlying PCRE library, so the semantics can be different. Basically, if you want to keep $ in front of numbers in the replacement string escape it with \\ (use latest CVS).
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 26 13:01:28 2024 UTC