什么时候(如果有的话)是eval而不是邪恶?

Ken*_*ins 26 php eval

我听说很多 地方 PHP的eval功能往往不是答案.鉴于PHP 5.3的LSB闭包,我们已经没有理由依赖evalcreate_function.

是否有任何可以想象的案例,哪些eval是PHP 5.3中最好(唯一?)的答案?

这个问题不是关于eval一般是否是邪恶,因为它显然不是.

答案摘要:

  • 评估数值表达式(或PHP的其他"安全"子集)
  • 单元测试
  • 交互式PHP"shell"
  • 可信赖的反序列化 var_export
  • 一些模板语言
  • 为管理员和/或黑客创建后门
  • 与<PHP 5.3的兼容性
  • 检查语法(可能不安全)

tyl*_*erl 18

如果您正在编写恶意软件,并且您希望为那些试图在您之后进行清理的系统管理员努力工作.这似乎是我经验中最常见的用例.

  • Eval不是它的一半 - http://stackoverflow.com/questions/3115559/ (7认同)

Rus*_*ias 17

Eric Lippert总结了三篇博文.这是一个非常有趣的阅读.

据我所知,以下是使用eval的一些唯一原因.

例如,当您根据用户输入构建复杂的数学表达式时,或者将对象状态序列化为字符串以便可以存储或传输它,并在以后重构时.

  • 我不确定我是否同意实施数学表达引擎是过度的.如果你努力确保它有效,那么评估它不应该花费太多精力. (6认同)
  • 评估数学表达式(在检查语法正确性并确保不是恶意之后)可能确实是"eval"的有效用法之一.自己实施它会有点矫枉过正.但是对于序列化对象,你应该使用PHP的`serialize`函数,这是a)更快b)更安全和c)更完整(循环引用,...) (2认同)
  • 去除输入的牙齿是不是和仅仅编写一个表达式求值器一样困难(而且更危险)? (2认同)

Gor*_*don 8

主要问题eval是它是恶意代码的网关.因此,您永远不应该在可以从外部利用它的上下文中使用它,例如用户提供的输入.

一个有效的UseCase将在Mocking Frameworks中.

例子来自 PHPUnit_Framework_TestCase::getMock()

// ... some code before

    $mock = PHPUnit_Framework_MockObject_Generator::generate(
      $originalClassName,
      $methods,
      $mockClassName,
      $callOriginalClone,
      $callAutoload
    );

    if (!class_exists($mock['mockClassName'], FALSE)) {
        eval($mock['code']);
    }

// ... some code after
Run Code Online (Sandbox Code Playgroud)

实际上,generate方法中发生了很多事情.在外行术语中:PHPUnit将接受参数generate并从中创建一个类模板.然后eval,该类模板将使其可用于实例化.这一点的关键是让TestDoubles在UnitTests中模拟依赖关系.


ts.*_*ts. 5

您可以使用eval创建临时类:

function myAutoLoad($sClassName){

   # classic part
   if (file_exists($sClassName.'.php'){

      require $sClassName.'.php';

    } else {

      eval("
            class $sClassName{
                public function __call($sMethod,$aArgs){
                     return 'No such class: ' . $sClassName;
                 }
                }");

    }

} 
Run Code Online (Sandbox Code Playgroud)

虽然,当然,使用非常有限(一些API或者可能是DI容器,测试框架,ORM必须处理具有动态结构的数据库,代码游乐场)

  • 抛出异常并使用`try` /`catch`块来处理逻辑不是更好吗? (5认同)