Commits

Benjamin Peterson  committed ffa26bf

remove taint objspace

  • Participants
  • Parent commits 22f84e5

Comments (0)

Files changed (8)

File pypy/config/pypyoption.py

 
 pypy_optiondescription = OptionDescription("objspace", "Object Space Options", [
     ChoiceOption("name", "Object Space name",
-                 ["std", "flow", "thunk", "dump", "taint"],
+                 ["std", "flow", "thunk", "dump"],
                  "std",
                  cmdline='--objspace -o'),
 

File pypy/doc/__pypy__-module.rst

 .. _`thunk object space docs`: objspace-proxies.html#thunk
 .. _`interface section of the thunk object space docs`: objspace-proxies.html#thunk-interface
 
-.. broken:
-
-    Taint Object Space Functionality
-    ================================
-
-    When the taint object space is used (choose with :config:`objspace.name`),
-    the following names are put into ``__pypy__``:
-
-     - ``taint``
-     - ``is_tainted``
-     - ``untaint``
-     - ``taint_atomic``
-     - ``_taint_debug``
-     - ``_taint_look``
-     - ``TaintError``
-
-    Those are all described in the `interface section of the taint object space
-    docs`_.
-
-    For more detailed explanations and examples see the `taint object space docs`_.
-
-    .. _`taint object space docs`: objspace-proxies.html#taint
-    .. _`interface section of the taint object space docs`: objspace-proxies.html#taint-interface
 
 Transparent Proxy Functionality
 ===============================

File pypy/doc/config/objspace.name.txt

 for normal usage):
 
   * thunk_: The thunk object space adds lazy evaluation to PyPy.
-  * taint_: The taint object space adds soft security features.
   * dump_:  Using this object spaces results in the dumpimp of all operations
     to a log.
 
 .. _`Object Space Proxies`: ../objspace-proxies.html
 .. _`Standard Object Space`: ../objspace.html#standard-object-space
 .. _thunk: ../objspace-proxies.html#thunk
-.. _taint: ../objspace-proxies.html#taint
 .. _dump: ../objspace-proxies.html#dump

File pypy/doc/index.rst

 .. _`object space`: objspace.html
 .. _FlowObjSpace: objspace.html#the-flow-object-space 
 .. _`trace object space`: objspace.html#the-trace-object-space 
-.. _`taint object space`: objspace-proxies.html#taint
 .. _`thunk object space`: objspace-proxies.html#thunk
 .. _`transparent proxies`: objspace-proxies.html#tproxy
 .. _`Differences between PyPy and CPython`: cpython_differences.html

File pypy/doc/objspace-proxies.rst

    function behaves lazily: all calls to it return a thunk object.
 
 
-.. broken right now:
-
-    .. _taint:
-
-    The Taint Object Space
-    ======================
-
-    Motivation
-    ----------
-
-    The Taint Object Space provides a form of security: "tainted objects",
-    inspired by various sources, see [D12.1]_ for a more detailed discussion. 
-
-    The basic idea of this kind of security is not to protect against
-    malicious code but to help with handling and boxing sensitive data. 
-    It covers two kinds of sensitive data: secret data which should not leak, 
-    and untrusted data coming from an external source and that must be 
-    validated before it is used.
-
-    The idea is that, considering a large application that handles these
-    kinds of sensitive data, there are typically only a small number of
-    places that need to explicitly manipulate that sensitive data; all the
-    other places merely pass it around, or do entirely unrelated things.
-
-    Nevertheless, if a large application needs to be reviewed for security,
-    it must be entirely carefully checked, because it is possible that a
-    bug at some apparently unrelated place could lead to a leak of sensitive
-    information in a way that an external attacker could exploit.  For
-    example, if any part of the application provides web services, an
-    attacker might be able to issue unexpected requests with a regular web
-    browser and deduce secret information from the details of the answers he
-    gets.  Another example is the common CGI attack where an attacker sends
-    malformed inputs and causes the CGI script to do unintended things.
-
-    An approach like that of the Taint Object Space allows the small parts
-    of the program that manipulate sensitive data to be explicitly marked.
-    The effect of this is that although these small parts still need a
-    careful security review, the rest of the application no longer does,
-    because even a bug would be unable to leak the information.
-
-    We have implemented a simple two-level model: objects are either
-    regular (untainted), or sensitive (tainted).  Objects are marked as
-    sensitive if they are secret or untrusted, and only declassified at
-    carefully-checked positions (e.g. where the secret data is needed, or
-    after the untrusted data has been fully validated).
-
-    It would be simple to extend the code for more fine-grained scales of
-    secrecy.  For example it is typical in the literature to consider
-    user-specified lattices of secrecy levels, corresponding to multiple
-    "owners" that cannot access data belonging to another "owner" unless
-    explicitly authorized to do so.
-
-    Tainting and untainting
-    -----------------------
-
-    Start a py.py with the Taint Object Space and try the following example::
-
-        $ py.py -o taint
-        >>>> from __pypy__ import taint
-        >>>> x = taint(6)
-
-        # x is hidden from now on.  We can pass it around and
-        # even operate on it, but not inspect it.  Taintness
-        # is propagated to operation results.
-
-        >>>> x
-        TaintError
-
-        >>>> if x > 5: y = 2   # see below
-        TaintError
-
-        >>>> y = x + 5         # ok
-        >>>> lst = [x, y]
-        >>>> z = lst.pop()
-        >>>> t = type(z)       # type() works too, tainted answer
-        >>>> t
-        TaintError
-        >>>> u = t is int      # even 'is' works
-        >>>> u
-        TaintError
-
-    Notice that using a tainted boolean like ``x > 5`` in an ``if``
-    statement is forbidden.  This is because knowing which path is followed
-    would give away a hint about ``x``; in the example above, if the
-    statement ``if x > 5: y = 2`` was allowed to run, we would know
-    something about the value of ``x`` by looking at the (untainted) value
-    in the variable ``y``.
-
-    Of course, there is a way to inspect tainted objects.  The basic way is
-    to explicitly "declassify" it with the ``untaint()`` function.  In an
-    application, the places that use ``untaint()`` are the places that need
-    careful security review.  To avoid unexpected objects showing up, the
-    ``untaint()`` function must be called with the exact type of the object
-    to declassify.  It will raise ``TaintError`` if the type doesn't match::
-
-        >>>> from __pypy__ import taint
-        >>>> untaint(int, x)
-        6
-        >>>> untaint(int, z)
-        11
-        >>>> untaint(bool, x > 5)
-        True
-        >>>> untaint(int, x > 5)
-        TaintError
-
-
-    Taint Bombs
-    -----------
-
-    In this area, a common problem is what to do about failing operations.
-    If an operation raises an exception when manipulating a tainted object,
-    then the very presence of the exception can leak information about the
-    tainted object itself.  Consider::
-
-        >>>> 5 / (x-6)
-
-    By checking if this raises ``ZeroDivisionError`` or not, we would know
-    if ``x`` was equal to 6 or not.  The solution to this problem in the
-    Taint Object Space is to introduce *Taint Bombs*.  They are a kind of
-    tainted object that doesn't contain a real object, but a pending
-    exception.  Taint Bombs are indistinguishable from normal tainted
-    objects to unprivileged code. See::
-
-        >>>> x = taint(6)
-        >>>> i = 5 / (x-6)     # no exception here
-        >>>> j = i + 1         # nor here
-        >>>> k = j + 5         # nor here
-        >>>> untaint(int, k)
-        TaintError
-
-    In the above example, all of ``i``, ``j`` and ``k`` contain a Taint
-    Bomb.  Trying to untaint it raises an exception - a generic
-    ``TaintError``.  What we win is that the exception gives little away,
-    and most importantly it occurs at the point where ``untaint()`` is
-    called, not where the operation failed.  This means that all calls to
-    ``untaint()`` - but not the rest of the code - must be carefully
-    reviewed for what occurs if they receive a Taint Bomb; they might catch
-    the ``TaintError`` and give the user a generic message that something
-    went wrong, if we are reasonably careful that the message or even its
-    presence doesn't give information away.  This might be a
-    problem by itself, but there is no satisfying general solution here:
-    it must be considered on a case-by-case basis.  Again, what the
-    Taint Object Space approach achieves is not solving these problems, but
-    localizing them to well-defined small parts of the application - namely,
-    around calls to ``untaint()``.
-
-    The ``TaintError`` exception deliberately does not include any
-    useful error messages, because they might give information away.
-    Of course, this makes debugging quite a bit harder; a difficult
-    problem to solve properly.  So far we have implemented a way to peek in a Taint
-    Box or Bomb, ``__pypy__._taint_look(x)``, and a "debug mode" that
-    prints the exception as soon as a Bomb is created - both write
-    information to the low-level stderr of the application, where we hope
-    that it is unlikely to be seen by anyone but the application
-    developer.
-
-
-    Taint Atomic functions
-    ----------------------
-
-    Occasionally, a more complicated computation must be performed on a
-    tainted object.  This requires first untainting the object, performing the
-    computations, and then carefully tainting the result again (including
-    hiding all exceptions into Bombs).
-
-    There is a built-in decorator that does this for you::
-
-        >>>> @__pypy__.taint_atomic
-        >>>> def myop(x, y):
-        ....     while x > 0:
-        ....         x -= y
-        ....     return x
-        ....
-        >>>> myop(42, 10)
-        -8
-        >>>> z = myop(taint(42), 10)
-        >>>> z
-        TaintError
-        >>>> untaint(int, z)
-        -8
-
-    The decorator makes a whole function behave like a built-in operation.
-    If no tainted argument is passed in, the function behaves normally.  But
-    if any of the arguments is tainted, it is automatically untainted - so
-    the function body always sees untainted arguments - and the eventual
-    result is tainted again (possibly in a Taint Bomb).
-
-    It is important for the function marked as ``taint_atomic`` to have no
-    visible side effects, as these could cause information leakage.
-    This is currently not enforced, which means that all ``taint_atomic``
-    functions have to be carefully reviewed for security (but not the
-    callers of ``taint_atomic`` functions).
-
-    A possible future extension would be to forbid side-effects on
-    non-tainted objects from all ``taint_atomic`` functions.
-
-    An example of usage: given a tainted object ``passwords_db`` that
-    references a database of passwords, we can write a function
-    that checks if a password is valid as follows::
-
-        @taint_atomic
-        def validate(passwords_db, username, password):
-            assert type(passwords_db) is PasswordDatabase
-            assert type(username) is str
-            assert type(password) is str
-            ...load username entry from passwords_db...
-            return expected_password == password
-
-    It returns a tainted boolean answer, or a Taint Bomb if something
-    went wrong.  A caller can do::
-
-        ok = validate(passwords_db, 'john', '1234')
-        ok = untaint(bool, ok)
-
-    This can give three outcomes: ``True``, ``False``, or a ``TaintError``
-    exception (with no information on it) if anything went wrong.  If even
-    this is considered giving too much information away, the ``False`` case
-    can be made indistinguishable from the ``TaintError`` case (simply by
-    raising an exception in ``validate()`` if the password is wrong).
-
-    In the above example, the security results achieved are the following:
-    as long as ``validate()`` does not leak information, no other part of
-    the code can obtain more information about a passwords database than a
-    Yes/No answer to a precise query.
-
-    A possible extension of the ``taint_atomic`` decorator would be to check
-    the argument types, as ``untaint()`` does, for the same reason: to
-    prevent bugs where a function like ``validate()`` above is accidentally
-    called with the wrong kind of tainted object, which would make it
-    misbehave.  For now, all ``taint_atomic`` functions should be
-    conservative and carefully check all assumptions on their input
-    arguments.
-
-
-    .. _`taint-interface`:
-
-    Interface
-    ---------
-
-    .. _`like a built-in operation`:
-
-    The basic rule of the Tainted Object Space is that it introduces two new
-    kinds of objects, Tainted Boxes and Tainted Bombs (which are not types
-    in the Python sense).  Each box internally contains a regular object;
-    each bomb internally contains an exception object.  An operation
-    involving Tainted Boxes is performed on the objects contained in the
-    boxes, and gives a Tainted Box or a Tainted Bomb as a result (such an
-    operation does not let an exception be raised).  An operation called
-    with a Tainted Bomb argument immediately returns the same Tainted Bomb.
-
-    In a PyPy running with (or translated with) the Taint Object Space,
-    the ``__pypy__`` module exposes the following interface:
-
-    * ``taint(obj)``
-
-        Return a new Tainted Box wrapping ``obj``.  Return ``obj`` itself
-        if it is already tainted (a Box or a Bomb).
-
-    * ``is_tainted(obj)``
-
-        Check if ``obj`` is tainted (a Box or a Bomb).
-
-    * ``untaint(type, obj)``
-
-        Untaints ``obj`` if it is tainted.  Raise ``TaintError`` if the type
-        of the untainted object is not exactly ``type``, or if ``obj`` is a
-        Bomb.
-
-    * ``taint_atomic(func)``
-
-        Return a wrapper function around the callable ``func``.  The wrapper
-        behaves `like a built-in operation`_ with respect to untainting the
-        arguments, tainting the result, and returning a Bomb.
-
-    * ``TaintError``
-
-        Exception.  On purpose, it provides no attribute or error message.
-
-    * ``_taint_debug(level)``
-
-        Set the debugging level to ``level`` (0=off).  At level 1 or above,
-        all Taint Bombs print a diagnostic message to stderr when they are
-        created.
-
-    * ``_taint_look(obj)``
-
-        For debugging purposes: prints (to stderr) the type and address of
-        the object in a Tainted Box, or prints the exception if ``obj`` is
-        a Taint Bomb.
-
-
 .. _dump:
 
 The Dump Object Space

File pypy/objspace/std/objecttype.py

         raise OperationError(space.w_TypeError,
                              space.wrap("__class__ assignment: only for heap types"))
     w_oldcls = space.type(w_obj)
-    # XXX taint space should raise a TaintError here if w_oldcls is tainted
     assert isinstance(w_oldcls, W_TypeObject)
     if w_oldcls.get_full_instance_layout() == w_newcls.get_full_instance_layout():
         w_obj.setclass(space, w_newcls)

File pypy/objspace/taint.py

-"""
-Just an experiment.
-"""
-import os
-from pypy.objspace.std.objspace import StdObjSpace
-from pypy.objspace.proxy import patch_space_in_place
-from pypy.objspace.thunk import nb_forcing_args
-from pypy.interpreter.error import OperationError
-from pypy.interpreter import baseobjspace, gateway, executioncontext
-from pypy.interpreter.function import Method
-from pypy.interpreter.pyframe import PyFrame
-from pypy.tool.sourcetools import func_with_new_name
-from pypy.rlib.unroll import unrolling_iterable
-
-
-class W_Tainted(baseobjspace.W_Root):
-    def __init__(self, w_obj):
-        self.w_obj = w_obj
-
-##    def getdict(self, space):
-##        return taint(self.w_obj.getdict(space))
-
-##    def getdictvalue(self, space, attr):
-##        return taint(self.w_obj.getdictvalue(space, attr))
-
-##    def setdictvalue(self, space, attr, w_value):
-##        return self.w_obj.setdictvalue(space, attr, w_value)
-
-##    ...
-
-class W_TaintBomb(baseobjspace.W_Root):
-    filename = '?'
-    codename = '?'
-    codeline = 0
-
-    def __init__(self, space, operr):
-        self.space = space
-        self.operr = operr
-        self.record_debug_info()
-
-    def record_debug_info(self):
-        ec = self.space.getexecutioncontext()
-        frame = ec.gettopframe_nohidden()
-        if isinstance(frame, PyFrame):     # and, in particular, frame != None
-            self.filename = frame.pycode.co_filename
-            self.codename = frame.pycode.co_name
-            self.codeline = frame.get_last_lineno()
-        if get_debug_level(self.space) > 0:
-            self.debug_dump()
-
-    def debug_dump(self):
-        os.write(2, 'Taint Bomb from file "%s", line %d, in %s\n    %s\n' % (
-            self.filename, self.codeline, self.codename,
-            self.operr.errorstr(self.space)))
-
-    def explode(self):
-        #msg = self.operr.errorstr(space)
-        raise OperationError(self.space.w_TaintError, self.space.w_None)
-
-
-def taint(w_obj):
-    """Return a tainted version of the argument."""
-    if w_obj is None or isinstance(w_obj, W_Tainted):
-        return w_obj
-    else:
-        return W_Tainted(w_obj)
-app_taint = gateway.interp2app(taint)
-
-def is_tainted(space, w_obj):
-    """Return whether the argument is tainted."""
-    res = isinstance(w_obj, W_Tainted) or isinstance(w_obj, W_TaintBomb)
-    return space.wrap(res)
-app_is_tainted = gateway.interp2app(is_tainted)
-
-def untaint(space, w_expectedtype, w_obj):
-    """untaint(expectedtype, tainted_obj) -> obj
-Untaint untainted_obj and return it. If the result is not of expectedtype,
-raise a type error."""
-    if (isinstance(w_expectedtype, W_Tainted) or
-        isinstance(w_expectedtype, W_TaintBomb)):
-        raise OperationError(space.w_TypeError,
-                  space.wrap("untaint() arg 1 must be an untainted type"))
-    if not space.is_true(space.isinstance(w_expectedtype, space.w_type)):
-        raise OperationError(space.w_TypeError,
-                             space.wrap("untaint() arg 1 must be a type"))
-    if isinstance(w_obj, W_Tainted):
-        w_obj = w_obj.w_obj
-    elif isinstance(w_obj, W_TaintBomb):
-        w_obj.explode()
-    #if isinstance(w_expectedtype, W_Tainted):
-    #    w_expectedtype = w_expectedtype.w_obj
-    w_realtype = space.type(w_obj)
-    if not space.is_w(w_realtype, w_expectedtype):
-        #msg = "expected an object of type '%s'" % (
-        #    w_expectedtype.getname(space),)
-        #    #w_realtype.getname(space))
-        raise OperationError(space.w_TaintError, space.w_None)
-    return w_obj
-app_untaint = gateway.interp2app(untaint)
-
-# ____________________________________________________________
-
-@gateway.unwrap_spec(args_w='args_w')
-def taint_atomic_function(space, w_func, args_w):
-    newargs_w = []
-    tainted = False
-    for w_arg in args_w:
-        if isinstance(w_arg, W_Tainted):
-            tainted = True
-            w_arg = w_arg.w_obj
-        elif isinstance(w_arg, W_TaintBomb):
-            return w_arg
-        newargs_w.append(w_arg)
-    w_newargs = space.newtuple(newargs_w)
-    try:
-        w_res = space.call(w_func, w_newargs)
-    except OperationError, operr:
-        if not tainted:
-            raise
-        return W_TaintBomb(space, operr)
-    if tainted:
-        w_res = taint(w_res)
-    return w_res
-
-app_taint_atomic_function = gateway.interp2app(taint_atomic_function)
-
-def taint_atomic(space, w_callable):
-    """decorator to make a callable "taint-atomic": if the function is called
-with tainted arguments, those are untainted. The result of the function is
-tainted again.  All exceptions that the callable raises are turned into
-taint bombs."""
-    meth = Method(space, space.w_fn_taint_atomic_function,
-                  w_callable, space.type(w_callable))
-    return space.wrap(meth)
-app_taint_atomic = gateway.interp2app(taint_atomic)
-
-# ____________________________________________________________
-
-executioncontext.ExecutionContext.taint_debug = 0
-
-@gateway.unwrap_spec(level=int)
-def taint_debug(space, level):
-    """Set the debug level. If the debug level is greater than 0, the creation
-of taint bombs will print debug information. For debugging purposes
-only!"""
-    space.getexecutioncontext().taint_debug = level
-app_taint_debug = gateway.interp2app(taint_debug)
-
-def taint_look(space, w_obj):
-    """Print some info about the taintedness of an object. For debugging
-purposes only!"""
-    if isinstance(w_obj, W_Tainted):
-        info = space.type(w_obj.w_obj).getname(space)
-        msg = space.str_w(w_obj.w_obj.getrepr(space, info))
-        msg = 'Taint Box %s\n' % msg
-        os.write(2, msg)
-    elif isinstance(w_obj, W_TaintBomb):
-        w_obj.debug_dump()
-    else:
-        os.write(2, 'not tainted\n')
-app_taint_look = gateway.interp2app(taint_look)
-
-def get_debug_level(space):
-    return space.getexecutioncontext().taint_debug
-
-def debug_bomb(space, operr):
-    ec = space.getexecutioncontext()
-    filename = '?'
-    codename = '?'
-    codeline = 0
-    frame = ec.gettopframe_nohidden()
-    if isinstance(frame, PyFrame):     # and, in particular, frame != None
-        filename = frame.pycode.co_filename
-        codename = frame.pycode.co_name
-        codeline = frame.get_last_lineno()
-    os.write(2, 'Taint Bomb in file "%s", line %d, in %s\n    %s\n' % (
-        filename, codeline, codename, operr.errorstr(space)))
-
-# ____________________________________________________________
-
-
-class TaintSpace(StdObjSpace):
-
-    def __init__(self, *args, **kwds):
-        StdObjSpace.__init__(self, *args, **kwds)
-        w_dict = self.newdict()
-        self.setitem(w_dict, self.wrap("__doc__"), self.wrap("""\
-Exception that is raised when an operation revealing information on a tainted
-object is performed."""))
-        self.w_TaintError = self.call_function(
-            self.w_type,
-            self.wrap("TaintError"),
-            self.newtuple([self.w_Exception]),
-            w_dict
-            )
-        w___pypy__ = self.getbuiltinmodule("__pypy__")
-        self.setattr(w___pypy__, self.wrap('taint'),
-                     self.wrap(app_taint))
-        self.setattr(w___pypy__, self.wrap('is_tainted'),
-                     self.wrap(app_is_tainted))
-        self.setattr(w___pypy__, self.wrap('untaint'),
-                     self.wrap(app_untaint))
-        self.w_fn_taint_atomic_function = self.wrap(app_taint_atomic_function)
-        self.setattr(w___pypy__, self.wrap('taint_atomic'),
-                     self.wrap(app_taint_atomic))
-        self.setattr(w___pypy__, self.wrap('TaintError'),
-                     self.w_TaintError)
-        self.setattr(w___pypy__, self.wrap('_taint_debug'),
-                     self.wrap(app_taint_debug))
-        self.setattr(w___pypy__, self.wrap('_taint_look'),
-                     self.wrap(app_taint_look))
-        patch_space_in_place(self, 'taint', proxymaker)
-
-        # XXX may leak info, perfomance hit, what about taint bombs?
-        from pypy.objspace.std.typeobject import W_TypeObject
-
-        def taint_lookup(w_obj, name):
-            if isinstance(w_obj, W_Tainted):
-                w_obj = w_obj.w_obj
-            w_type = self.type(w_obj)
-            assert isinstance(w_type, W_TypeObject)
-            return w_type.lookup(name)
-
-        def taint_lookup_in_type_where(w_obj, name):
-            if isinstance(w_obj, W_Tainted):
-                w_type = w_obj.w_obj
-            else:
-                w_type = w_obj
-            assert isinstance(w_type, W_TypeObject)
-            return w_type.lookup_where(name)
-
-        self.lookup = taint_lookup
-        self.lookup_in_type_where = taint_lookup_in_type_where
-
-
-Space = TaintSpace
-
-
-def tainted_error(space, name):
-    #msg = "operation '%s' forbidden on tainted object" % (name,)
-    raise OperationError(space.w_TaintError, space.w_None)# space.wrap(msg))
-
-
-RegularMethods = dict.fromkeys(
-    [name for name, _, _, _ in baseobjspace.ObjSpace.MethodTable])
-
-TaintResultIrregularMethods = dict.fromkeys(
-    ['wrap', 'call_args'] +
-    [name for name in baseobjspace.ObjSpace.IrregularOpTable
-          if name.startswith('new')])
-
-def proxymaker(space, name, parentfn):
-    arity = nb_forcing_args[name]
-    indices = unrolling_iterable(range(arity))
-    if name in RegularMethods:
-
-        def proxy(*args_w):
-            newargs_w = ()
-            tainted = False
-            for i in indices:
-                w_arg = args_w[i]
-                if isinstance(w_arg, W_Tainted):
-                    tainted = True
-                    w_arg = w_arg.w_obj
-                elif isinstance(w_arg, W_TaintBomb):
-                    return w_arg
-                newargs_w += (w_arg,)
-            newargs_w += args_w[arity:]
-            try:
-                w_res = parentfn(*newargs_w)
-            except OperationError, operr:
-                if not tainted:
-                    raise
-                return W_TaintBomb(space, operr)
-            if tainted:
-                w_res = taint(w_res)
-            return w_res
-
-    elif arity == 0:
-        return None
-
-    else:
-
-        def proxy(*args_w):
-            for i in indices:
-                w_arg = args_w[i]
-                if isinstance(w_arg, W_Tainted):
-                    tainted_error(space, name)
-                elif isinstance(w_arg, W_TaintBomb):
-                    w_arg.explode()
-            return parentfn(*args_w)
-
-    proxy = func_with_new_name(proxy, '%s_proxy' % name)
-    return proxy

File pypy/objspace/test/test_taintobjspace.py

-from pypy.conftest import gettestobjspace
-
-class AppTest_Taint:
-
-    def setup_class(cls):
-        cls.space = gettestobjspace('taint')
-
-    def test_simple(self):
-        from __pypy__ import taint, untaint, TaintError
-        x = taint(6)
-        x = x * 7
-        raises(TaintError, "if x: y = 1")
-        t = type(x)
-        raises(TaintError, "if t is int: y = 1")
-        assert untaint(int, x) == 42
-        raises(TaintError, "untaint(float, x)")
-
-    def test_bomb(self):
-        from __pypy__ import taint, untaint, TaintError
-        x = taint(6)
-        x = x / 0
-        raises(TaintError, "if x: y = 1")
-        t = type(x)
-        raises(TaintError, "if t is int: y = 1")
-        raises(TaintError, "untaint(int, x)")
-        raises(TaintError, "untaint(float, x)")
-
-    def test_taint_atomic(self):
-        from __pypy__ import taint, untaint, TaintError, taint_atomic
-        x = taint(6)
-        x *= 7
-
-        def dummy(x):
-            if x > 40:
-                return 5
-            else:
-                return 3
-        dummy = taint_atomic(dummy)
-
-        y = dummy(x)
-        raises(TaintError, "if y == 3: z = 1")
-        assert untaint(int, y) == 5
-
-    def test_taint_atomic_exception(self):
-        from __pypy__ import taint, untaint, TaintError, taint_atomic
-        x = taint(6)
-        x *= 7
-
-        def dummy(x):
-            if x + "world" == "hello world":
-                return 5
-            else:
-                return 3
-        dummy = taint_atomic(dummy)
-
-        y = dummy(x)
-        raises(TaintError, "if y == 3: z = 1")
-        raises(TaintError, "untaint(int, y)")
-
-    def test_taint_atomic_incoming_bomb(self):
-        from __pypy__ import taint, untaint, TaintError, taint_atomic
-        x = taint(6)
-        x /= 0
-        lst = []
-
-        def dummy(x):
-            lst.append("running!")
-            if x > 40:
-                return 5
-            else:
-                return 3
-        dummy = taint_atomic(dummy)
-
-        y = dummy(x)
-        raises(TaintError, "if y == 3: z = 1")
-        assert lst == []
-        raises(TaintError, "untaint(int, y)")