php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #23903 preg_replace incorrect output with *
Submitted: 2003-05-30 13:08 UTC Modified: 2003-06-06 08:10 UTC
From: mnilsson at bowesnet dot com Assigned:
Status: Not a bug Package: PCRE related
PHP Version: 4.3.2 OS: linux 2.4.18
Private report: No CVE-ID: None
 [2003-05-30 13:08 UTC] mnilsson at bowesnet dot com
PROBLEM: preg_replace does not return the proper value with 
a * in the regular expression.

INPUT: $_POST['bannerad_url'] = 'www.canoe.ca';

PROCESS CODE:
$_POST['bannerad_url'] = trim($_POST['bannerad_url']);

if (preg_match ("/^http:\/\/(.*)/i", 
$_POST['bannerad_url']) > 0)
	$bannerad_url = $_POST['bannerad_url'];
else
	$bannerad_url = preg_replace ("/(.*)/", "http://\$1", 
$_POST['bannerad_url']);

OUTPUT: echo $bannerad_url; -------> http://
www.canoe.cahttp://


FIX:
INPUT: $_POST['bannerad_url'] = 'www.canoe.ca';

PROCESS CODE:
$_POST['bannerad_url'] = trim($_POST['bannerad_url']);

if (preg_match ("/^http:\/\/(.+)/i", 
$_POST['bannerad_url']) > 0)
	$bannerad_url = $_POST['bannerad_url'];
else
	$bannerad_url = preg_replace ("/(.+)/", "http://\$1", 
$_POST['bannerad_url']);

OUTPUT: echo $bannerad_url; -------> http://www.canoe.ca

NOTES:
I was able to reproduce this several times. It seems to be 
related to the *, but replacing it with a + solves the 
problem. Thanks.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2003-05-30 15:12 UTC] elmicha@php.net
Smaller example:

  echo preg_replace ("/(.*)/", "http://\$1", "abc"),"\n";

Output: http://abchttp://

This doesn't look correct to me.

However, your search pattern doesn't look very reasonable - the normal way to prepend a string to another string is the "." operator:

  $bannerad_url = 'http://' . $_POST['bannerad_url'];


 [2003-06-06 03:05 UTC] sniper@php.net
Andrei, is this documentation issue or real bug? :)

 [2003-06-06 08:10 UTC] sniper@php.net
"That's just how it works. It matches the whole string on the 
first try and then tries again after the 'c'. Perl works the 
same way. A better way would be to use (.+) actually." --Andrei

So not any bug..

 [2003-06-06 20:27 UTC] stuge-phpbugs at cdy dot org
Compare #23946, which is a dupe.

$ echo xyz|perl -e 'while(<STDIN>)
{ $_=~ s/(.*)/http:\/\/\1/;print}'
http://xyz

Unfortunately, this shows Andrei's comment to be incorrect. I believe the error in both preg_replace() and ereg_replace() is that the regex gets checked one extra time after the entire string has been processed already, all regexes that match an empty string will hence replace one extra time at the end.

I believe an empty string should only be allowed to match at the very first iteration at the core of [ep]reg_replace().

See #23946 for some more discussion, examples and a suggested (and untested :) patch for ereg_replace().
 
PHP Copyright © 2001-2022 The PHP Group
All rights reserved.
Last updated: Fri Jan 28 00:03:34 2022 UTC