Joel Hedlund wrote: > Hi all! > > I'm writing a program that presents a lot of numbers to the user, and I > want to let the user apply moderately simple arithmentics to these > numbers. One possibility that comes to mind is to use the eval function, > but since that sends up all kinds of warning flags in my head, I thought > I'd put my idea out here first so you guys can tell me if I'm insane. :-) > > This is the gist of it: > ---------------------------------------------------------- > import math > > globals = dict((s, getattr(math, s)) for s in dir(math) if '_' not in s) > globals.update(__builtins__=None, divmod=divmod, round=round) > > def calc(expr, x): > if '_' in expr: > raise ValueError("expr must not contain '_' characters") > try: > return eval(expr, globals, dict(x=x)) > except: > raise ValueError("bad expr or x") > > print calc('cos(x*pi)', 1.33) > ---------------------------------------------------------- > > This lets the user do stuff like "exp(-0.01*x)" or "round(100*x)" but > prevents malevolent stuff like "__import__('os').system('del *.*')" or > "(t for t in (42).__class__.__base__.__subclasses__() if t.__name__ == > 'file').next()" from messing things up. > > I assume there's lots of nasty and absolutely lethal stuff that I've > missed, and I kindly request you show me the error of my ways. > > Thank you for your time! > /Joel Hedlund
I'm way too dumb and lazy to provide a working example, but someone could work around the _ restriction by obfuscating them a bit, like this: >>> '\x5f' '_' >>> getattr(42, '\x5f\x5fclass\x5f\x5f') # __class__ <type 'int'> Is that enough to show you the error of your ways? :-D Cuz seriously, it's a bad idea. I'm sorry, but I don't know a good solution. The simplicity of eval is definitely very attractive, but it's just not safe. (BTW: What if a user tries to do some ridiculously large calculation to DoS the app? Is that a problem?) -- -- http://mail.python.org/mailman/listinfo/python-list