[pypy-svn] r79899 - in pypy/branch/gc-debug/pypy/rpython/lltypesystem: . test

arigo at codespeak.net arigo at codespeak.net
Wed Dec 8 16:50:11 CET 2010


Author: arigo
Date: Wed Dec  8 16:50:09 2010
New Revision: 79899

Modified:
   pypy/branch/gc-debug/pypy/rpython/lltypesystem/llarena.py
   pypy/branch/gc-debug/pypy/rpython/lltypesystem/test/test_llarena.py
Log:
Translation of arena_protect().


Modified: pypy/branch/gc-debug/pypy/rpython/lltypesystem/llarena.py
==============================================================================
--- pypy/branch/gc-debug/pypy/rpython/lltypesystem/llarena.py	(original)
+++ pypy/branch/gc-debug/pypy/rpython/lltypesystem/llarena.py	Wed Dec  8 16:50:09 2010
@@ -130,8 +130,8 @@
     def mark_freed(self):
         self.freed = True    # this method is a hook for tests
 
-    def set_protect(self, accessible):
-        if not accessible:
+    def set_protect(self, inaccessible):
+        if inaccessible:
             assert self.protect_inaccessible is None
             saved = []
             for ptr in self.objectptrs.values():
@@ -383,15 +383,15 @@
     """
     return Arena(ptr.arena.nbytes, False).getaddr(0)
 
-def arena_protect(arena_addr, size, accessible):
+def arena_protect(arena_addr, size, inaccessible):
     """For debugging, set or reset memory protection on an arena.
     For now, the starting point and size should reference the whole arena.
-    The value of 'accessible' is a boolean.
+    The value of 'inaccessible' is a boolean.
     """
     arena_addr = getfakearenaaddress(arena_addr)
     assert arena_addr.offset == 0
     assert size == arena_addr.arena.nbytes
-    arena_addr.arena.set_protect(accessible)
+    arena_addr.arena.set_protect(inaccessible)
 
 # ____________________________________________________________
 #
@@ -503,6 +503,37 @@
     # them immediately.
     clear_large_memory_chunk = llmemory.raw_memclear
 
+if os.name == "posix":
+    from pypy.translator.tool.cbuild import ExternalCompilationInfo
+    _eci = ExternalCompilationInfo(includes=['sys/mman.h'])
+    raw_mprotect = rffi.llexternal('mprotect',
+                                   [llmemory.Address, rffi.SIZE_T, rffi.INT],
+                                   rffi.INT,
+                                   sandboxsafe=True, _nowrapper=True,
+                                   compilation_info=_eci)
+    def llimpl_arena_protect(addr, size, inaccessible):
+        # do some alignment
+        start = rffi.cast(lltype.Signed, addr)
+        end = start + size
+        start = (start + 4095) & ~ 4095
+        end = end & ~ 4095
+        if end > start:
+            if inaccessible:
+                prot = 0
+            else:
+                from pypy.rlib.rmmap import PROT_READ, PROT_WRITE
+                prot = PROT_READ | PROT_WRITE
+            raw_mprotect(rffi.cast(llmemory.Address, start),
+                         rffi.cast(rffi.SIZE_T, end - start),
+                         rffi.cast(rffi.INT, prot))
+            # ignore potential errors
+    has_protect = True
+
+else:
+    def llimpl_arena_protect(addr, size, inaccessible):
+        pass
+    has_protect = False
+
 
 llimpl_malloc = rffi.llexternal('malloc', [lltype.Signed], llmemory.Address,
                                 sandboxsafe=True, _nowrapper=True)
@@ -572,6 +603,11 @@
                   'll_arena.arena_new_view', llimpl=llimpl_arena_new_view,
                   llfakeimpl=arena_new_view, sandboxsafe=True)
 
+register_external(arena_protect, [llmemory.Address, lltype.Signed,
+                                  lltype.Bool], lltype.Void,
+                  'll_arena.arena_protect', llimpl=llimpl_arena_protect,
+                  llfakeimpl=arena_protect, sandboxsafe=True)
+
 def llimpl_getfakearenaaddress(addr):
     return addr
 register_external(getfakearenaaddress, [llmemory.Address], llmemory.Address,

Modified: pypy/branch/gc-debug/pypy/rpython/lltypesystem/test/test_llarena.py
==============================================================================
--- pypy/branch/gc-debug/pypy/rpython/lltypesystem/test/test_llarena.py	(original)
+++ pypy/branch/gc-debug/pypy/rpython/lltypesystem/test/test_llarena.py	Wed Dec  8 16:50:09 2010
@@ -6,7 +6,8 @@
 from pypy.rpython.lltypesystem.llarena import round_up_for_allocation
 from pypy.rpython.lltypesystem.llarena import ArenaError, arena_new_view
 from pypy.rpython.lltypesystem.llarena import arena_shrink_obj
-from pypy.rpython.lltypesystem.llarena import arena_protect
+from pypy.rpython.lltypesystem.llarena import arena_protect, has_protect
+from pypy.translator.c.test import test_genc, test_standalone
 
 def test_arena():
     S = lltype.Struct('S', ('x',lltype.Signed))
@@ -266,8 +267,7 @@
     assert res == 42
 
 def test_compiled():
-    from pypy.translator.c.test.test_genc import compile
-    fn = compile(test_look_inside_object, [])
+    fn = test_genc.compile(test_look_inside_object, [])
     res = fn()
     assert res == 42
 
@@ -291,11 +291,43 @@
     p = llmemory.cast_adr_to_ptr(a, lltype.Ptr(S))
     p.x = 123
     assert p.x == 123
-    arena_protect(a, 100, accessible=False)
+    arena_protect(a, 100, True)
     py.test.raises(ArenaError, arena_reserve, a + 48, llmemory.sizeof(S))
     py.test.raises(RuntimeError, "p.x")
     py.test.raises(RuntimeError, "p.x = 124")
-    arena_protect(a, 100, accessible=True)
+    arena_protect(a, 100, False)
     assert p.x == 123
     p.x = 125
     assert p.x == 125
+
+
+class TestStandalone(test_standalone.StandaloneTests):
+    def test_compiled_arena_protect(self):
+        import os
+        from pypy.translator.c.test.test_genc import compile
+        S = lltype.Struct('S', ('x', lltype.Signed))
+        #
+        def fn(argv):
+            testrun = int(argv[1])
+            a = arena_malloc(65536, False)
+            arena_reserve(a, llmemory.sizeof(S))
+            p = llmemory.cast_adr_to_ptr(a + 23432, lltype.Ptr(S))
+            p.x = 123
+            assert p.x == 123
+            arena_protect(a, 65536, True)
+            result = 0
+            if testrun == 1:
+                print p.x       # segfault
+            if testrun == 2:
+                p.x = 124       # segfault
+            arena_protect(a, 65536, False)
+            p.x += 10
+            print p.x
+            return 0
+        #
+        t, cbuilder = self.compile(fn)
+        data = cbuilder.cmdexec('0')
+        assert data == '133\n'
+        if has_protect:
+            cbuilder.cmdexec('1', expect_crash=True)
+            cbuilder.cmdexec('2', expect_crash=True)



More information about the Pypy-commit mailing list