如何在PHP中找到eval'd函数的源代码?

时间:2008-12-03 15:53:15

标签: php function reflection

我正在尝试找到一种方法来获取字符串中(用户定义的)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 个答案:

答案 0 :(得分:1)

我最初的回答是说在eval中创建函数几乎没有理由。

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

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   baz(); 
12 }
13 
14 
15 
16 try{ 
17   foo(); 
18 }catch( Exception $e ){
19   var_dump($e); 
20 }
21 try{ 
22   foo(); 
23 }
24 catch( Exception $e ){
25   var_dump($e);
26 }

发出这个:



object(Exception)#1 (6) {
  ["message:protected"]=>
  string(0) ""
  ["string:private"]=>
  string(0) ""
  ["code:protected"]=>
  int(0)
  ["file:protected"]=>
  string(50) "/tmp/xx.php(10) : eval()'d code(4) : eval()'d code"
  ["line:protected"]=>
  int(1)
  ["trace:private"]=>
  array(3) {
    [0]=>
    array(3) {
      ["file"]=>
      string(31) "/tmp/xx.php(10) : eval()'d code"
      ["line"]=>
      int(4)
      ["function"]=>
      string(4) "eval"
    }
    [1]=>
    array(4) {
      ["file"]=>
      string(11) "/tmp/xx.php"
      ["line"]=>
      int(11)
      ["function"]=>
      string(3) "baz"
      ["args"]=>
      array(0) {
      }
    }
    [2]=>
    array(4) {
      ["file"]=>
      string(11) "/tmp/xx.php"
      ["line"]=>
      int(17)
      ["function"]=>
      string(3) "foo"
      ["args"]=>
      array(0) {
      }
    }
  }
}

Fatal error: Cannot redeclare baz() (previously declared in /tmp/xx.php(10) : eval()'d code:2) in /tmp/xx.php(10) : eval()'d code on line 5

Call Stack:
    0.0002     115672   1. {main}() /tmp/xx.php:0
    0.0006     122304   2. foo() /tmp/xx.php:22

这么多的不好,很少的努力。

答案 1 :(得分:1)

你不能自己搜索文件? grep或wingrep是完美的。

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

答案 2 :(得分:1)

如何定义自己的eval-function,并在那里进行跟踪?

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

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

答案 3 :(得分:0)

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

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

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