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)