lmfit / asteval

minimalistic evaluator of python expression using ast module
https://lmfit.github.io/asteval
MIT License
183 stars 41 forks source link

Does not evaluate types like eval() #98

Closed a-p-jo closed 3 years ago

a-p-jo commented 3 years ago

Sorry for vague title, did not know how to properly word this. Here's what I'm seeing :

>>> import asteval
>>> e = asteval.Interpreter()
>>> eval('type(4) == int')
True
>>> e('type(4) == int')
False

Why ? Well, because :

>>> e('type(1)')
'int'
>>> eval('type(1)')
<class 'int'>

But why's that ?

newville commented 3 years ago

On Sat, Aug 14, 2021, 6:14 AM A.P. Jo. @.***> wrote:

Sorry for vague title, did not know how to properly word this. Here's what I'm seeing :

import asteval e = asteval.Interpreter() eval('type(4) == int') True e('type(4) == int') False

Why ? Well, because :

e('type(1)') 'int' eval('type(1)') <class 'int'>

But why's that ?

Because returning a python class would be dangerous.

a-p-jo commented 3 years ago

@newville it seems then that the intended use of your project and the requirements I have for my project have a significant gulf between them.

Could you suggest another eval() style way of running python expressions safely ?

If you have the time, could you also ELI5 why returning classes is dangerous , and why you find it is worth the breakage of functionality

newville commented 3 years ago

@a-p-jo I have no idea what 'ELI5' means. For why returning a class is dangerous, see https://newville.github.io/asteval/motivation.html#how-safe-is-asteval and http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html. Basically, if the user gets a Python class as a value, it is trivial to segfault the calling Python interpreter.

I don't know what your requirements (features or safety) for an eval() function that is both "somewhat safe" and "different from asteval". For sure, this code here may not do everything that everyone wants for a "safe-ish" eval(). Suggestions welcome. Then again, any project that claims to be completely safe is almost certainly wrong.

We try to avoid known ways for user code causing core dumps of the calling process. Still, it is trivial for a single line of code accepted by asteval (and python) to have a runtime of 10 years, with no way to interrupt that except by killing the process. All that is required is the ** operator. That is the recipe for a DOS attack. We cannot prevent that and also allow simple mathematical processing.

a-p-jo commented 3 years ago

@newville ELI5 means 'Explain Like I'm 5' , and I used it because I'm kind of new to Python. The segfault risk though, gives me a question - isn't asteval designed to take user input but the returned stuff is handled by the programmer who implemented it ? If so, the programmer ought to be trusted to not segfault in his code ?

My requirements are essentiallly an eval() that doesn't allow the user arbitrary code execution (like with calling import, exec, compile, eval, etc) meant for evaluating things like foo[bar] or foo + bar from input, and of course converting something like "[foo,bar...]" to [foo,bar...]. I was previously just using eval but with restricted names and not evaluating expressions if compile(...) had in it names that were not allowed. I will probably go back to this , as it seems to be the best way to do what i need at the moment.

I understand the DOS / runtime attack vector, and that is not a concern. I'm writing a completely offline, domain-specific small script interpreter and the only reason to restrict arbitrary code execution is because it would be stupid if a user could be importing or evaluating code randomly where they're supposed to be entering a python sequence. It's not exactly a serious security consideration.

newville commented 3 years ago

@a-p-jo I am definitely not going to try to explain this to anyone as if they were 5 years old.

The segfault risk though, gives me a question - isn't asteval designed to take user input but the returned stuff is handled by the programmer who implemented it ? If so, the programmer ought to be trusted to not segfault in his code ?

We disallow many things in the user-available asteval mini-language that we know would let a user intentionally segfault the calling Python process. From within the asteval mini-language, the user cannot create new classes, import modules, or dig too deeply into the underbelly of the various classes/types that are available. Despite that, enough of Python is supported to give a credible mini-language, especially for mathematical calculations, with user-defined functions, and handling strings, lists, and dictionaries. If you have not read the docs, please do so.

a-p-jo commented 3 years ago

I am definitely not going to try to explain this to anyone as if they were 5 years old.

It was a figure of speech 🤦

If you have not read the docs, please do so.

I have , and I respect and understand that your vision for your project makes this a non-issue for this project. I am thereby closing this issue. Thank you for your timely responses !