From 47e85c9de4c4c3a58ad1d5143596062ade1cb3b6 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Wed, 4 Feb 2026 15:46:17 +0800 Subject: [PATCH] =?UTF-8?q?refactor(Php):=20=E7=A7=BB=E9=99=A4=20strlen=20?= =?UTF-8?q?=E7=AD=89=E5=87=BD=E6=95=B0=E7=9A=84=E7=89=B9=E6=AE=8A=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 从 FuncCallOptimizer 中移除了对 strlen、sizeof、count 函数的特殊转换逻辑 - 在 MagicMethodDetector 中为 __call 方法添加了参数类型验证 - 为 __toString、__serialize、__unserialize 等魔术方法添加了返回值和参数类型验证 - 为 __isset、__unset、__set_state、__debugInfo 等魔术方法添加了类型检查规则 - 添加了字符串类型参数验证以确保魔术方法符合 PHP 规范 - 添加了数组类型返回值验证以确保序列化相关方法正确实现 --- src/Php/FuncCallOptimizer.php | 3 --- src/Php/MagicMethodDetector.php | 33 +++++++++++++++++++++++++++++++++ tests/aot/to-str.phpt | 13 +++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 tests/aot/to-str.phpt diff --git a/src/Php/FuncCallOptimizer.php b/src/Php/FuncCallOptimizer.php index ac16f2b6..146acbb9 100644 --- a/src/Php/FuncCallOptimizer.php +++ b/src/Php/FuncCallOptimizer.php @@ -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': diff --git a/src/Php/MagicMethodDetector.php b/src/Php/MagicMethodDetector.php index e8cd4a19..88d3d322 100644 --- a/src/Php/MagicMethodDetector.php +++ b/src/Php/MagicMethodDetector.php @@ -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"); + } } } } diff --git a/tests/aot/to-str.phpt b/tests/aot/to-str.phpt new file mode 100644 index 00000000..53cac6a4 --- /dev/null +++ b/tests/aot/to-str.phpt @@ -0,0 +1,13 @@ +--TEST-- +any +--FILE-- + +--EXPECT-- +int(8) +string(8) "87654321" +int(18)