Is this a safe use of eval?

Discussion in 'Python' started by Frank Millman, Feb 24, 2011.

  1. Hi all

    I know that the use of 'eval' is discouraged because of the dangers of
    executing untrusted code.

    Here is a variation that seems safe to me, but I could be missing something.

    I have a class, and the class has one or more methods which accept various
    arguments and return a result.

    I want to accept a method name and arguments in string form, and 'eval' it
    to get the result.

    Assume I have an instance called my_inst, and a method called 'calc_area',
    with arguments w and h.

    I then receive my_string = 'calc_area(100, 200)'.

    >>> result = eval('my_inst.{0}'.format(my_string))


    This will only work if the string contains a valid method name with valid
    arguments.

    Can anyone see anything wrong with this?

    Thanks

    Frank Millman
    Frank Millman, Feb 24, 2011
    #1
    1. Advertising

  2. Frank Millman

    Paul Rubin Guest

    "Frank Millman" <> writes:
    > I then receive my_string = 'calc_area(100, 200)'.
    >>>> result = eval('my_inst.{0}'.format(my_string))

    > This will only work if the string contains a valid method name with
    > valid arguments.
    >
    > Can anyone see anything wrong with this?


    Um, yes. What are valid arguments? Are you going to eval them?

    If they can only be literals, maybe you could use something like

    from ast import literal_eval
    method_name = 'calc_area'
    args = literal_eval('(100,200)')
    result = getattr(my_inst, method_name)(*args)

    but even that is risky in a hostile data environment.
    Paul Rubin, Feb 24, 2011
    #2
    1. Advertising

  3. Frank Millman

    Peter Otten Guest

    Frank Millman wrote:

    > Hi all
    >
    > I know that the use of 'eval' is discouraged because of the dangers of
    > executing untrusted code.
    >
    > Here is a variation that seems safe to me, but I could be missing
    > something.
    >
    > I have a class, and the class has one or more methods which accept various
    > arguments and return a result.
    >
    > I want to accept a method name and arguments in string form, and 'eval' it
    > to get the result.
    >
    > Assume I have an instance called my_inst, and a method called 'calc_area',
    > with arguments w and h.
    >
    > I then receive my_string = 'calc_area(100, 200)'.
    >
    >>>> result = eval('my_inst.{0}'.format(my_string))

    >
    > This will only work if the string contains a valid method name with valid
    > arguments.
    >
    > Can anyone see anything wrong with this?


    How do you prevent that a malicious source sends you

    my_string = 'calc_area(__import__("os").system("rm important_file") or 100,
    200)'

    instead?
    Peter Otten, Feb 24, 2011
    #3
  4. Frank Millman

    Web Dreamer Guest

    Frank Millman a écrit ce jeudi 24 février 2011 09:48 dans
    <> :

    > Hi all
    >
    > I know that the use of 'eval' is discouraged because of the dangers of
    > executing untrusted code.
    >
    > Here is a variation that seems safe to me, but I could be missing
    > something.
    >
    > I have a class, and the class has one or more methods which accept various
    > arguments and return a result.
    >
    > I want to accept a method name and arguments in string form, and 'eval' it
    > to get the result.
    >
    > Assume I have an instance called my_inst, and a method called 'calc_area',
    > with arguments w and h.
    >
    > I then receive my_string = 'calc_area(100, 200)'.
    >
    >>>> result = eval('my_inst.{0}'.format(my_string))

    >
    > This will only work if the string contains a valid method name with valid
    > arguments.


    I'd do it that way:

    >>> class My_Class(object):

    .... def calc_area(self, a, b):
    .... return a*b
    ....
    >>> my_inst = My_Class()
    >>> my_string = 'calc_area(100, 200)'
    >>> my_func_and_args = my_string.split('(')
    >>> my_func = my_func_and_args.pop(0)
    >>> my_args = my_func_and_args[0].strip(')')
    >>> my_args = my_args.split(',')
    >>> my_args = [int(arg) for arg in my_args]
    >>> if hasattr(my_inst, my_func):

    .... getattr(my_inst,my_func)(*my_args)
    ....
    20000


    And no eval is ever performed.

    --
    Web Dreamer
    Web Dreamer, Feb 24, 2011
    #4
  5. Frank Millman

    Nobody Guest

    On Thu, 24 Feb 2011 15:24:51 +0200, Frank Millman wrote:

    > Thanks, Christian. I had a look at that recipe, but I must say that Paul's
    > suggestion is much simpler -
    >
    > from ast import literal_eval
    > method_name = 'calc_area'
    > args = literal_eval('(100,200)')
    > result = getattr(my_inst, method_name)(*args)
    >
    > In my case the arguments are all strings or integers, so it looks as if this
    > approach should be safe. Do you see any problem with it?


    Only that you may need a fairly recent version of the ast module; the
    first attempt at literal_eval was a bit too ... literal, e.g. it couldn't
    handle negative numbers (Python doesn't have negative integer literals;
    evaluating "-10" applies the negation operator to the integer 10).
    Nobody, Feb 25, 2011
    #5
    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,379
    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,427
    Bruno Desthuilliers
    Jan 8, 2009
  4. Liang Wang
    Replies:
    8
    Views:
    128
    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