0

我正在尝试找到一种方法来获取字符串中(用户定义的)PHP 函数的源代码。

对于普通代码,这很容易,使用反射我可以找到定义函数的文件和行号;然后我可以打开文件并阅读函数源代码。

如果在 eval'd 代码中定义了函数,这将不起作用。我不想记录所有经过评估的代码。

这可能吗?如果是,那么如何?

示例代码:

function myfunction() {
    echo "Test";
}
eval('
  function myevalfunction() {
    echo "Test";
  }
');

$a = new ReflectionFunction('myfunction');
echo $a;

$b = new ReflectionFunction('myevalfunction');
echo $b;

输出:

Function [ <user> <visibility error> function myfunction ] {
  @@ test.php 3 - 5
}
Function [ <user> <visibility error> function myevalfunction ] {
  @@ test.php(11) : eval()'d code 2 - 4
}
4

4 回答 4

1

我最初的反应是说在 eval 中创建一个函数几乎是 0 个很好的理由。

您可以有条件地创建函数,即:

if ( $cond ){ 
   function foo(){ 

   }
}

如果你想要像闭包一样的行为,我猜 eval 是 PHP5.3 之前的唯一方法,但它的EPIC坏东西,你应该避免所有成本。

原因如下:


01 <?php
 02  
03 function foo ()
 04 {
 05    eval(
 '06      function baz()
 07      {
 08         eval("throw new Exception();"); 
 09      }
 10    '); 
11   巴兹(); 
12 }
 13  
14  
15  
16尝试{ 
 17    foo(); 
18 }catch( 异常 $e ){
 19    var_dump($e); 
20 }
 21尝试{ 
 22    foo(); 
23 }
 24捕获(异常 $e){
 25    var_dump($e);
26 }

哪个发出这个:



对象(异常)#1 (6) {
  [“消息:受保护”]=>
  字符串(0)“”
  [“字符串:私有”]=>
  字符串(0)“”
  [“代码:受保护”]=>
  整数(0)
  [“文件:受保护”]=>
  string(50) "/tmp/xx.php(10) : eval()'d code(4) : eval()'d code"
  [“线路:受保护”]=>
  整数(1)
  [“跟踪:私人”]=>
  数组(3){
    [0]=>
    数组(3){
      [“文件”]=>
      string(31) "/tmp/xx.php(10) : eval()'d 代码"
      [“行”]=>
      整数(4)
      [“功能”]=>
      字符串(4)“评估”
    }
    [1]=>
    数组(4){
      [“文件”]=>
      字符串(11)“/tmp/xx.php”
      [“行”]=>
      整数(11)
      [“功能”]=>
      字符串(3)“巴兹”
      [“参数”]=>
      数组(0){
      }
    }
    [2]=>
    数组(4){
      [“文件”]=>
      字符串(11)“/tmp/xx.php”
      [“行”]=>
      整数(17)
      [“功能”]=>
      字符串(3)“富”
      [“参数”]=>
      数组(0){
      }
    }
  }
}

致命错误:无法在 /tmp/xx.php(10) 中重新声明 baz()(之前在 /tmp/xx.php(10) 中声明:eval()'d code:2):eval()'d code on line 5

调用堆栈:
    0.0002 115672 1. {main}() /tmp/xx.php:0
    0.0006 122304 2. foo() /tmp/xx.php:22

这么多的坏事,这么少的努力。

于 2008-12-03T16:01:26.930 回答
1

您不能自己搜索文件吗?grep 或wingrep 非常适合这个。

如果没有,您可以尝试使用 pecl 函数 rename_function 并记录所有创建函数的 eval 调用。

于 2008-12-03T16:07:48.460 回答
1

您如何定义自己的评估函数并在那里进行跟踪?

function myeval($code) {
     my_eval_tracking($code, ...);  # use traceback to get more info if necessary
     # (...)
     return eval($code);
}

也就是说,在这种情况下,我确实分享了 Kent Fredric 对 eval 的很多感受。

于 2008-12-03T16:40:34.650 回答
0

如果你想找到源代码,即使在调试器中,你也可以定义你自己的 eval() 函数来处理临时文件:

function my_eval($code) {
  $file = << TEMP-DIR >> . '/' . md5($code) . '.php';
  if (!file_exists($file)) {
    file_put_contents($file, "<?php\n" . $code);
  }
  return require($file);
}

其实我觉得如果你调用这个函数eval并把它放在默认的命名空间里,代码中大部分的eval()调用都会改为调用这个函数。

于 2021-08-10T10:43:05.993 回答