Why should exec() and eval() be avoided?

后端 未结 11 1993
Happy的楠姐
Happy的楠姐 2020-11-22 00:16

I\'ve seen this multiple times in multiple places, but never have found a satisfying explanation as to why this should be the case.

So, hopefully, one will be prese

相关标签:
11条回答
  • 2020-11-22 00:56

    I have used eval() in the past (and still do from time-to-time) for massaging data during quick and dirty operations. It is part of the toolkit that can be used for getting a job done, but should NEVER be used for anything you plan to use in production such as any command-line tools or scripts, because of all the reasons mentioned in the other answers.

    You cannot trust your users--ever--to do the right thing. In most cases they will, but you have to expect them to do all of the things you never thought of and find all of the bugs you never expected. This is precisely where eval() goes from being a tool to a liability.

    A perfect example of this would be using Django, when constructing a QuerySet. The parameters passed to a query accepts keyword arguments, that look something like this:

    results = Foo.objects.filter(whatever__contains='pizza')
    

    If you're programmatically assigning arguments, you might think to do something like this:

    results = eval("Foo.objects.filter(%s__%s=%s)" % (field, matcher, value))
    

    But there is always a better way that doesn't use eval(), which is passing a dictionary by reference:

    results = Foo.objects.filter( **{'%s__%s' % (field, matcher): value} ) 
    

    By doing it this way, it's not only faster performance-wise, but also safer and more Pythonic.

    Moral of the story?

    Use of eval() is ok for small tasks, tests, and truly temporary things, but bad for permanent usage because there is almost certainly always a better way to do it!

    0 讨论(0)
  • 2020-11-22 00:57

    There are often clearer, more direct ways to get the same effect. If you build a complex string and pass it to exec, the code is difficult to follow, and difficult to test.

    Example: I wrote code that read in string keys and values and set corresponding fields in an object. It looked like this:

    for key, val in values:
        fieldName = valueToFieldName[key]
        fieldType = fieldNameToType[fieldName]
        if fieldType is int:
            s = 'object.%s = int(%s)' % (fieldName, fieldType) 
        #Many clauses like this...
    
    exec(s)
    

    That code isn't too terrible for simple cases, but as new types cropped up it got more and more complex. When there were bugs they always triggered on the call to exec, so stack traces didn't help me find them. Eventually I switched to a slightly longer, less clever version that set each field explicitly.

    The first rule of code clarity is that each line of your code should be easy to understand by looking only at the lines near it. This is why goto and global variables are discouraged. exec and eval make it easy to break this rule badly.

    0 讨论(0)
  • 2020-11-22 00:57

    When you need exec and eval, yeah, you really do need them.

    But, the majority of the in-the-wild usage of these functions (and the similar constructs in other scripting languages) is totally inappropriate and could be replaced with other simpler constructs that are faster, more secure and have fewer bugs.

    You can, with proper escaping and filtering, use exec and eval safely. But the kind of coder who goes straight for exec/eval to solve a problem (because they don't understand the other facilities the language makes available) isn't the kind of coder that's going to be able to get that processing right; it's going to be someone who doesn't understand string processing and just blindly concatenates substrings, resulting in fragile insecure code.

    It's the Lure Of Strings. Throwing string segments around looks easy and fools naïve coders into thinking they understand what they're doing. But experience shows the results are almost always wrong in some corner (or not-so-corner) case, often with potential security implications. This is why we say eval is evil. This is why we say regex-for-HTML is evil. This is why we push SQL parameterisation. Yes, you can get all these things right with manual string processing... but unless you already understand why we say those things, chances are you won't.

    0 讨论(0)
  • 2020-11-22 00:59

    Security aside, eval and exec are often marked as undesirable because of the complexity they induce. When you see a eval call you often don't know what's really going on behind it, because it acts on data that's usually in a variable. This makes code harder to read.

    Invoking the full power of the interpreter is a heavy weapon that should be only reserved for very tricky cases. In most cases, however, it's best avoided and simpler tools should be employed.

    That said, like all generalizations, be wary of this one. In some cases, exec and eval can be valuable. But you must have a very good reason to use them. See this post for one acceptable use.

    0 讨论(0)
  • 2020-11-22 00:59

    Allowing these function in a context where they might run user input is a security issue, and sanitizers that actually work are hard to write.

    0 讨论(0)
提交回复
热议问题