Re: How is correct use of eval()

Discussion in 'Python' started by Chris Rebert, Oct 11, 2010.

  1. Chris Rebert

    Chris Rebert Guest

    On Mon, Oct 11, 2010 at 11:11 AM, Cata <> wrote:
    > Hi .
    > I read about eval().
    > I also read about this "bug" :
    > cod = raw_input ('Enter:")
    > eval (cod)
    > if i use  "rm -rf ~"  all files will be deleted .


    That's incorrect. eval() does not (directly) run shell commands. It
    does evaluate arbitrary Python expressions though, which can delete
    files and do other things just as nasty as rm -rf.

    > What is correct way to use this function?


    To not use it in the first place if at all possible (use int(),
    float(), getattr(), etc. instead, depending on what you're doing), or
    to only use it with trusted or heavily validated input.

    Cheers,
    Chris
    --
    Darned literature commentaries...
    http://blog.rebertia.com
    Chris Rebert, Oct 11, 2010
    #1
    1. Advertising

  2. On Mon, 11 Oct 2010 11:18:37 -0700, Chris Rebert wrote:

    > On Mon, Oct 11, 2010 at 11:11 AM, Cata <> wrote:
    >> Hi .
    >> I read about eval().
    >> I also read about this "bug" :
    >> cod = raw_input ('Enter:")
    >> eval (cod)
    >> if i use  "rm -rf ~"  all files will be deleted .

    >
    > That's incorrect. eval() does not (directly) run shell commands. It does
    > evaluate arbitrary Python expressions though, which can delete files and
    > do other things just as nasty as rm -rf.
    >
    >> What is correct way to use this function?

    >
    > To not use it in the first place if at all possible (use int(), float(),
    > getattr(), etc. instead, depending on what you're doing), or to only use
    > it with trusted or heavily validated input.


    Furthermore, consider that no matter how clever you are at guessing all
    the possible tricks that bad guys might introduce to your code, you can
    never be sure you have guessed *all* of them.


    --
    Steven
    Steven D'Aprano, Oct 12, 2010
    #2
    1. Advertising

  3. Chris Rebert

    Nobody Guest

    On Mon, 11 Oct 2010 11:18:37 -0700, Chris Rebert wrote:

    >> What is correct way to use this function?

    >
    > To not use it in the first place if at all possible (use int(),
    > float(), getattr(), etc. instead,


    Use read(). Oh wait, Python doesn't have that. Because parsing literals
    and executing code are like totally the same thing.
    Nobody, Oct 12, 2010
    #3
  4. Chris Rebert

    Chris Rebert Guest

    On Mon, Oct 11, 2010 at 5:26 PM, Nobody <> wrote:
    > On Mon, 11 Oct 2010 11:18:37 -0700, Chris Rebert wrote:
    >>> What is correct way to use this function?

    >>
    >> To not use it in the first place if at all possible (use int(),
    >> float(), getattr(), etc. instead,

    >
    > Use read(). Oh wait, Python doesn't have that. Because parsing literals
    > and executing code are like totally the same thing.


    import ast
    module = compile(raw_input(), "<input>", "exec", ast.PyCF_ONLY_AST)
    print ast.dump(module)

    Cheers,
    Chris
    --
    http://blog.rebertia.com
    Chris Rebert, Oct 12, 2010
    #4
  5. Chris Rebert

    Nobody Guest

    On Tue, 12 Oct 2010 01:26:25 +0100, Nobody wrote:

    >>> What is correct way to use this function?

    >>
    >> To not use it in the first place if at all possible (use int(),
    >> float(), getattr(), etc. instead,

    >
    > Use read(). Oh wait, Python doesn't have that. Because parsing literals
    > and executing code are like totally the same thing.


    Oh, look what's "new in version 2.6":

    > ast.literal_eval("7")
    7
    > ast.literal_eval("7") == 7
    True

    ast.literal_eval(node_or_string)

    Safely evaluate an expression node or a string containing a Python
    expression. The string or node provided may only consist of the
    following Python literal structures: strings, numbers, tuples, lists,
    dicts, booleans, and None.

    This can be used for safely evaluating strings containing Python
    expressions from untrusted sources without the need to parse the
    values oneself.

    I'm guessing that I'm not the only person who hasn't noticed this until
    now.
    Nobody, Oct 12, 2010
    #5
  6. Chris Rebert

    Guest

    Ok,
    I asking that to understand the correct way of python and I don't want
    make mistakes.
    I suppose has many tricks used by "bad guys".
    , Oct 12, 2010
    #6
  7. Nobody <> writes:

    > Oh, look what's "new in version 2.6":
    >
    > > ast.literal_eval("7")
    > 7
    > > ast.literal_eval("7") == 7
    > True


    Note that it doesn't work for some reasonable inputs involving unary and
    binary plus, such as "[-2, +1]" or "2+3j". This has been fixed in the
    development (3.2) sources.

    An interesting aspect of ast.literal_eval is that it merely uses the
    public API to access the AST provided by the compiler. One is therefore
    free to "fix" literal_eval in 2.6 or 2.7 by defining their own similar
    function with the desired flavor. For example:

    import ast
    from itertools import imap, izip

    def my_literal_eval(s):
    node = ast.parse(s, mode='eval').body
    return _convert(node)

    _safe_names = {'None': None, 'True': True, 'False': False}
    _safe_operands = (ast.Num, ast.UnaryOp, ast.BinOp)
    _safe_unops = (ast.UAdd, ast.USub)
    _safe_binops = (ast.Add, ast.Sub)

    def _convert(node):
    if isinstance(node, ast.Str):
    return node.s
    elif isinstance(node, ast.Num):
    return node.n
    elif isinstance(node, ast.Tuple):
    return tuple(imap(_convert, node.elts))
    elif isinstance(node, ast.List):
    return list(imap(_convert, node.elts))
    elif isinstance(node, ast.Dict):
    return dict((_convert(k), _convert(v)) for k, v
    in izip(node.keys, node.values))
    elif isinstance(node, ast.Name) and node.id in _safe_names:
    return _safe_names[node.id]
    elif isinstance(node, ast.UnaryOp) and \
    isinstance(node.op, _safe_unops) and \
    isinstance(node.operand, _safe_operands):
    operand = _convert(node.operand)
    if isinstance(node.op, ast.UAdd):
    return + operand
    else:
    return - operand
    elif isinstance(node, ast.BinOp) and isinstance(node.op, _safe_binops) \
    and isinstance(node.right, _safe_operands) \
    and isinstance(node.left, _safe_operands):
    left = _convert(node.left)
    right = _convert(node.right)
    if isinstance(node.op, ast.Add):
    return left + right
    else:
    return left - right
    raise ValueError('malformed expression: ' + repr(node))
    Hrvoje Niksic, Oct 12, 2010
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Eric Newton
    Replies:
    3
    Views:
    9,389
    Brock Allen
    Apr 4, 2005
  2. DataBinder.Eval and Eval.

    , Jun 16, 2006, in forum: ASP .Net
    Replies:
    1
    Views:
    542
    Karl Seguin [MVP]
    Jun 16, 2006
  3. Alex van der Spek

    eval('07') works, eval('08') fails, why?

    Alex van der Spek, Jan 8, 2009, in forum: Python
    Replies:
    6
    Views:
    1,434
    Bruno Desthuilliers
    Jan 8, 2009
  4. Liang Wang
    Replies:
    8
    Views:
    129
    Ben Morrow
    Feb 2, 2008
  5. Marc Girod

    to eval or not to eval?

    Marc Girod, Apr 19, 2011, in forum: Perl Misc
    Replies:
    2
    Views:
    154
    Marc Girod
    Apr 19, 2011
Loading...

Share This Page