[pypy-commit] pypy more-rposix: Fix integration with sandbox.

amauryfa noreply at buildbot.pypy.org
Wed Nov 5 16:59:54 CET 2014


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: more-rposix
Changeset: r74341:d5481860c952
Date: 2014-11-05 14:37 +0100
http://bitbucket.org/pypy/pypy/changeset/d5481860c952/

Log:	Fix integration with sandbox. Sandbox now accepts functions no
	created by ExtFunc.

	The "sandbox_name" looks less magic, more explicit, and easier to
	extend.

diff --git a/rpython/flowspace/operation.py b/rpython/flowspace/operation.py
--- a/rpython/flowspace/operation.py
+++ b/rpython/flowspace/operation.py
@@ -12,11 +12,10 @@
 from rpython.tool.sourcetools import compile2
 from rpython.flowspace.model import (Constant, WrapException, const, Variable,
                                      SpaceOperation)
-from rpython.flowspace.specialcase import register_flow_sc
+from rpython.flowspace.specialcase import register_flow_sc, get_specialcase
 from rpython.annotator.model import (
     SomeTuple, AnnotatorError, read_can_only_throw)
 from rpython.annotator.argument import ArgumentsForTranslation
-from rpython.flowspace.specialcase import SPECIAL_CASES
 
 
 NOT_REALLY_CONST = {
@@ -570,11 +569,8 @@
         w_callable, args_w = self.args[0], self.args[1:]
         if isinstance(w_callable, Constant):
             fn = w_callable.value
-            try:
-                sc = SPECIAL_CASES[fn]   # TypeError if 'fn' not hashable
-            except (KeyError, TypeError):
-                pass
-            else:
+            sc = get_specialcase(fn)
+            if sc:
                 return sc(ctx, *args_w)
         return ctx.do_op(self)
 
@@ -589,11 +585,8 @@
         w_callable = self.args[0]
         if isinstance(w_callable, Constant):
             fn = w_callable.value
-            try:
-                sc = SPECIAL_CASES[fn]   # TypeError if 'fn' not hashable
-            except (KeyError, TypeError):
-                pass
-            else:
+            sc = get_specialcase(fn)
+            if sc:
                 from rpython.flowspace.flowcontext import FlowingError
                 raise FlowingError(
                     "should not call %r with keyword arguments" % (fn,))
diff --git a/rpython/flowspace/specialcase.py b/rpython/flowspace/specialcase.py
--- a/rpython/flowspace/specialcase.py
+++ b/rpython/flowspace/specialcase.py
@@ -54,6 +54,26 @@
         from rpython.flowspace.operation import op
         return op.getattr(w_obj, w_index).eval(ctx)
 
+def get_specialcase(fn):
+    try:
+        return SPECIAL_CASES[fn]   # TypeError if 'fn' not hashable
+    except (KeyError, TypeError):
+        # Try to import modules containing special cases
+        for modname in SPECIAL_MODULES.get(fn.__module__, []):
+            __import__(modname)
+        try:
+            return SPECIAL_CASES[fn]
+        except (KeyError, TypeError):
+            pass
+    return None
+
+SPECIAL_MODULES = {
+    # Modules with functions registered with @register_flow_sc, and
+    # which cannot be imported when before the flow object space
+    # (because of import loops).
+    'posix': ['rpython.rlib.rposix'],
+}
+
 # _________________________________________________________________________
 
 redirect_function(open,       'rpython.rlib.rfile.create_file')
diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py
--- a/rpython/rlib/objectmodel.py
+++ b/rpython/rlib/objectmodel.py
@@ -286,13 +286,15 @@
     return Constant(True)
 
 
-def register_replacement_for(replaced_function):
+def register_replacement_for(replaced_function, sandboxed_name=None):
     """Decorator that causes RPython to replace the function passed as parameter
     with the function being defined."""
     def wrap(func):
         @register_flow_sc(replaced_function)
         def sc_redirected_function(ctx, *args_w):
             return ctx.appcall(func, *args_w)
+        if sandboxed_name:
+            func._sandbox_external_name = sandboxed_name
         return func
     return wrap
 
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -4,7 +4,8 @@
 from rpython.rtyper.lltypesystem import ll2ctypes, rffi
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 from rpython.rlib.rarithmetic import intmask
-from rpython.rlib.objectmodel import specialize, register_replacement_for
+from rpython.rlib.objectmodel import (
+    specialize, enforceargs, register_replacement_for)
 from rpython.rlib import jit
 from rpython.translator.platform import platform
 
@@ -111,6 +112,7 @@
         "_PyVerify_fd", [rffi.INT], rffi.INT,
         compilation_info=errno_eci,
         ))
+    @enforceargs(int)
     def validate_fd(fd):
         if not is_valid_fd(fd):
             raise OSError(get_errno(), 'Bad file descriptor')
@@ -118,6 +120,7 @@
     def is_valid_fd(fd):
         return 1
 
+    @enforceargs(int)
     def validate_fd(fd):
         pass
 
@@ -250,15 +253,15 @@
 # They usually check the return value and raise an (RPython) OSError
 # with errno.
 
- at register_replacement_for(os.dup)
+ at register_replacement_for(os.dup, sandboxed_name='ll_os.ll_os_dup')
 def dup(fd):
     validate_fd(fd)
     newfd = c_dup(fd)
     if newfd < 0:
         raise OSError(get_errno(), "dup failed")
-    return newfd
+    return intmask(newfd)
 
- at register_replacement_for(os.dup2)
+ at register_replacement_for(os.dup2, sandboxed_name='ll_os.ll_os_dup2')
 def dup2(fd, newfd):
     validate_fd(fd)
     error = c_dup2(fd, newfd)
diff --git a/rpython/rlib/test/test_rposix.py b/rpython/rlib/test/test_rposix.py
--- a/rpython/rlib/test/test_rposix.py
+++ b/rpython/rlib/test/test_rposix.py
@@ -1,4 +1,5 @@
 from rpython.rtyper.test.test_llinterp import interpret
+from rpython.translator.c.test.test_genc import compile
 from rpython.tool.udir import udir
 from rpython.rlib import rposix
 import os, sys
diff --git a/rpython/translator/c/database.py b/rpython/translator/c/database.py
--- a/rpython/translator/c/database.py
+++ b/rpython/translator/c/database.py
@@ -385,6 +385,9 @@
             return False
         if hasattr(fnobj, '_safe_not_sandboxed'):
             return not fnobj._safe_not_sandboxed
+        elif getattr(getattr(fnobj, '_callable', None),
+                     '_sandbox_external_name', None):
+            return True
         else:
             return "if_external"
 
diff --git a/rpython/translator/sandbox/rsandbox.py b/rpython/translator/sandbox/rsandbox.py
--- a/rpython/translator/sandbox/rsandbox.py
+++ b/rpython/translator/sandbox/rsandbox.py
@@ -115,7 +115,11 @@
     trampoline marshals its input arguments, dumps them to STDOUT,
     and waits for an answer on STDIN.
     """
-    fnname = fnobj._name
+    if getattr(getattr(fnobj, '_callable', None),
+               '_sandbox_external_name', None):
+        fnname = fnobj._callable._sandbox_external_name
+    else:
+        fnname = fnobj._name
     if hasattr(fnobj, 'graph'):
         # get the annotation of the input arguments and the result
         graph = fnobj.graph


More information about the pypy-commit mailing list