Re: Is it possible to get the erroneous variable when getting a NameError exception?
On Sat, Dec 26, 2009 at 4:34 AM, Michael Fötsch wrote: > To explain, "().__class__.__base__.__subclasses__()" gives you a list of > all object-derived classes, i.e., of *all* classes that exist in the > surrounding program. If you can find just one class that allows you to do > something subtle or dangerous, you're done. > > Aiee, I forgot about that. I stand corrected. :) Okay, I'll go back to the 'eval is almost never what you wanna do' camp again :) --S -- http://mail.python.org/mailman/listinfo/python-list
Re: Is it possible to get the erroneous variable when getting a NameError exception?
A simple expression is enough to write to files, for example. Try this expression in Python 3.0: [x for x in ().__class__.__base__.__subclasses__() if x.__name__ == '_FileIO'][0]('hello.txt', 'w').write('Hello, World!') To explain, "().__class__.__base__.__subclasses__()" gives you a list of all object-derived classes, i.e., of *all* classes that exist in the surrounding program. If you can find just one class that allows you to do something subtle or dangerous, you're done. See also: - "Controlling Access to Resources Within The Python Interpreter" (http://people.cs.ubc.ca/~drifty/papers/python_security.pdf) - http://evoque.gizmojo.org/usage/restricted/ To write your own restricted expression parser, the standard module "ast" is quite useful. For example, ast.parse("my_number < 10") gives you a syntax tree similar to this: ast.Expr(ast.Compare(ops=[ast.Lt], left=ast.Name(id="my_number"), comparators=[ast.Num(n=10)])) From there, you can implement your own logic to traverse the tree, which gives you very fine-grained control over the kinds of expressions to allow, where to look up variable names, how to react to errors, etc. Kind Regards, M.F. Hi all. First of all, thank you very much for your response. The answers I got made me think if I'm trying to solve a problem because of the way I'm doing things; I tried to evaluate a string that a user supplied to me and try to get the various python exceptions to make the user understand what was his error. My original idea was to get the bad symbol, and print the user a more "friendly" error message. I think that the direction that Michael showed me is better, and It is a better solution (maybe, first I need to traverse the tree, give the right error messages and only then execute the eval). Thanks!!! Dotan -- http://mail.python.org/mailman/listinfo/python-list
Re: Is it possible to get the erroneous variable when getting a NameError exception?
Stephen Hansen wrote: Dotan Barak wrote: ... eval("my_number < 10", {"__builtins__":None}, {}) Hm, is this true, though? Is there anything subtle or dangerous possible here? He's using eval-- so no statements, its only an expression. He's passing in a 'globals' which has __builtins__ set to None, so this environment has access to -- basically nothing. Then the locals dictionary is empty as well, though I assume he'll fill it with things like my_number. A simple expression is enough to write to files, for example. Try this expression in Python 3.0: [x for x in ().__class__.__base__.__subclasses__() if x.__name__ == '_FileIO'][0]('hello.txt', 'w').write('Hello, World!') To explain, "().__class__.__base__.__subclasses__()" gives you a list of all object-derived classes, i.e., of *all* classes that exist in the surrounding program. If you can find just one class that allows you to do something subtle or dangerous, you're done. See also: - "Controlling Access to Resources Within The Python Interpreter" (http://people.cs.ubc.ca/~drifty/papers/python_security.pdf) - http://evoque.gizmojo.org/usage/restricted/ To write your own restricted expression parser, the standard module "ast" is quite useful. For example, ast.parse("my_number < 10") gives you a syntax tree similar to this: ast.Expr(ast.Compare(ops=[ast.Lt], left=ast.Name(id="my_number"), comparators=[ast.Num(n=10)])) From there, you can implement your own logic to traverse the tree, which gives you very fine-grained control over the kinds of expressions to allow, where to look up variable names, how to react to errors, etc. Kind Regards, M.F. -- http://mail.python.org/mailman/listinfo/python-list
Re: Is it possible to get the erroneous variable when getting a NameError exception?
On Fri, Dec 25, 2009 at 8:00 PM, Dave Angel wrote: > Dotan Barak wrote: >>> >>> Recover the exception, and examine the tuple of args or the message >>> string. >>> >>> try: >>> ... eval("my_number < 10", {"__builtins__":None}, {}) >>> ... except NameError,e: >>> ... print e.args >>> ... print e.message >>> ... >>> ("name 'my_number' is not defined",) >>> name 'my_number' is not defined >>> >>> I think there's a more fundamental question here. You're apparently > looking to build your own error message instead of using the one already > generated. But as you point out, you might end up parsing the existing > error message in order to do that, and that's fragile coding. My take is > that if you're using "eval" in your code, your user is clearly a programmer. > So why are you not letting that programmer see the real error message, > instead of trying to pretty it up? You can add to the message, but > shouldn't need to hide the original one. > > To put it the other way around, if your user can't understand the python > error messages, you should probably not be using unrestricted "eval" on > something that user supplies. Lots more errors than NameError, and many of > them are more subtle and dangerous. > > Hm, is this true, though? Is there anything subtle or dangerous possible here? He's using eval-- so no statements, its only an expression. He's passing in a 'globals' which has __builtins__ set to None, so this environment has access to -- basically nothing. Then the locals dictionary is empty as well, though I assume he'll fill it with things like my_number. Its sort of an interesting use for 'eval' that I hadn't ever considered before, really: ISTM that there's only three possible results.. a NameError, a SyntaxError, or a safely evaluated expression based on certain pre-defined objects. Okay, maybe one or two other simple exceptions if one tries to do strange things with dictionaries/etc in the expression. You can't even make it blow up to trigger a MemoryError, with some insane list comprehension because you don't even have access to range(). Unless he's passing an arbitrarily long string into the expression. I'm normally against eval -- but maybe I'm blind in not seeing the possible exploit or subtlety here in this eval-with-zero-access. --S -- http://mail.python.org/mailman/listinfo/python-list
Re: Is it possible to get the erroneous variable when getting a NameError exception?
Dotan Barak wrote: On 25/12/2009 19:27, Gary Herron wrote: Dotan Barak wrote: Recover the exception, and examine the tuple of args or the message string. >>> try: ... eval("my_number < 10", {"__builtins__":None}, {}) ... except NameError,e: ... print e.args ... print e.message ... ("name 'my_number' is not defined",) name 'my_number' is not defined First of all, thank - I really appreciate your response. :) I must admit that i don't like the idea of parsing a string (if tomorrow the format of the message will change, i will be in a deep trouble ...). Is there is another way which doesn't involve string parsing? Thanks Dotan I think there's a more fundamental question here. You're apparently looking to build your own error message instead of using the one already generated. But as you point out, you might end up parsing the existing error message in order to do that, and that's fragile coding. My take is that if you're using "eval" in your code, your user is clearly a programmer. So why are you not letting that programmer see the real error message, instead of trying to pretty it up? You can add to the message, but shouldn't need to hide the original one. To put it the other way around, if your user can't understand the python error messages, you should probably not be using unrestricted "eval" on something that user supplies. Lots more errors than NameError, and many of them are more subtle and dangerous. DaveA -- http://mail.python.org/mailman/listinfo/python-list
Re: Is it possible to get the erroneous variable when getting a NameError exception?
Dotan Barak wrote: On 25/12/2009 19:27, Gary Herron wrote: Dotan Barak wrote: Recover the exception, and examine the tuple of args or the message string. >>> try: ... eval("my_number < 10", {"__builtins__":None}, {}) ... except NameError,e: ... print e.args ... print e.message ... ("name 'my_number' is not defined",) name 'my_number' is not defined First of all, thank - I really appreciate your response. :) I must admit that i don't like the idea of parsing a string (if tomorrow the format of the message will change, i will be in a deep trouble ...). Is there is another way which doesn't involve string parsing? Thanks Dotan OK. Try this: Executing your code attempts to lookup variables in a local dictionary. You can rig up a local dictionary of your own choosing -- in this case, I have it print the name of any variable that is being looked up before actually doing the lookup.But at that point, you have what you want, that is, the name as a string -- you can do with it as you will -- record it, or print your nice error, or ... You probably want to change my def of __getitem__ to attempt the lookup first -- if that succeeds, return the value -- if it fails, then handle the error. Good luck, Gary Herron class D(dict): def __getitem__(self, name): print 'retrieving', name return dict.__getitem__(self,name) locals = D(b=123) # Defines b in a local dictionary exec("a=2*b", locals) # Looks up b in locals print locals['a'] # Returns the result (stored in 'a' in locals) locals = D() # Does not define b in the local dictionary exec("a=2*b", locals) # Fails to find b in locals -- http://mail.python.org/mailman/listinfo/python-list
Re: Is it possible to get the erroneous variable when getting a NameError exception?
On 25/12/2009 19:27, Gary Herron wrote: Dotan Barak wrote: Recover the exception, and examine the tuple of args or the message string. >>> try: ... eval("my_number < 10", {"__builtins__":None}, {}) ... except NameError,e: ... print e.args ... print e.message ... ("name 'my_number' is not defined",) name 'my_number' is not defined First of all, thank - I really appreciate your response. :) I must admit that i don't like the idea of parsing a string (if tomorrow the format of the message will change, i will be in a deep trouble ...). Is there is another way which doesn't involve string parsing? Thanks Dotan -- http://mail.python.org/mailman/listinfo/python-list
Re: Is it possible to get the erroneous variable when getting a NameError exception?
Dotan Barak wrote: Hi. I'm trying to evaluate a string and getting a NameError (it is expected, since the variable my_number wasn't provided in the "locals" dictionary). <--snip start--> >>> eval("my_number < 10", {"__builtins__":None}, {}) Traceback (most recent call last): File "", line 1, in ? File "", line 0, in ? NameError: name 'my_number' is not defined <--snip end--> My question is: how can i know which variable name / symbol causes the NameError exception? In my example, this symbol is my_number. Using that information, I will be able to print a nice error message to the user. Thanks Dotan Recover the exception, and examine the tuple of args or the message string. >>> try: ... eval("my_number < 10", {"__builtins__":None}, {}) ... except NameError,e: ... print e.args ... print e.message ... ("name 'my_number' is not defined",) name 'my_number' is not defined -- http://mail.python.org/mailman/listinfo/python-list
Re: Is it possible to get the erroneous variable when getting a NameError exception?
On Fri, 25 Dec 2009 17:29:48 +0200, Dotan Barak wrote: > Hi. > > I'm trying to evaluate a string and getting a NameError (it is expected, > since the variable my_number wasn't provided in the "locals" > dictionary). > > <--snip start--> > >>> eval("my_number < 10", {"__builtins__":None}, {}) > Traceback (most recent call last): >File "", line 1, in ? >File "", line 0, in ? > NameError: name 'my_number' is not defined > <--snip end--> > > My question is: how can i know which variable name / symbol causes the > NameError exception? > In my example, this symbol is my_number. > > Using that information, I will be able to print a nice error message to > the user. You mean just like the error message that Python already prints? NameError: name 'my_number' is not defined Don't waste your time re-inventing the wheel. But if you do insist on reinventing the wheel, here are some tools to help you: try: my_number except NameError, e: print str(e) print type(e) print e.args -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Is it possible to get the erroneous variable when getting a NameError exception?
Hi. I'm trying to evaluate a string and getting a NameError (it is expected, since the variable my_number wasn't provided in the "locals" dictionary). <--snip start--> >>> eval("my_number < 10", {"__builtins__":None}, {}) Traceback (most recent call last): File "", line 1, in ? File "", line 0, in ? NameError: name 'my_number' is not defined <--snip end--> My question is: how can i know which variable name / symbol causes the NameError exception? In my example, this symbol is my_number. Using that information, I will be able to print a nice error message to the user. Thanks Dotan -- http://mail.python.org/mailman/listinfo/python-list