ID: 30698 User updated by: php at richardneill dot org Reported By: php at richardneill dot org Status: Bogus Bug Type: Documentation problem Operating System: Linux PHP Version: 4.3.9 New Comment:
Sorry - I'm not thinking clearly today - need more coffee! Anyway, the parts (ii) in my previous comment are complete nonsense, but the parts (i) are true. I still think that the documentation is wrong: it reads: "Single AND double quotes are escaped by backslashes in substituted backreferences" whereas it should read: "In single-quoted backreferences, single-quotes are escaped by backslashes; double quotes are not escaped". The reverse applies for double-quoted backreferences. ------------------ I also think that some sort of warning is important here (even if it's just a link to another page). This is necessary because a double escaped quote becomes an SQL injection issue. Eg: User writes: Here's a test. After magic quoting: Here\'s a test. After preg_replace using ("\\1") Here\\'s a test SQL: $sql="UPDATE table SET value='$input'"; Database query is: UPDATE table SET value='Here\\'s a test' which is parsed as literal \ followed by unescaped ' Which will fail. Thus the user thinks that they are always safe because of magic-quotes, but in fact they are NOT. Previous Comments: ------------------------------------------------------------------------ [2005-04-05 16:59:43] [EMAIL PROTECTED] Unescaped quotes doesn't cause parse error thanks to escaping provided by /e. <?php echo preg_replace('~.*~e', '"\\0"', '"'); // ", no parse error ?> I'm against messing this part with magic_qutes and SQL injection issues. ------------------------------------------------------------------------ [2005-04-05 16:47:43] php at richardneill dot org I don't think this is exactly bogus, since I think the documentation is not clear. The documentation for /e says just: -------------------- If this modifier is set, preg_replace() does normal substitution of backreferences in the replacement string, evaluates it as PHP code, and uses the result for replacing the search string. Single and double quotes are escaped by backslashes in substituted backreferences. ---------------------- Given that this is a really awkward potential gotcha, especially when it interacts with PHP's magic quotes and SQL, I think it is worth stressing that: a)If the backreference is single quoted, eg: ('\\1') then i)Double quotes will become escaped by \ ii)Unescaped single quotes will cause a parse error. b)If the backreference is double quoted, eg: ("\\1") then i)single quotes will become escaped by \ ii)Unescaped double quotes will cause a parse error. c)If the source is user-input which has had magic-quotes applied, then quotes of type (i) will end up doubly escaped causing an SQL error, and one of the escapes must be removed quotes of type (ii) will lose their magic quoting, and need to have the escape restored. ------------------------------------------------------------------------ [2005-04-05 15:46:35] [EMAIL PROTECTED] It works as expected and documented: modify('\\1') is translated to modify('single quote \', a double quote \", and a backslash\\') resulting in single quote ', a double quote \", and a backslash\ --- modify("\\1") is translated to modify("single quote \', a double quote \", and a backslash\\") resulting in single quote \', a double quote ", and a backslash\ ------------------------------------------------------------------------ [2004-11-11 01:44:09] php at richardneill dot org I hope this test case is more useful. <? $message="This string contains a single quote ', a double quote \", and a backslash\ ."; function modify($string){ return "START $string END"; } $new_bad=preg_replace("/^(.*)$/e", "'BEGINNING '.modify('\\1').' FINISH'", $message); $new_good=preg_replace("/^(.*)$/e", "'BEGINNING '.modify(\"\\1\").' FINISH'", $message); echo "MESSAGE:\n$message\n\n"; echo "NEW_BAD:\n$new_bad\n\n"; echo "NEW_GOOD:\n$new_good\n\n"; echo "NB: none of these are the same!\n" /* The problem is that depending on precisely how the replacements in the preg_replace are quoted, the escaping is different. This is not documented. $new_bad and $new_good should be the same! Furthermore, in the case where $message is user-submitted, and has arrived via magic_quotes, ready for insertion into a database, modify() will want to include a strip_slashes, to remove the redundant slashes (but leaving the original ones). The above behaviour could leave a database vulnerable to sql injection attacks My personal favoured solution would be for the /e modifier not to add the extra backslashes. */ ?> ------------------------------------------------------------------------ [2004-11-10 18:24:12] [EMAIL PROTECTED] Thank you for this bug report. To properly diagnose the problem, we need a short but complete example script to be able to reproduce this bug ourselves. A proper reproducing script starts with <?php and ends with ?>, is max. 10-20 lines long and does not require any external resources such as databases, etc. If possible, make the script source available online and provide an URL to it here. Try avoid embedding huge scripts into the report. Btw, the example from docs works just fine for me. ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at http://bugs.php.net/30698 -- Edit this bug report at http://bugs.php.net/?id=30698&edit=1