我从外部源获取的字符串如下:
array(1,2,3)
但也包括更大的数组,例如
array("a", "b", "c", array("1", "2", array("A", "B")), array("3", "4"), "d")
我希望在php中它们能够成为一个真正的数组。我知道我可以使用eval,但由于它们来自不受信任的来源,我宁愿不这样做。我也无法控制外部来源。
我应该使用一些正则表达式吗(如果是,是什么),还是有其他方法?
我从外部源获取的字符串如下:
array(1,2,3)
但也包括更大的数组,例如
array("a", "b", "c", array("1", "2", array("A", "B")), array("3", "4"), "d")
我希望在php中它们能够成为一个真正的数组。我知道我可以使用eval,但由于它们来自不受信任的来源,我宁愿不这样做。我也无法控制外部来源。
我应该使用一些正则表达式吗(如果是,是什么),还是有其他方法?
在使用 Tokenizer 编写解析器时,我发现这并不像我预想的那么容易,于是我又想到了另一个方法:为什么不使用 eval
解析数组,但首先验证其是否包含有害内容?
所以,代码的作用是:检查数组的标记,确保其只包含一些允许的标记和字符,然后执行 eval。我希望已经包含了所有可能无害的标记,如果没有,请添加它们。(我故意没有包括 HEREDOC 和 NOWDOC,因为我认为它们不太可能被使用。)
function parseArray($code) {
$allowedTokens = array(
T_ARRAY => true,
T_CONSTANT_ENCAPSED_STRING => true,
T_LNUMBER => true,
T_DNUMBER => true,
T_DOUBLE_ARROW => true,
T_WHITESPACE => true,
);
$allowedChars = array(
'(' => true,
')' => true,
',' => true,
);
$tokens = token_get_all('<?php '.$code);
array_shift($tokens); // remove opening php tag
foreach ($tokens as $token) {
// char token
if (is_string($token)) {
if (!isset($allowedChars[$token])) {
throw new Exception('Disallowed token \''.$token.'\' encountered.');
}
continue;
}
// array token
// true, false and null are okay, too
if ($token[0] == T_STRING && ($token[1] == 'true' || $token[1] == 'false' || $token[1] == 'null')) {
continue;
}
if (!isset($allowedTokens[$token[0]])) {
throw new Exception('Disallowed token \''.token_name($token[0]).'\' encountered.');
}
}
// fetch error messages
ob_start();
if (false === eval('$returnArray = '.$code.';')) {
throw new Exception('Array couldn\'t be eval()\'d: '.ob_get_clean());
}
else {
ob_end_clean();
return $returnArray;
}
}
var_dump(parseArray('array("a", "b", "c", array("1", "2", array("A", "B")), array("3", "4"), "d")'));
我认为这是安全与便利之间的一个很好的折衷方案-无需自己解析。
例如:
parseArray('exec("haha -i -thought -i -was -smart")');
将会抛出异常:
Disallowed token 'T_STRING' encountered.
json_decode(str_replace(array('array(', ')'), array('[', ']'), $string)));
json_decode
。如果字符串只是一个具有标量值的多维数组,则进行str_replace
不会破坏任何内容,并且您可以将其json_decode
。如果它包含任何代码,它也将替换函数括号,然后Json将无效并返回NULL
。