NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

sandbox.py (6033B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\jinja2\sandbox.py
      2 import operator
      3 from jinja2.environment import Environment
      4 from jinja2.exceptions import SecurityError
      5 from jinja2.utils import FunctionType, MethodType, TracebackType, CodeType, FrameType, GeneratorType
      6 MAX_RANGE = 100000
      7 UNSAFE_FUNCTION_ATTRIBUTES = set(['func_closure',
      8  'func_code',
      9  'func_dict',
     10  'func_defaults',
     11  'func_globals'])
     12 UNSAFE_METHOD_ATTRIBUTES = set(['im_class', 'im_func', 'im_self'])
     13 import warnings
     14 warnings.filterwarnings('ignore', 'the sets module', DeprecationWarning, module='jinja2.sandbox')
     15 from collections import deque
     16 _mutable_set_types = (set,)
     17 _mutable_mapping_types = (dict,)
     18 _mutable_sequence_types = (list,)
     19 try:
     20     from UserDict import UserDict, DictMixin
     21     from UserList import UserList
     22     _mutable_mapping_types += (UserDict, DictMixin)
     23     _mutable_set_types += (UserList,)
     24 except ImportError:
     25     pass
     26 
     27 try:
     28     from sets import Set
     29     _mutable_set_types += (Set,)
     30 except ImportError:
     31     pass
     32 
     33 try:
     34     from collections import MutableSet, MutableMapping, MutableSequence
     35     _mutable_set_types += (MutableSet,)
     36     _mutable_mapping_types += (MutableMapping,)
     37     _mutable_sequence_types += (MutableSequence,)
     38 except ImportError:
     39     pass
     40 
     41 _mutable_spec = ((_mutable_set_types, frozenset(['add',
     42    'clear',
     43    'difference_update',
     44    'discard',
     45    'pop',
     46    'remove',
     47    'symmetric_difference_update',
     48    'update'])),
     49  (_mutable_mapping_types, frozenset(['clear',
     50    'pop',
     51    'popitem',
     52    'setdefault',
     53    'update'])),
     54  (_mutable_sequence_types, frozenset(['append',
     55    'reverse',
     56    'insert',
     57    'sort',
     58    'extend',
     59    'remove'])),
     60  (deque, frozenset(['append',
     61    'appendleft',
     62    'clear',
     63    'extend',
     64    'extendleft',
     65    'pop',
     66    'popleft',
     67    'remove',
     68    'rotate'])))
     69 
     70 def safe_range(*args):
     71     rng = xrange(*args)
     72     if len(rng) > MAX_RANGE:
     73         raise OverflowError('range too big, maximum size for range is %d' % MAX_RANGE)
     74     return rng
     75 
     76 
     77 def unsafe(f):
     78     f.unsafe_callable = True
     79     return f
     80 
     81 
     82 def is_internal_attribute(obj, attr):
     83     if isinstance(obj, FunctionType):
     84         if attr in UNSAFE_FUNCTION_ATTRIBUTES:
     85             return True
     86     elif isinstance(obj, MethodType):
     87         if attr in UNSAFE_FUNCTION_ATTRIBUTES or attr in UNSAFE_METHOD_ATTRIBUTES:
     88             return True
     89     elif isinstance(obj, type):
     90         if attr == 'mro':
     91             return True
     92     else:
     93         if isinstance(obj, (CodeType, TracebackType, FrameType)):
     94             return True
     95         if isinstance(obj, GeneratorType):
     96             if attr == 'gi_frame':
     97                 return True
     98     return attr.startswith('__')
     99 
    100 
    101 def modifies_known_mutable(obj, attr):
    102     for typespec, unsafe in _mutable_spec:
    103         if isinstance(obj, typespec):
    104             return attr in unsafe
    105 
    106     return False
    107 
    108 
    109 class SandboxedEnvironment(Environment):
    110     sandboxed = True
    111     default_binop_table = {'+': operator.add,
    112      '-': operator.sub,
    113      '*': operator.mul,
    114      '/': operator.truediv,
    115      '//': operator.floordiv,
    116      '**': operator.pow,
    117      '%': operator.mod}
    118     default_unop_table = {'+': operator.pos,
    119      '-': operator.neg}
    120     intercepted_binops = frozenset()
    121     intercepted_unops = frozenset()
    122 
    123     def intercept_unop(self, operator):
    124         return False
    125 
    126     def __init__(self, *args, **kwargs):
    127         Environment.__init__(self, *args, **kwargs)
    128         self.globals['range'] = safe_range
    129         self.binop_table = self.default_binop_table.copy()
    130         self.unop_table = self.default_unop_table.copy()
    131 
    132     def is_safe_attribute(self, obj, attr, value):
    133         return not (attr.startswith('_') or is_internal_attribute(obj, attr))
    134 
    135     def is_safe_callable(self, obj):
    136         return not (getattr(obj, 'unsafe_callable', False) or getattr(obj, 'alters_data', False))
    137 
    138     def call_binop(self, context, operator, left, right):
    139         return self.binop_table[operator](left, right)
    140 
    141     def call_unop(self, context, operator, arg):
    142         return self.unop_table[operator](arg)
    143 
    144     def getitem(self, obj, argument):
    145         try:
    146             return obj[argument]
    147         except (TypeError, LookupError):
    148             if isinstance(argument, basestring):
    149                 try:
    150                     attr = str(argument)
    151                 except Exception:
    152                     pass
    153                 else:
    154                     try:
    155                         value = getattr(obj, attr)
    156                     except AttributeError:
    157                         pass
    158                     else:
    159                         if self.is_safe_attribute(obj, argument, value):
    160                             return value
    161                         return self.unsafe_undefined(obj, argument)
    162 
    163         return self.undefined(obj=obj, name=argument)
    164 
    165     def getattr(self, obj, attribute):
    166         try:
    167             value = getattr(obj, attribute)
    168         except AttributeError:
    169             try:
    170                 return obj[attribute]
    171             except (TypeError, LookupError):
    172                 pass
    173 
    174         else:
    175             if self.is_safe_attribute(obj, attribute, value):
    176                 return value
    177             return self.unsafe_undefined(obj, attribute)
    178 
    179         return self.undefined(obj=obj, name=attribute)
    180 
    181     def unsafe_undefined(self, obj, attribute):
    182         return self.undefined('access to attribute %r of %r object is unsafe.' % (attribute, obj.__class__.__name__), name=attribute, obj=obj, exc=SecurityError)
    183 
    184     def call(_SandboxedEnvironment__self, _SandboxedEnvironment__context, _SandboxedEnvironment__obj, *args, **kwargs):
    185         if not __self.is_safe_callable(__obj):
    186             raise SecurityError('%r is not safely callable' % (__obj,))
    187         return __context.call(__obj, *args, **kwargs)
    188 
    189 
    190 class ImmutableSandboxedEnvironment(SandboxedEnvironment):
    191 
    192     def is_safe_attribute(self, obj, attr, value):
    193         if not SandboxedEnvironment.is_safe_attribute(self, obj, attr, value):
    194             return False
    195         return not modifies_known_mutable(obj, attr)