昨天我们的xhgui出现报错Warning: preg_match(): Null byte in regex,于是,检查原因:是有pattern里面的null(0×0)字符引起的。
先看一个demo:
preg_match("/abcd".chr(0)."efg/", 'abc');
分析源码(源码位置:php/ext/pcre/php_pcre.c:325)
PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
{
......
p = ZSTR_VAL(regex);// p = '/abcd',c语言字符串以\0结尾,这个赋值就把\0后面的字符丢了
......
delimiter = *p++; // delimiter = "/"
......
start_delimiter = delimiter; // start_delimiter = "/"
if ((pp = strchr("([{< )]}> )]}>", delimiter)))
delimiter = pp[5];
end_delimiter = delimiter; // end_delimiter = "/"
pp = p; // pp = 'abcd'
if (start_delimiter == end_delimiter) {
/* We need to iterate through the pattern, searching for the ending delimiter,
but skipping the backslashed delimiters. If the ending delimiter is not
found, display a warning. */
while (*pp != 0) { // 这个while没找到结束标记,所以循环结束后pp指针移动到字符串末尾
if (*pp == '\' && pp[1] != 0) pp++;
else if (*pp == delimiter)
break;
pp++;
}
}
......
if (*pp == 0) {
if (pp < ZSTR_VAL(regex) + ZSTR_LEN(regex)) { // 判断末尾位置是不是原字符串的末尾位置,不是则报E_WARNING
php_error_docref(NULL,E_WARNING, "Null byte in regex");
}
......
}
{
......
p = ZSTR_VAL(regex);// p = '/abcd',c语言字符串以\0结尾,这个赋值就把\0后面的字符丢了
......
delimiter = *p++; // delimiter = "/"
......
start_delimiter = delimiter; // start_delimiter = "/"
if ((pp = strchr("([{< )]}> )]}>", delimiter)))
delimiter = pp[5];
end_delimiter = delimiter; // end_delimiter = "/"
pp = p; // pp = 'abcd'
if (start_delimiter == end_delimiter) {
/* We need to iterate through the pattern, searching for the ending delimiter,
but skipping the backslashed delimiters. If the ending delimiter is not
found, display a warning. */
while (*pp != 0) { // 这个while没找到结束标记,所以循环结束后pp指针移动到字符串末尾
if (*pp == '\' && pp[1] != 0) pp++;
else if (*pp == delimiter)
break;
pp++;
}
}
......
if (*pp == 0) {
if (pp < ZSTR_VAL(regex) + ZSTR_LEN(regex)) { // 判断末尾位置是不是原字符串的末尾位置,不是则报E_WARNING
php_error_docref(NULL,E_WARNING, "Null byte in regex");
}
......
}
从这段源码可以看出我们demo中输入的”/abcd”.chr(0).”efg/”字符串由于赋值操作,变成了”/abcd”,后面的chr(0).”efg/”在赋值操作中丢失。看起来是c语言本身的问题(c语言的字符串以\0结尾),而php没有处理这个问题。
延伸阅读,php的bug list中有一篇报告:点击查看
pattern中的\0(null)会导致安全问题,因为c语言的\0是字符串的结束符,在检测用户输入的字符串是遇到\0会认为用户输入结束,所以后面的字符就不会再检测,导致用户输入的字符串绕过匹配检测,产生这个安全问题。
转载请注明:小Y » php的Warning: preg_match(): Null byte in regex问题的分析