diff options
| author | monster <[email protected]> | 2022-07-07 14:41:37 +0300 | 
|---|---|---|
| committer | monster <[email protected]> | 2022-07-07 14:41:37 +0300 | 
| commit | 06e5c21a835c0e923506c4ff27929f34e00761c2 (patch) | |
| tree | 75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/python/Jinja2/py3/jinja2/sandbox.py | |
| parent | 03f024c4412e3aa613bb543cf1660176320ba8f4 (diff) | |
fix ya.make
Diffstat (limited to 'contrib/python/Jinja2/py3/jinja2/sandbox.py')
| -rw-r--r-- | contrib/python/Jinja2/py3/jinja2/sandbox.py | 428 | 
1 files changed, 0 insertions, 428 deletions
diff --git a/contrib/python/Jinja2/py3/jinja2/sandbox.py b/contrib/python/Jinja2/py3/jinja2/sandbox.py deleted file mode 100644 index 42948847769..00000000000 --- a/contrib/python/Jinja2/py3/jinja2/sandbox.py +++ /dev/null @@ -1,428 +0,0 @@ -"""A sandbox layer that ensures unsafe operations cannot be performed. -Useful when the template itself comes from an untrusted source. -""" -import operator -import types -import typing as t -from _string import formatter_field_name_split  # type: ignore -from collections import abc -from collections import deque -from string import Formatter - -from markupsafe import EscapeFormatter -from markupsafe import Markup - -from .environment import Environment -from .exceptions import SecurityError -from .runtime import Context -from .runtime import Undefined - -F = t.TypeVar("F", bound=t.Callable[..., t.Any]) - -#: maximum number of items a range may produce -MAX_RANGE = 100000 - -#: Unsafe function attributes. -UNSAFE_FUNCTION_ATTRIBUTES: t.Set[str] = set() - -#: Unsafe method attributes. Function attributes are unsafe for methods too. -UNSAFE_METHOD_ATTRIBUTES: t.Set[str] = set() - -#: unsafe generator attributes. -UNSAFE_GENERATOR_ATTRIBUTES = {"gi_frame", "gi_code"} - -#: unsafe attributes on coroutines -UNSAFE_COROUTINE_ATTRIBUTES = {"cr_frame", "cr_code"} - -#: unsafe attributes on async generators -UNSAFE_ASYNC_GENERATOR_ATTRIBUTES = {"ag_code", "ag_frame"} - -_mutable_spec: t.Tuple[t.Tuple[t.Type, t.FrozenSet[str]], ...] = ( -    ( -        abc.MutableSet, -        frozenset( -            [ -                "add", -                "clear", -                "difference_update", -                "discard", -                "pop", -                "remove", -                "symmetric_difference_update", -                "update", -            ] -        ), -    ), -    ( -        abc.MutableMapping, -        frozenset(["clear", "pop", "popitem", "setdefault", "update"]), -    ), -    ( -        abc.MutableSequence, -        frozenset(["append", "reverse", "insert", "sort", "extend", "remove"]), -    ), -    ( -        deque, -        frozenset( -            [ -                "append", -                "appendleft", -                "clear", -                "extend", -                "extendleft", -                "pop", -                "popleft", -                "remove", -                "rotate", -            ] -        ), -    ), -) - - -def inspect_format_method(callable: t.Callable) -> t.Optional[str]: -    if not isinstance( -        callable, (types.MethodType, types.BuiltinMethodType) -    ) or callable.__name__ not in ("format", "format_map"): -        return None - -    obj = callable.__self__ - -    if isinstance(obj, str): -        return obj - -    return None - - -def safe_range(*args: int) -> range: -    """A range that can't generate ranges with a length of more than -    MAX_RANGE items. -    """ -    rng = range(*args) - -    if len(rng) > MAX_RANGE: -        raise OverflowError( -            "Range too big. The sandbox blocks ranges larger than" -            f" MAX_RANGE ({MAX_RANGE})." -        ) - -    return rng - - -def unsafe(f: F) -> F: -    """Marks a function or method as unsafe. - -    .. code-block: python - -        @unsafe -        def delete(self): -            pass -    """ -    f.unsafe_callable = True  # type: ignore -    return f - - -def is_internal_attribute(obj: t.Any, attr: str) -> bool: -    """Test if the attribute given is an internal python attribute.  For -    example this function returns `True` for the `func_code` attribute of -    python objects.  This is useful if the environment method -    :meth:`~SandboxedEnvironment.is_safe_attribute` is overridden. - -    >>> from jinja2.sandbox import is_internal_attribute -    >>> is_internal_attribute(str, "mro") -    True -    >>> is_internal_attribute(str, "upper") -    False -    """ -    if isinstance(obj, types.FunctionType): -        if attr in UNSAFE_FUNCTION_ATTRIBUTES: -            return True -    elif isinstance(obj, types.MethodType): -        if attr in UNSAFE_FUNCTION_ATTRIBUTES or attr in UNSAFE_METHOD_ATTRIBUTES: -            return True -    elif isinstance(obj, type): -        if attr == "mro": -            return True -    elif isinstance(obj, (types.CodeType, types.TracebackType, types.FrameType)): -        return True -    elif isinstance(obj, types.GeneratorType): -        if attr in UNSAFE_GENERATOR_ATTRIBUTES: -            return True -    elif hasattr(types, "CoroutineType") and isinstance(obj, types.CoroutineType): -        if attr in UNSAFE_COROUTINE_ATTRIBUTES: -            return True -    elif hasattr(types, "AsyncGeneratorType") and isinstance( -        obj, types.AsyncGeneratorType -    ): -        if attr in UNSAFE_ASYNC_GENERATOR_ATTRIBUTES: -            return True -    return attr.startswith("__") - - -def modifies_known_mutable(obj: t.Any, attr: str) -> bool: -    """This function checks if an attribute on a builtin mutable object -    (list, dict, set or deque) or the corresponding ABCs would modify it -    if called. - -    >>> modifies_known_mutable({}, "clear") -    True -    >>> modifies_known_mutable({}, "keys") -    False -    >>> modifies_known_mutable([], "append") -    True -    >>> modifies_known_mutable([], "index") -    False - -    If called with an unsupported object, ``False`` is returned. - -    >>> modifies_known_mutable("foo", "upper") -    False -    """ -    for typespec, unsafe in _mutable_spec: -        if isinstance(obj, typespec): -            return attr in unsafe -    return False - - -class SandboxedEnvironment(Environment): -    """The sandboxed environment.  It works like the regular environment but -    tells the compiler to generate sandboxed code.  Additionally subclasses of -    this environment may override the methods that tell the runtime what -    attributes or functions are safe to access. - -    If the template tries to access insecure code a :exc:`SecurityError` is -    raised.  However also other exceptions may occur during the rendering so -    the caller has to ensure that all exceptions are caught. -    """ - -    sandboxed = True - -    #: default callback table for the binary operators.  A copy of this is -    #: available on each instance of a sandboxed environment as -    #: :attr:`binop_table` -    default_binop_table: t.Dict[str, t.Callable[[t.Any, t.Any], t.Any]] = { -        "+": operator.add, -        "-": operator.sub, -        "*": operator.mul, -        "/": operator.truediv, -        "//": operator.floordiv, -        "**": operator.pow, -        "%": operator.mod, -    } - -    #: default callback table for the unary operators.  A copy of this is -    #: available on each instance of a sandboxed environment as -    #: :attr:`unop_table` -    default_unop_table: t.Dict[str, t.Callable[[t.Any], t.Any]] = { -        "+": operator.pos, -        "-": operator.neg, -    } - -    #: a set of binary operators that should be intercepted.  Each operator -    #: that is added to this set (empty by default) is delegated to the -    #: :meth:`call_binop` method that will perform the operator.  The default -    #: operator callback is specified by :attr:`binop_table`. -    #: -    #: The following binary operators are interceptable: -    #: ``//``, ``%``, ``+``, ``*``, ``-``, ``/``, and ``**`` -    #: -    #: The default operation form the operator table corresponds to the -    #: builtin function.  Intercepted calls are always slower than the native -    #: operator call, so make sure only to intercept the ones you are -    #: interested in. -    #: -    #: .. versionadded:: 2.6 -    intercepted_binops: t.FrozenSet[str] = frozenset() - -    #: a set of unary operators that should be intercepted.  Each operator -    #: that is added to this set (empty by default) is delegated to the -    #: :meth:`call_unop` method that will perform the operator.  The default -    #: operator callback is specified by :attr:`unop_table`. -    #: -    #: The following unary operators are interceptable: ``+``, ``-`` -    #: -    #: The default operation form the operator table corresponds to the -    #: builtin function.  Intercepted calls are always slower than the native -    #: operator call, so make sure only to intercept the ones you are -    #: interested in. -    #: -    #: .. versionadded:: 2.6 -    intercepted_unops: t.FrozenSet[str] = frozenset() - -    def __init__(self, *args: t.Any, **kwargs: t.Any) -> None: -        super().__init__(*args, **kwargs) -        self.globals["range"] = safe_range -        self.binop_table = self.default_binop_table.copy() -        self.unop_table = self.default_unop_table.copy() - -    def is_safe_attribute(self, obj: t.Any, attr: str, value: t.Any) -> bool: -        """The sandboxed environment will call this method to check if the -        attribute of an object is safe to access.  Per default all attributes -        starting with an underscore are considered private as well as the -        special attributes of internal python objects as returned by the -        :func:`is_internal_attribute` function. -        """ -        return not (attr.startswith("_") or is_internal_attribute(obj, attr)) - -    def is_safe_callable(self, obj: t.Any) -> bool: -        """Check if an object is safely callable. By default callables -        are considered safe unless decorated with :func:`unsafe`. - -        This also recognizes the Django convention of setting -        ``func.alters_data = True``. -        """ -        return not ( -            getattr(obj, "unsafe_callable", False) or getattr(obj, "alters_data", False) -        ) - -    def call_binop( -        self, context: Context, operator: str, left: t.Any, right: t.Any -    ) -> t.Any: -        """For intercepted binary operator calls (:meth:`intercepted_binops`) -        this function is executed instead of the builtin operator.  This can -        be used to fine tune the behavior of certain operators. - -        .. versionadded:: 2.6 -        """ -        return self.binop_table[operator](left, right) - -    def call_unop(self, context: Context, operator: str, arg: t.Any) -> t.Any: -        """For intercepted unary operator calls (:meth:`intercepted_unops`) -        this function is executed instead of the builtin operator.  This can -        be used to fine tune the behavior of certain operators. - -        .. versionadded:: 2.6 -        """ -        return self.unop_table[operator](arg) - -    def getitem( -        self, obj: t.Any, argument: t.Union[str, t.Any] -    ) -> t.Union[t.Any, Undefined]: -        """Subscribe an object from sandboxed code.""" -        try: -            return obj[argument] -        except (TypeError, LookupError): -            if isinstance(argument, str): -                try: -                    attr = str(argument) -                except Exception: -                    pass -                else: -                    try: -                        value = getattr(obj, attr) -                    except AttributeError: -                        pass -                    else: -                        if self.is_safe_attribute(obj, argument, value): -                            return value -                        return self.unsafe_undefined(obj, argument) -        return self.undefined(obj=obj, name=argument) - -    def getattr(self, obj: t.Any, attribute: str) -> t.Union[t.Any, Undefined]: -        """Subscribe an object from sandboxed code and prefer the -        attribute.  The attribute passed *must* be a bytestring. -        """ -        try: -            value = getattr(obj, attribute) -        except AttributeError: -            try: -                return obj[attribute] -            except (TypeError, LookupError): -                pass -        else: -            if self.is_safe_attribute(obj, attribute, value): -                return value -            return self.unsafe_undefined(obj, attribute) -        return self.undefined(obj=obj, name=attribute) - -    def unsafe_undefined(self, obj: t.Any, attribute: str) -> Undefined: -        """Return an undefined object for unsafe attributes.""" -        return self.undefined( -            f"access to attribute {attribute!r} of" -            f" {type(obj).__name__!r} object is unsafe.", -            name=attribute, -            obj=obj, -            exc=SecurityError, -        ) - -    def format_string( -        self, -        s: str, -        args: t.Tuple[t.Any, ...], -        kwargs: t.Dict[str, t.Any], -        format_func: t.Optional[t.Callable] = None, -    ) -> str: -        """If a format call is detected, then this is routed through this -        method so that our safety sandbox can be used for it. -        """ -        formatter: SandboxedFormatter -        if isinstance(s, Markup): -            formatter = SandboxedEscapeFormatter(self, escape=s.escape) -        else: -            formatter = SandboxedFormatter(self) - -        if format_func is not None and format_func.__name__ == "format_map": -            if len(args) != 1 or kwargs: -                raise TypeError( -                    "format_map() takes exactly one argument" -                    f" {len(args) + (kwargs is not None)} given" -                ) - -            kwargs = args[0] -            args = () - -        rv = formatter.vformat(s, args, kwargs) -        return type(s)(rv) - -    def call( -        __self,  # noqa: B902 -        __context: Context, -        __obj: t.Any, -        *args: t.Any, -        **kwargs: t.Any, -    ) -> t.Any: -        """Call an object from sandboxed code.""" -        fmt = inspect_format_method(__obj) -        if fmt is not None: -            return __self.format_string(fmt, args, kwargs, __obj) - -        # the double prefixes are to avoid double keyword argument -        # errors when proxying the call. -        if not __self.is_safe_callable(__obj): -            raise SecurityError(f"{__obj!r} is not safely callable") -        return __context.call(__obj, *args, **kwargs) - - -class ImmutableSandboxedEnvironment(SandboxedEnvironment): -    """Works exactly like the regular `SandboxedEnvironment` but does not -    permit modifications on the builtin mutable objects `list`, `set`, and -    `dict` by using the :func:`modifies_known_mutable` function. -    """ - -    def is_safe_attribute(self, obj: t.Any, attr: str, value: t.Any) -> bool: -        if not super().is_safe_attribute(obj, attr, value): -            return False - -        return not modifies_known_mutable(obj, attr) - - -class SandboxedFormatter(Formatter): -    def __init__(self, env: Environment, **kwargs: t.Any) -> None: -        self._env = env -        super().__init__(**kwargs)  # type: ignore - -    def get_field( -        self, field_name: str, args: t.Sequence[t.Any], kwargs: t.Mapping[str, t.Any] -    ) -> t.Tuple[t.Any, str]: -        first, rest = formatter_field_name_split(field_name) -        obj = self.get_value(first, args, kwargs) -        for is_attr, i in rest: -            if is_attr: -                obj = self._env.getattr(obj, i) -            else: -                obj = self._env.getitem(obj, i) -        return obj, first - - -class SandboxedEscapeFormatter(SandboxedFormatter, EscapeFormatter): -    pass  | 
