note 73382 added to function.preg-replace

From: Date: Tue, 20 Feb 2007 22:19:22 +0000
Subject: note 73382 added to function.preg-replace
Groups: php.notes 
Request: Send a blank email to php-notes+get-123614@lists.php.net to get a copy of this message
preg_replace() is NOT binary-safe. If a match is made to an ASCII NULL character (0x00) or an ASCII double-quote character (0x22), the backreference will NOT return those characters! Instead, the backreference contains the 2-character backslash-escaped sequence \0 or \" respectively. This causes escaped data to be mixed with unescaped data in the resulting replacement string, destroying the data integrity. To use preg_replace() for binary data, you MUST use the "e" modifier in the regular expression, and then call a function on the backreference to unescape the data in these two special circumstances. Since it is only 0x00 and 0x22 that are escaped, you can NOT use stripslashes(). Instead, write your own function, or use a pair of nested str_replace() function calls. Here's an example of a URL validator using preg_replace() made binary-safe: <?php function url_validate($uncertainURL){ return preg_replace('/([\\x00-\\x20"<>`\\x7F-\\xFF])/e', "'%'.sprintf('%02X',ord( str_replace('\\\\0',\"\\0\", str_replace('\\\\\"','\"','\\1') ) ))", $uncertainURL); } ?> Notice the following: -A match is made for all ASCII control characters, double-quote, the greater-than and less-than characters, the grave accent, ASCII DEL, and all 8-bit high characters. -When an ASCII NULL is matched, the outer str_replace() function call unescapes it. -When a double-quote is matched, the nested str_replace() function call unescapes it. -All other matched characters are returned in the back-reference as-is, and therefore do not need unescaping. -After unescaping the backreference (if necessary), the sprintf() and ord() functions are called to replace the instance of the matched character in the source string ($uncertainURL) with a URL-encoded character code. The sheer number of backslashes looks a little confusing, but remember, we're 2-levels deep in escaping context: Literal backslashes have to be doubled in the source code first to make them literals in the regular expression, and then those have to be doubled again if they are to be literals in the replacement PHP string expression. So every literal backslash has to be represented with 4 backslashes! ---- Server IP: 66.207.199.35 Probable Submitter: 64.7.136.101 ---- Manual Page -- http://www.php.net/manual/en/function.preg-replace.php Edit -- https://master.php.net/note/edit/73382 Del: integrated -- https://master.php.net/note/delete/73382/integrated Del: useless -- https://master.php.net/note/delete/73382/useless Del: bad code -- https://master.php.net/note/delete/73382/bad+code Del: spam -- https://master.php.net/note/delete/73382/spam Del: non-english -- https://master.php.net/note/delete/73382/non-english Del: in docs -- https://master.php.net/note/delete/73382/in+docs Del: other reasons-- https://master.php.net/note/delete/73382 Reject -- https://master.php.net/note/reject/73382 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#123614) next »