[pypy-commit] pypy default: remove taint objspace
gutworth
noreply at buildbot.pypy.org
Wed Oct 12 17:22:28 CEST 2011
Author: Benjamin Peterson <benjamin at python.org>
Branch:
Changeset: r47968:ffa26bfd476e
Date: 2011-10-12 11:22 -0400
http://bitbucket.org/pypy/pypy/changeset/ffa26bfd476e/
Log: remove taint objspace
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -127,7 +127,7 @@
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'),
diff --git a/pypy/doc/__pypy__-module.rst b/pypy/doc/__pypy__-module.rst
--- a/pypy/doc/__pypy__-module.rst
+++ b/pypy/doc/__pypy__-module.rst
@@ -37,29 +37,6 @@
.. _`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
===============================
diff --git a/pypy/doc/config/objspace.name.txt b/pypy/doc/config/objspace.name.txt
--- a/pypy/doc/config/objspace.name.txt
+++ b/pypy/doc/config/objspace.name.txt
@@ -4,7 +4,6 @@
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.
@@ -12,5 +11,4 @@
.. _`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
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -309,7 +309,6 @@
.. _`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
diff --git a/pypy/doc/objspace-proxies.rst b/pypy/doc/objspace-proxies.rst
--- a/pypy/doc/objspace-proxies.rst
+++ b/pypy/doc/objspace-proxies.rst
@@ -129,297 +129,6 @@
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
diff --git a/pypy/objspace/std/objecttype.py b/pypy/objspace/std/objecttype.py
--- a/pypy/objspace/std/objecttype.py
+++ b/pypy/objspace/std/objecttype.py
@@ -44,7 +44,6 @@
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)
diff --git a/pypy/objspace/taint.py b/pypy/objspace/taint.py
deleted file mode 100644
--- a/pypy/objspace/taint.py
+++ /dev/null
@@ -1,294 +0,0 @@
-"""
-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)
-
-# ____________________________________________________________
-
- at 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
-
- at 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
diff --git a/pypy/objspace/test/test_taintobjspace.py b/pypy/objspace/test/test_taintobjspace.py
deleted file mode 100644
--- a/pypy/objspace/test/test_taintobjspace.py
+++ /dev/null
@@ -1,77 +0,0 @@
-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)")
More information about the pypy-commit
mailing list