2016-07-15 31 views
2

Ich versuche Pythons (2.7) eval in einer (relativ) sicheren Weise zu verwenden. Daher I definiert:Ist keine wirklich eingebaut?

def safer_eval(string): 
    """Safer version of eval() as globals and builtins are inaccessible""" 
    return eval(string, {'__builtins__': {}}) 

Wie erwartet, die folgenden nicht mehr funktioniert:

print safer_eval("True") 
NameError: name 'True' is not defined 

Allerdings kann ich eval noch einen "None" string:

print safer_eval("None") 
None 
  • Also, ist None kein eingebauter? Sie sind mindestens beide Teil von __builtin__ ...

  • Warum ist es noch eval-fähig?

  • Wie würde ich es loswerden, wenn ich müsste?
+4

Warum nicht einfach 'ast.literal_eval' verwenden? – jonrsharpe

+0

Welche Python-Version? – Ares

+0

Ja, 'None' ist ein eingebautes Singleton-Objekt und ein * Schlüsselwort *. –

Antwort

9

None ist eine Konstante in Python finden Sie in der Keywords documentation:

in Version geändert 2.4: None eine Konstante wurde und nun durch den Compiler als Name für die eingebauten Objekt None erkannt wird. Obwohl es kein Schlüsselwort ist, können Sie ihm kein anderes Objekt zuweisen.

Der Compiler fügt einfach einen Verweis auf das Singleton None Objekt, wann immer Sie es nennen:

>>> from dis import dis 
>>> dis(compile('None', '', 'eval')) 
    1   0 LOAD_CONST    0 (None) 
       3 RETURN_VALUE 

True und False sind Einbauten in Python 2, was auch bedeutet, dass sie maskiert werden.

In Python 3, None, True und False alle sind now keywords, und alle drei sind lediglich durch die Benennung sie materialisiert:

>>> eval('True', {'__builtins__': {}}) 
True 

Guido van Rossum's blog post on why this was changed See.

Beachten Sie, dass es nichts sicher über eval ist, auch mit __builtins__ kastriert, da sie noch über andere Mittel verwiesen werden kann:

>>> s = ''' 
... [ 
...  c for c in().__class__.__base__.__subclasses__() 
...  if c.__name__ == 'catch_warnings' 
... ][0]()._module.__builtins__ 
... ''' 
>>> eval(s, {'__builtins__': {}}) 
{'bytearray': <type 'bytearray'>, 'IndexError': <type 'exceptions.IndexError'>, 'all': <built-in function all>, 'help': Type help() for interactive help, or help(object) for help about object., 'vars': <built-in function vars>, 'SyntaxError': <type 'exceptions.SyntaxError'>, 'unicode': <type 'unicode'>, 'UnicodeDecodeError': <type 'exceptions.UnicodeDecodeError'>, 'memoryview': <type 'memoryview'>, 'isinstance': <built-in function isinstance>, 'copyright': Copyright (c) 2001-2015 Python Software Foundation. 
All Rights Reserved. 

Copyright (c) 2000 BeOpen.com. 
All Rights Reserved. 

Copyright (c) 1995-2001 Corporation for National Research Initiatives. 
All Rights Reserved. 

Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam. 
All Rights Reserved., 'NameError': <type 'exceptions.NameError'>, 'BytesWarning': <type 'exceptions.BytesWarning'>, 'dict': <type 'dict'>, 'input': <built-in function input>, 'oct': <built-in function oct>, 'bin': <built-in function bin>, 'SystemExit': <type 'exceptions.SystemExit'>, 'StandardError': <type 'exceptions.StandardError'>, 'format': <built-in function format>, 'repr': <built-in function repr>, 'sorted': <built-in function sorted>, 'False': False, 'RuntimeWarning': <type 'exceptions.RuntimeWarning'>, 'list': <type 'list'>, 'iter': <built-in function iter>, 'reload': <built-in function reload>, 'Warning': <type 'exceptions.Warning'>, '__package__': None, 'round': <built-in function round>, 'dir': <built-in function dir>, 'cmp': <built-in function cmp>, 'set': <type 'set'>, 'bytes': <type 'str'>, 'reduce': <built-in function reduce>, 'intern': <built-in function intern>, 'issubclass': <built-in function issubclass>, 'Ellipsis': Ellipsis, 'EOFError': <type 'exceptions.EOFError'>, 'locals': <built-in function locals>, 'BufferError': <type 'exceptions.BufferError'>, 'slice': <type 'slice'>, 'FloatingPointError': <type 'exceptions.FloatingPointError'>, 'sum': <built-in function sum>, 'getattr': <built-in function getattr>, 'abs': <built-in function abs>, 'exit': Use exit() or Ctrl-D (i.e. EOF) to exit, 'print': <built-in function print>, 'True': True, 'FutureWarning': <type 'exceptions.FutureWarning'>, 'ImportWarning': <type 'exceptions.ImportWarning'>, 'None': None, 'hash': <built-in function hash>, 'ReferenceError': <type 'exceptions.ReferenceError'>, 'len': <built-in function len>, 'credits':  Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands 
    for supporting Python development. See www.python.org for more information., 'frozenset': <type 'frozenset'>, '__name__': '__builtin__', 'ord': <built-in function ord>, 'super': <type 'super'>, '_': None, 'TypeError': <type 'exceptions.TypeError'>, 'license': See http://www.python.org/2.7/license.html, 'KeyboardInterrupt': <type 'exceptions.KeyboardInterrupt'>, 'UserWarning': <type 'exceptions.UserWarning'>, 'filter': <built-in function filter>, 'range': <built-in function range>, 'staticmethod': <type 'staticmethod'>, 'SystemError': <type 'exceptions.SystemError'>, 'BaseException': <type 'exceptions.BaseException'>, 'pow': <built-in function pow>, 'RuntimeError': <type 'exceptions.RuntimeError'>, 'float': <type 'float'>, 'MemoryError': <type 'exceptions.MemoryError'>, 'StopIteration': <type 'exceptions.StopIteration'>, 'globals': <built-in function globals>, 'divmod': <built-in function divmod>, 'enumerate': <type 'enumerate'>, 'apply': <built-in function apply>, 'LookupError': <type 'exceptions.LookupError'>, 'open': <built-in function open>, 'quit': Use quit() or Ctrl-D (i.e. EOF) to exit, 'basestring': <type 'basestring'>, 'UnicodeError': <type 'exceptions.UnicodeError'>, 'zip': <built-in function zip>, 'hex': <built-in function hex>, 'long': <type 'long'>, 'next': <built-in function next>, 'ImportError': <type 'exceptions.ImportError'>, 'chr': <built-in function chr>, 'xrange': <type 'xrange'>, 'type': <type 'type'>, '__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.", 'Exception': <type 'exceptions.Exception'>, 'tuple': <type 'tuple'>, 'UnicodeTranslateError': <type 'exceptions.UnicodeTranslateError'>, 'reversed': <type 'reversed'>, 'UnicodeEncodeError': <type 'exceptions.UnicodeEncodeError'>, 'IOError': <type 'exceptions.IOError'>, 'hasattr': <built-in function hasattr>, 'delattr': <built-in function delattr>, 'setattr': <built-in function setattr>, 'raw_input': <built-in function raw_input>, 'SyntaxWarning': <type 'exceptions.SyntaxWarning'>, 'compile': <built-in function compile>, 'ArithmeticError': <type 'exceptions.ArithmeticError'>, 'str': <type 'str'>, 'property': <type 'property'>, 'GeneratorExit': <type 'exceptions.GeneratorExit'>, 'int': <type 'int'>, '__import__': <built-in function __import__>, 'KeyError': <type 'exceptions.KeyError'>, 'coerce': <built-in function coerce>, 'PendingDeprecationWarning': <type 'exceptions.PendingDeprecationWarning'>, 'file': <type 'file'>, 'EnvironmentError': <type 'exceptions.EnvironmentError'>, 'unichr': <built-in function unichr>, 'id': <built-in function id>, 'OSError': <type 'exceptions.OSError'>, 'DeprecationWarning': <type 'exceptions.DeprecationWarning'>, 'min': <built-in function min>, 'UnicodeWarning': <type 'exceptions.UnicodeWarning'>, 'execfile': <built-in function execfile>, 'any': <built-in function any>, 'complex': <type 'complex'>, 'bool': <type 'bool'>, 'ValueError': <type 'exceptions.ValueError'>, 'NotImplemented': NotImplemented, 'map': <built-in function map>, 'buffer': <type 'buffer'>, 'max': <built-in function max>, 'object': <type 'object'>, 'TabError': <type 'exceptions.TabError'>, 'callable': <built-in function callable>, 'ZeroDivisionError': <type 'exceptions.ZeroDivisionError'>, 'eval': <built-in function eval>, '__debug__': True, 'IndentationError': <type 'exceptions.IndentationError'>, 'AssertionError': <type 'exceptions.AssertionError'>, 'classmethod': <type 'classmethod'>, 'UnboundLocalError': <type 'exceptions.UnboundLocalError'>, 'NotImplementedError': <type 'exceptions.NotImplementedError'>, 'AttributeError': <type 'exceptions.AttributeError'>, 'OverflowError': <type 'exceptions.OverflowError'>} 

oder Sie können einfach den Interpreter sprengen durch einen gebrochenen Code zu schaffen Objekt. Siehe Eval really is dangerous.

Wenn Sie nur die Python-Literalsyntax laden möchten (Listen, Tupel, Wörterbücher, Strings, Zahlen usw.), dann möchten Sie die ast.literal_eval() function verwenden, die speziell dafür entwickelt wurde, sicher zu sein.

+0

Vielleicht möchten Sie "ast.literal_eval" erwähnen und auf diese Frage verlinken: http://stackoverflow.com/questions/4710247/python-3-are-there-any-known-security-holes-in-ast-literal -evalnode-oder-string? Es scheint eine wahrscheinliche Folgefrage zu sein ... – NichtJens

+0

@NichtJens: fügte eine Erwähnung hinzu; Ich glaube nicht, dass diese Frage verlinkt werden muss, die Dokumentation reicht: * Sicher auswerten ... * –

+0

Ja, super! Sie beantworten diese Nachfolgefrage eigentlich schon hier ;-) – NichtJens

1

In Python 2.7 ist dies eine absolut gültige Aussage.

True = False 
>>> print True 
False 

Versuchen Sie es mit None obwohl zu tun, und ..

SyntaxError: cannot assign to None

Art kann Ihren Kopf drehen. Ich bin mir nicht sicher, aber ich vermute, dass True ist ein eingebauter und None ist eigentlich eine Konstante. Sie können ändernTrue auf einen anderen Wert, aber Sie können None nicht ändern.

+0

Nein, True und False sind die eingebauten und können maskiert werden. –

+0

Also sind sie alle eingebaut? Was ist der Unterschied dann? EDIT: Ah, ich sehe, 'None' ist auch ein Schlüsselwort. – Ares

+0

Ich bin mir nicht sicher, dass es technisch auch ein Schlüsselwort ist (zumindest nicht in python2.x): 'Schlüsselwort importieren; print keyword.iskeyword ('None') ' – mgilson