Path: csiph.com!usenet.pasdenom.info!gegeweb.org!de-l.enfer-du-nord.net!feeder2.enfer-du-nord.net!newsfeed.eweka.nl!eweka.nl!feeder3.eweka.nl!newsfeed.xs4all.nl!newsfeed3.news.xs4all.nl!xs4all!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.002 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'column': 0.07; 'subject:Question': 0.07; 'false,': 0.09; 'mixed': 0.09; 'raises': 0.09; 'received:80.91': 0.09; 'received:80.91.229': 0.09; 'received:gmane.org': 0.09; 'received:list': 0.09; 'subject:skip:a 10': 0.09; 'underscore': 0.09; 'wrapper': 0.09; 'suggest': 0.14; "wouldn't": 0.14; 'barrier': 0.16; 'brackets.': 0.16; 'evaluates': 0.16; 'false)': 0.16; 'globals': 0.16; 'globals.': 0.16; 'investigate': 0.16; 'personally,': 0.16; 'received:80.91.229.3': 0.16; 'received:plane.gmane.org': 0.16; 'substitute': 0.16; 'underscore.': 0.16; 'underscores': 0.16; '{})': 0.16; 'exception': 0.16; ':-)': 0.16; 'wrote:': 0.18; 'result.': 0.19; 'seems': 0.21; 'header:User-Agent:1': 0.23; 'convenient': 0.24; 'finally,': 0.24; 'mon,': 0.24; 'pass': 0.26; 'header:X -Complaints-To:1': 0.27; 'header:In-Reply-To:1': 0.27; 'point': 0.28; 'appreciated.': 0.29; "doesn't": 0.30; 'strongly': 0.30; 'work.': 0.31; 'gives': 0.31; 'that.': 0.31; 'usually': 0.31; 'breaking': 0.31; "d'aprano": 0.31; 'directly,': 0.31; 'high.': 0.31; 'steven': 0.31; 'anyone': 0.31; 'this.': 0.32; 'themselves': 0.32; 'becomes': 0.33; 'actual': 0.34; 'maybe': 0.34; "can't": 0.35; 'advice': 0.35; 'anywhere': 0.35; 'usual': 0.35; 'test': 0.35; 'but': 0.35; '+0200,': 0.36; 'thanks': 0.36; 'wrong': 0.37; 'list': 0.37; 'to:addr:python-list': 0.38; 'list,': 0.38; 'anything': 0.39; 'sure': 0.39; 'to:addr:python.org': 0.39; 'received:org': 0.40; 'even': 0.60; 'expression': 0.60; 'manually': 0.60; 'worry': 0.60; 'break': 0.61; 'name': 0.63; 'real': 0.63; 'decided': 0.64; 'response.': 0.68; 'frank': 0.68; 'internet': 0.71; 'safe': 0.72; 'evaluate': 0.72; 'experiment': 0.84; 'hand.': 0.84; 'refusing': 0.84; 'safe.': 0.84; 'approach.': 0.91; '2013': 0.98 X-Injected-Via-Gmane: http://gmane.org/ To: python-list@python.org From: Frank Millman Subject: Re: Question about ast.literal_eval Date: Tue, 21 May 2013 08:30:03 +0200 References: <519a4b6a$0$29997$c3e8da3$5496439d@news.astraweb.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Gmane-NNTP-Posting-Host: 197.87.30.233 User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:17.0) Gecko/20130509 Thunderbird/17.0.6 In-Reply-To: <519a4b6a$0$29997$c3e8da3$5496439d@news.astraweb.com> X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 64 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1369117820 news.xs4all.nl 15863 [2001:888:2000:d::a6]:42762 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:45645 On 20/05/2013 18:12, Steven D'Aprano wrote: > On Mon, 20 May 2013 15:26:02 +0200, Frank Millman wrote: > >> Can anyone see anything wrong with the following approach. I have not >> definitely decided to do it this way, but I have been experimenting and >> it seems to work. >> [...] > > It seems safe to me too, but then any fool can come up with a system > which they themselves cannot break :-) > Thanks for the detailed response. > I think the real worry is validating the column name. That will be > critical. I would not pass the actual column name to eval(), I would use it to retrieve a value from a data object and pass that to eval(). However, then your point becomes 'validating the value retrieved'. I had not thought about that. I will investigate further. > Personally, I would strongly suggest writing your own mini- > evaluator that walks the list and evaluates it by hand. It isn't as > convenient as just calling eval, but *definitely* safer. > I am not sure I can wrap my mind around mixed 'and's, 'or's, and brackets. [Thinking aloud] Maybe I can manually reduce each internal test to a True or False, substitute them in the list, and then call eval() on the result. eval('(True and False) or (False or True)') I will experiment with that. > If you do call eval, make sure you supply the globals and locals > arguments. The usual way is: > > eval(expression, {'__builtins__': None}, {}) > > which gives you an empty locals() and a minimal, (mostly) safe globals. > Thanks - I did not know about that. > Finally, as a "belt-and-braces" approach, I wouldn't even call eval > directly, but call a thin wrapper that raises an exception if the > expression contains an underscore. Underscores are usually the key to > breaking eval, so refusing to evaluate anything with an underscore raises > the barrier very high. > > And even with all those defences, I wouldn't allow untrusted data from > the Internet anywhere near this. Just because I can't break it, doesn't > mean it's safe. > All good advice - much appreciated. Frank