在HTML5模式输入元素属性上使用什么是安全的PCRE正则表达式分隔符?

问题描述 投票:12回答:6

似乎HTML5 spec (and therefore ECMA262)允许<input type="text" pattern="[0-9]/[0-9]" />匹配字符串'0/0',即使正斜杠没有被转义。像Drupal这样的Web应用程序希望为不支持HTML5的浏览器提供服务器端验证,例如:

<?php
preg_match('/^(' . $pattern . ')$/', $value);
?>

不幸的是,字符串'[0-9] / [0-9]'不是有效的PRCE正则表达式。似乎大多数(如果不是全部)支持HTML5的浏览器都支持pattern="[0-9]/[0-9]"pattern="[0-9]\/[0-9]",这引出了一个问题 - 我们可以使用什么作为分隔符来运行这种模式来对抗Perl风格的正则表达式?

我们已经提交了bug report against the W3C spec,但这里的浏览器是错误的吗?是否需要澄清HTML5规范?我们可以在PHP中使用解决方法吗?

php regex html5 pcre
6个回答
4
投票

如果你使用#而不是/作为分隔符,它是一个有效的正则表达式。例:

preg_match('#^('.$pattern.')$#', $value);

4
投票

我建议使用"\xFF"字节作为模式分隔符,因为它不允许在UTF-8字符串中,所以我们可以确定它不会出现在模式中。因为preg_match不理解UTF-8,所以不会造成麻烦。

示例:preg_match("\xFF$pattern\$\xFFADmsu", $subject);

请注意ADmsu修饰符和添加$u修饰符仅在模式中需要有效的UTF-8字节,但在周围的分隔符中不需要。


3
投票

PCRE的一个问题是几乎任何分隔符对于开始和结束标记都是合法的,这取决于使剩余的转义更容易的原因。所以#foo#是合法的,/ foo /是合法的,!foo!是合法的(我认为)等等,我会说,无论如何,正确的理由是非常危险的。这听起来像是一个没有指定的HTML5规范bug。

也许在PHP中,扫描字符串并从字符串中不存在的白名单中选择一个分隔符? (例如,如果没有/使用它,如果有使用#,如果那里使用%,等等)


2
投票

我认为chr(0)会工作得很好。编辑:没有。但chr(1)确实有效。


0
投票

鉴于PHP应用程序(在这种情况下是Drupal)正在生成输入字段,似乎解决方法是执行以下操作:

$pattern = '[0-9]/[0-9]';
...
$cleanPattern = preg_replace('/\//', '\\/', $pattern);
preg_match('/' . $cleanPattern . '/', $subject, $matches);

我想不出一个不起作用的情况,/被用作表达式中的文字。

HTML5规范遵循ECMA262的法律模式规范:

如果指定,则属性的值必须与JavaScript Pattern生成匹配。 [ECMA262]

由于ECMA262中定义了BNF,因此完全解析器(而不是使用PCRE)似乎是最安全的方法。


0
投票

只需将其括在括号或括号中(是的,这很奇怪!):

<?php
preg_match('(^' . $pattern . '$)', $value);
?>

手册指出您可以使用所有相应的对:http://php.net/manual/en/regexp.reference.delimiters.php

一开始并不容易,但它清楚地处理了你可能在其间使用的任何角色。例如,'(^(foo|bar)$)'作为最终的正则表达式:^(foo|bar)$,没有任何潜在的危险逃脱。

© www.soinside.com 2019 - 2024. All rights reserved.