热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

什么时候(如果有的话)不邪恶?-When(ifever)isevalNOTevil?

IveheardmanyplacesthatPHPsevalfunctionisoftennottheanswer.InlightofPHP5.3sLSBa

I've heard many places that PHP's eval function is often not the answer. In light of PHP 5.3's LSB and closures we're running out of reasons to depend on eval or create_function.

我在很多地方听说PHP的eval函数通常不是答案。根据PHP 5.3的LSB和闭包,我们没有理由依赖eval或create_function。

Are there any conceivable cases where eval is the best (only?) answer in PHP 5.3?

有没有可能在PHP 5.3中,eval是最好的(唯一的)答案?

This question is not about whether eval is evil in general, as it obviously is not.

这个问题并不是关于eval是否总体上是邪恶的,因为它显然不是。

Summary of Answers:

总结的答案:

  • Evaluating numerical expressions (or other "safe" subsets of PHP)
  • 计算数值表达式(或PHP的其他“安全”子集)
  • Unit testing
  • 单元测试
  • Interactive PHP "shell"
  • 交互式PHP“壳”
  • Deserialization of trusted var_export
  • 反序列化的信任var_export
  • Some template languages
  • 一些模板语言
  • Creating backdoors for administers and/or hackers
  • 为管理和/或黑客创建后门。
  • Compatibility with
  • Checking syntax (possibly not safe)
  • 检查语法(可能不安全)

15 个解决方案

#1


17  

Eric Lippert sums eval up over three blog posts. It's a very interesting read.

Eric Lippert总结了三篇博文。这是一本非常有趣的书。

As far as I'm aware, the following are some of the only reasons eval is used.

就我所知,以下是使用eval的唯一原因。

For example, when you are building up complex mathematical expressions based on user input, or when you are serializing object state to a string so that it can be stored or transmitted, and reconstituted later.

例如,当您基于用户输入构建复杂的数学表达式时,或者当您将对象状态序列化为字符串时,以便将其存储或传输,并在稍后重新构建。

#2


17  

If you're writing malware and you want to make life hard for the sysadmin who's trying to clean up after you. That seems to be the most common usage case in my experience.

如果你在写恶意软件,你想让那些试图清理你的系统管理员日子不好过。在我的经验中,这似乎是最常见的用法。

#3


8  

The main problem with eval is it being a gateway for malicious code. Thus you should never use it in a context where it can be exploited from the outside, e.g. user provided input.

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

One valid UseCase would be in Mocking Frameworks.

一个有效的UseCase是在mock框架中。

Example from PHPUnit_Framework_TestCase::getMock()

从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

There is actually a lot of things happening in the generate method. In laymens terms: PHPUnit will take the arguments to generate and create a class template from it. It will then eval that class template to make it available for instantiation. The point of this is to have TestDoubles to mock dependencies in UnitTests of course.

实际上在生成方法中发生了很多事情。用分层的术语来说:PHPUnit将使用参数来生成并创建一个类模板。然后,它将对类模板进行eval,使其可用于实例化。这样做的目的是让testdouble在UnitTests中模拟依赖关系。

#4


5  

You can use eval to create ad-hoc classes:

您可以使用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;
                 }
                }");

    }

} 

Although, of course, usage is quite limited (some API's or maybe DI containers, testing frameworks, ORMs which have to deal with databases with dynamic structure, code playgrounds)

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

#5


3  

If you are writing a site that interprets and executes PHP code, like an interactive shell would.

如果您正在编写一个解释和执行PHP代码的站点,就像交互式shell那样。

...

I'm a systems guy, that's all I got.

我是个搞系统的人,这就是我的全部。

#6


3  

eval is a construct that can be used to check for syntax errors.

eval是一个可用于检查语法错误的构造。

Say you have these two PHP scripts:

假设您有这两个PHP脚本:

script1.php

script1.php

script2.php

script2.php

You can check for syntax errors using eval:

您可以使用eval检查语法错误:

$code1 = 'return true; ?>'.file_get_contents('script1.php');
$code2 = 'return true; ?>'.file_get_contents('script2.php');

echo eval($code1) ? 'script1 has valid syntax' : 'script1 has syntax errors';
echo eval($code2) ? 'script2 has valid syntax' : 'script2 has syntax errors';

Unlike php_check_syntax (which is deprecated and removed anyway), the code will not be executed.

不像php_check_syntax(它已经被弃用并删除),代码不会被执行。

EDIT:

编辑:

The other (preferred) alternative being php -l. You can use the solution above if you don't have access to system() or shell execution commands.

另一种选择是php -l。如果不能访问system()或shell执行命令,可以使用上面的解决方案。

This method can inject classes/functions in your code. Be sure to enforce a preg_replace call or a namespace before doing so, to prevent them from being executed in subsequent calls.

这个方法可以在代码中注入类/函数。确保在执行之前强制执行preg_replace调用或命名空间,以防止在后续调用中执行它们。

As for the OP topic: When (if ever) is eval NOT evil? eval is simply not evil. Programmers are evil for using eval for no reason. eval can shorten your code (mathematical expression evaluation, per example).

关于OP主题:什么时候(如果有的话)eval不是邪恶的?eval不是邪恶。程序员毫无理由地使用eval是邪恶的。eval可以缩短代码(每个示例的数学表达式求值)。

#7


2  

I've found that there are times when most features of a language are useful. After all, even GOTO has had its proponents. Eval is used in a number of frameworks and it is used well. For example, CodeIgniter uses eval to distinguish between class hierarchy of PHP 4 and PHP 5 implementations. Blog plugins which allow for execution of PHP code definitely need it (and that is a feature available in Expression Engine, Wordpress, and others). I've also used it for one website where a series of views are almost identical, but custom code was needed for each and creating some sort of insane rules engine was far more complicated and slower.

我发现有时候语言的大多数特性都是有用的。毕竟,即使是GOTO也有它的支持者。Eval在许多框架中使用,并且使用得很好。例如,CodeIgniter使用eval来区分PHP 4和PHP 5实现的类层次结构。允许执行PHP代码的博客插件肯定需要它(表达式引擎、Wordpress和其他软件都有这个功能)。我也曾在一个网站上使用它,那里的一系列视图几乎是相同的,但是每个都需要定制代码,创建某种疯狂的规则引擎要复杂得多,速度也慢得多。

While I know that this isn't PHP, I found that Python's eval makes implementation of a basic calculator much simpler.

虽然我知道这不是PHP,但我发现Python的eval使基本计算器的实现简单得多。

Basically, here's the question:

基本上,这是一个问题:

  1. Does eval make it easier to read? One of our chief goals is communicating to other programmers what was going through our head when we wrote this. In the CodeIgniter example it is very clear what they were trying to accomplish.
  2. eval能让它更容易阅读吗?我们的主要目标之一是向其他程序员传达当我们写这篇文章时,我们的脑子里在想什么。在CodeIgniter示例中,非常清楚他们试图实现什么。
  3. Is there another way? Chances are, if you're using eval (or variable variables, or any other form of string look-up or reflection syntax), there is another way to do it. Have you exhausted your other options? Do you have a reasonably limitted input set? Can a switch statement be used?
  4. 有另一种方式吗?如果您正在使用eval(或变量变量,或任何其他形式的字符串查找或反射语法),那么很可能还有其他的方法。你已经用尽了其他的选择了吗?你有合理限制的输入集吗?可以使用switch语句吗?

Other considerations:

其他注意事项:

  1. Can it be made safe? Is there a way that a stray piece of code can work its way into the eval statement?
  2. 它能安全吗?是否有一种方法可以让一段零散的代码工作到eval语句中?
  3. Can it be made consistent? Can you, given an input, always and consistently produce the same output?
  4. 它能保持一致吗?你是否能够,给定一个输入,总是并且始终如一地产生相同的输出?

#8


1  

An appropriate occasion (given the lack of easy alternatives) would be when trusted data was serialized with var_export and it's necessary to unserialize it. Of course, it should never have been serialized in that fashion, but sometimes the error is already done.

一个合适的情况(由于缺乏简单的替代方案)是使用var_export对受信任数据进行序列化,并且需要对其进行反序列化。当然,不应该以这种方式序列化它,但是有时错误已经发生了。

#9


1  

I suppose, eval should be used where the code is actually needs to be compiled. I mean such cases like template file compilations (template language into PHP for the sake of performance), plugin hook compilation, compilations for performance reasons etc.

我认为,应该在需要编译代码的地方使用eval。我的意思是这样的情况,比如模板文件编译(为了性能而将模板语言转换为PHP)、插件钩子编译、性能原因的编译等等。

#10


1  

You could use eval to create a setup for adding code after the system installed. Normally if you would want to change the code on the server you would have to add/change existing PHP files. An alternative to this would be to store the code in a database and use eval to execute it. You'd have to be sure that the code added is safe though.

您可以使用eval创建一个安装程序,以便在系统安装之后添加代码。通常,如果您想要更改服务器上的代码,您必须添加/更改现有的PHP文件。另一种方法是将代码存储在数据库中,并使用eval来执行它。您必须确保添加的代码是安全的。

Think of it like a plugin, just one that can do about anything...

把它想象成一个插件,一个可以做任何事情的插件……

You could think of a site that would allow people to contribute code snippets that the users could then dynamically add into their web pages - without them actually persisting code on the webservers filesystem. What you would need is an approval process though...

您可以想到一个站点,它允许用户贡献代码片段,用户可以动态地将其添加到他们的web页面中——而不需要它们在webserver文件系统上保存代码。但是你需要的是一个批准过程……

#11


0  

Compatibility. It's quite frequent to provide PHP4 fallbacks. But likewise it's a possible desire to emulate PHP5.4 functionality in 5.3, as example SplString. While simply providing two include variants (include.php4 vs. include.php5) is frequent, it's sometimes more efficient or readable to resort to eval():

兼容性。提供PHP4回退是很常见的。但同样,在5.3中模拟PHP5.4功能也是可能的,例如SplString。简单地提供两个包含变体(包括)。php4 vs. include.php5)是常见的,有时使用eval()会更有效或更易读:

 $IMPL_AA = PHP_VERSION >= 5 ? "implements ArrayAccess" : "";
 eval(<<

Where in this case the code would work on PHP4, but expose the nicer API/syntax only on PHP5. Note that the example is fictional.

在本例中,代码将在PHP4上工作,但只在PHP5上公开更好的API/语法。注意这个例子是虚构的。

#12


0  

I've used eval when I had a php-engined bot that communicated with me and I could tell it to do commands via EVAL: php commands here. Still evil, but if your code has no idea what to expect (in case you pull a chunk of PHP code from a database) eval is the only solution.

当我有一个与我通信的php-engine机器人时,我使用了eval: php命令。仍然很糟糕,但是如果您的代码不知道要做什么(如果您从数据库中提取一大块PHP代码),那么eval就是惟一的解决方案。

#13


0  

So, this should hold true for all languages with eval:

因此,对于所有使用eval的语言,都应该如此:

Basically, with few exceptions, if you are building the value passed to eval or getting it from a non-truested source you are doing something wrong. The same holds true if you are calling eval on a static string.

基本上,除了少数例外,如果您正在构建传递给eval的值,或者从一个非真实的源获取值,那么您正在做一些错误的事情。如果在静态字符串中调用eval,则相同。

Beyond the performance problems with initializing the parser at runtime, and the security issues, You generally mess with the type system.

除了在运行时初始化解析器的性能问题和安全性问题之外,通常还会影响类型系统。

More seriously, it's just been shown that in the vast majority of cases, there are much more elegant approaches to the solution. However, instead of banning the construct outright, it's nice to think of it as one might goto. There are legitimate uses for both, but it is a good red flag that should get you thinking about if you are approaching the problem the correct way.

更严重的是,我们刚刚发现,在绝大多数情况下,解决方案的方法要优雅得多。然而,与其完全禁止这个结构,不如把它想象成一个可以去的地方。两者都有合法的用途,但这是一个好的警示标志,如果你用正确的方法解决问题,你应该考虑一下。

In my experience, I've only found legitimate uses that fall in the categories of plugins and privileged user (for instance, the administrator of a website, not the user of such) extensions. Basically things that act as code coming from trusted sources.

根据我的经验,我只找到了属于插件和特权用户类别的合法用途(例如,网站管理员,而不是此类用户)。基本上是来自可信来源的代码。

#14


0  

Not direct use but the /e modifier to preg_replace utilizes eval and can be quite handy. See example #4 on http://php.net/preg_replace.

不是直接使用,而是preg_replace的/e修饰符使用eval,非常方便。参见http://php.net/preg_replace上的示例#4。

Whether or not it's evil/bad is subjective and depends entirely on what you consider "good" in a specific context. When dealing with untrusted inputs it is usually considered bad. However, in other situations it can be useful. Imagine writing a one-time data conversion script under extreme deadline pressure. In this situation, if eval works and makes things easier, I would have trouble calling it evil.

它是邪恶还是邪恶都是主观的,完全取决于你在特定的环境下认为“好”的东西。当处理不可信的输入时,通常被认为是不好的。然而,在其他情况下,它可能是有用的。想象一下,在极端的截止日期压力下编写一个一次性的数据转换脚本。在这种情况下,如果eval能起作用,使事情变得更容易,我就很难称之为邪恶了。

#15


-1  

This eval debate is actually one big misunderstanding in context of php. People are brainwasched about eval being evil, but usually they have no problem using include, although include is essentially the same thing. Include foo is the same as eval file_get_contents foo, so everytime you're including something you commit the mortal sin of eval.

在php上下文中,这种eval的争论实际上是一个很大的误解。人们被认为是邪恶的,但通常他们没有问题使用包括,尽管包括本质上是一样的东西。Include foo与eval file_get_contents foo相同,所以每次包含某些内容时,都会犯eval的致命错误。


推荐阅读
  • PHP反射API的功能和用途详解
    本文详细介绍了PHP反射API的功能和用途,包括动态获取信息和调用对象方法的功能,以及自动加载插件、生成文档、扩充PHP语言等用途。通过反射API,可以获取类的元数据,创建类的实例,调用方法,传递参数,动态调用类的静态方法等。PHP反射API是一种内建的OOP技术扩展,通过使用Reflection、ReflectionClass和ReflectionMethod等类,可以帮助我们分析其他类、接口、方法、属性和扩展。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 也就是|小窗_卷积的特征提取与参数计算
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了卷积的特征提取与参数计算相关的知识,希望对你有一定的参考价值。Dense和Conv2D根本区别在于,Den ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 如何在php中将mysql查询结果赋值给变量
    本文介绍了在php中将mysql查询结果赋值给变量的方法,包括从mysql表中查询count(学号)并赋值给一个变量,以及如何将sql中查询单条结果赋值给php页面的一个变量。同时还讨论了php调用mysql查询结果到变量的方法,并提供了示例代码。 ... [详细]
  • 【shell】网络处理:判断IP是否在网段、两个ip是否同网段、IP地址范围、网段包含关系
    本文介绍了使用shell脚本判断IP是否在同一网段、判断IP地址是否在某个范围内、计算IP地址范围、判断网段之间的包含关系的方法和原理。通过对IP和掩码进行与计算,可以判断两个IP是否在同一网段。同时,还提供了一段用于验证IP地址的正则表达式和判断特殊IP地址的方法。 ... [详细]
  • 本文介绍了在wepy中运用小顺序页面受权的计划,包含了用户点击作废后的从新受权计划。 ... [详细]
  • Learning to Paint with Model-based Deep Reinforcement Learning
    本文介绍了一种基于模型的深度强化学习方法,通过结合神经渲染器,教机器像人类画家一样进行绘画。该方法能够生成笔画的坐标点、半径、透明度、颜色值等,以生成类似于给定目标图像的绘画。文章还讨论了该方法面临的挑战,包括绘制纹理丰富的图像等。通过对比实验的结果,作者证明了基于模型的深度强化学习方法相对于基于模型的DDPG和模型无关的DDPG方法的优势。该研究对于深度强化学习在绘画领域的应用具有重要意义。 ... [详细]
  • 本文介绍了在满足特定条件时如何在输入字段中使用默认值的方法和相应的代码。当输入字段填充100或更多的金额时,使用50作为默认值;当输入字段填充有-20或更多(负数)时,使用-10作为默认值。文章还提供了相关的JavaScript和Jquery代码,用于动态地根据条件使用默认值。 ... [详细]
  • 本文介绍了贝叶斯垃圾邮件分类的机器学习代码,代码来源于https://www.cnblogs.com/huangyc/p/10327209.html,并对代码进行了简介。朴素贝叶斯分类器训练函数包括求p(Ci)和基于词汇表的p(w|Ci)。 ... [详细]
  • node.jsrequire和ES6导入导出的区别原 ... [详细]
  • Python基础知识:注释、输出和input交互
    本文介绍了Python基础知识,包括注释的使用、输出函数print的用法以及input函数的交互功能。其中涉及到字符串和整数的类型转换等内容。 ... [详细]
  • 前段时间做一个项目,需求是对每个视频添加预览图,这个问题最终选择方案是:用canvas.toDataYRL();来做转换获取视频的一个截图,添加到页面中,达到自动添加预览图的目的。 ... [详细]
  • 在加载一个第三方厂商的dll文件时,提示“找不到指定模块,加载失败”。由于缺乏必要的技术支持,百思不得期间。后来发现一个有用的工具 ... [详细]
author-avatar
subingyi84
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有