refactor(Php): 移除 strlen 等函数的特殊优化处理

- 从 FuncCallOptimizer 中移除了对 strlen、sizeof、count 函数的特殊转换逻辑
- 在 MagicMethodDetector 中为 __call 方法添加了参数类型验证
- 为 __toString、__serialize、__unserialize 等魔术方法添加了返回值和参数类型验证
- 为 __isset、__unset、__set_state、__debugInfo 等魔术方法添加了类型检查规则
- 添加了字符串类型参数验证以确保魔术方法符合 PHP 规范
- 添加了数组类型返回值验证以确保序列化相关方法正确实现
pull/1/head
韩天峰 7 months ago
parent 1d6e7522ab
commit 47e85c9de4
  1. 3
      src/Php/FuncCallOptimizer.php
  2. 33
      src/Php/MagicMethodDetector.php
  3. 13
      tests/aot/to-str.phpt

@ -17,9 +17,6 @@ trait FuncCallOptimizer
$getArg = function ($i) use ($expr) {
return $this->parseIdentifier($expr->args[$i]->value);
};
if ($name === 'strlen' or $name === 'sizeof' or $name === 'count') {
return 'php::len(' . $getArg(0) . ')';
}
if (count($expr->args) == 1) {
switch ($name) {
case 'intval':

@ -19,10 +19,43 @@ trait MagicMethodDetector
if (count($methodDef->functionDef->argInfoList) != 2) {
$this->fatalError($v, 'Method ' . $this->class . "::{$name}() must take exactly 2 arguments");
}
if (!$methodDef->functionDef->argInfoList[0]->type or $methodDef->functionDef->argInfoList[0]->type != 'string') {
$this->fatalError($v, 'Method ' . $this->class . "::{$name}() must take string as argument");
}
} elseif ($name == '__get') {
if (count($methodDef->functionDef->argInfoList) != 1) {
$this->fatalError($v, 'Method ' . $this->class . "::{$name}() must take exactly 1 argument");
}
} elseif ($name == '__toString') {
if (!$methodDef->functionDef->returnType or $methodDef->functionDef->returnType != 'string') {
$this->fatalError($v, 'Method ' . $this->class . "::{$name}() must return string");
}
} elseif ($name == '__serialize') {
if (!$methodDef->functionDef->returnType or $methodDef->functionDef->returnType != 'array') {
$this->fatalError($v, 'Method ' . $this->class . "::{$name}() must return array");
}
} elseif ($name == '__unserialize') {
if (count($methodDef->functionDef->argInfoList) != 1) {
$this->fatalError($v, 'Method ' . $this->class . "::{$name}() must take exactly 1 argument");
} elseif (!$methodDef->functionDef->argInfoList[0]->type or $methodDef->functionDef->argInfoList[0]->type != 'array') {
$this->fatalError($v, 'Method ' . $this->class . "::{$name}() must take array as argument");
}
} elseif ($name == '__isset' or $name == '__unset' or $name == '__set_state') {
if (count($methodDef->functionDef->argInfoList) != 1) {
$this->fatalError($v, 'Method ' . $this->class . "::{$name}() must take exactly 1 argument");
}
if (!$methodDef->functionDef->argInfoList[0]->type or $methodDef->functionDef->argInfoList[0]->type != 'string') {
$this->fatalError($v, 'Method ' . $this->class . "::{$name}() must take string as argument");
}
if ($name == '__set_state') {
if (!$methodDef->functionDef->returnType or $methodDef->functionDef->returnType != 'array') {
$this->fatalError($v, 'Method ' . $this->class . "::{$name}() must return array");
}
}
} elseif ($name == '__debugInfo') {
if (!$methodDef->functionDef->returnType or $methodDef->functionDef->returnType != 'array') {
$this->fatalError($v, 'Method ' . $this->class . "::{$name}() must return array");
}
}
}
}

@ -0,0 +1,13 @@
--TEST--
any
--FILE--
<?php
$s = 12345678;
var_dump(strlen($s));
var_dump(strrev($s));
var_dump(strlen(3.1415926));
?>
--EXPECT--
int(8)
string(8) "87654321"
int(18)
Loading…
Cancel
Save