Commits

Amaury Forgeot d'Arc  committed a0016c9

The "str0" check is now optional, and controlled by the option
config.translation.check_str_without_nul.

  • Participants
  • Parent commits f32cbb5

Comments (0)

Files changed (5)

File pypy/annotation/model.py

         s_obj = new_s_obj
     return s_obj
 
+def remove_no_nul(s_obj):
+    if not getattr(s_obj, 'no_nul', False):
+        return s_obj
+    new_s_obj = SomeObject.__new__(s_obj.__class__)
+    new_s_obj.__dict__ = s_obj.__dict__.copy()
+    del new_s_obj.no_nul
+    return new_s_obj
+    
+
 # ____________________________________________________________
 # internal
 

File pypy/config/translationoption.py

                  default="off"),
     # jit_ffi is automatically turned on by withmod-_ffi (which is enabled by default)
     BoolOption("jit_ffi", "optimize libffi calls", default=False, cmdline=None),
+    BoolOption("check_str_without_nul",
+               "Forbid NUL chars in strings in some external function calls",
+               default=False, cmdline=None),
 
     # misc
     BoolOption("verbose", "Print extra information", default=False),

File pypy/rpython/extfunc.py

 from pypy.rpython.extregistry import ExtRegistryEntry
 from pypy.rpython.lltypesystem.lltype import typeOf
 from pypy.objspace.flow.model import Constant
-from pypy.annotation.model import unionof
+from pypy.annotation import model as annmodel
 from pypy.annotation.signature import annotation
 
 import py, sys
     # we defer a bit annotation here
 
     def compute_result_annotation(self):
-        from pypy.annotation import model as annmodel
         return annmodel.SomeGenericCallable([annotation(i, self.bookkeeper)
                                              for i in self.instance.args],
                            annotation(self.instance.result, self.bookkeeper))
         signature_args = [annotation(arg, None) for arg in args]
         assert len(args_s) == len(signature_args),\
                "Argument number mismatch"
+
+        check_no_nul = False
+        if hasattr(self, 'bookkeeper'):
+            config = self.bookkeeper.annotator.translator.config
+            if config.translation.check_str_without_nul:
+                check_no_nul = True
+            
         for i, expected in enumerate(signature_args):
-            arg = unionof(args_s[i], expected)
+            if not check_no_nul:
+                expected = annmodel.remove_no_nul(expected)
+            arg = annmodel.unionof(args_s[i], expected)
             if not expected.contains(arg):
                 name = getattr(self, 'name', None)
                 if not name:

File pypy/rpython/module/ll_os_environ.py

 from pypy.rpython.controllerentry import Controller
 from pypy.rpython.extfunc import register_external
 from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.rpython.module import ll_os
 from pypy.rlib import rposix
 
-str0 = annmodel.s_Str0
+str0 = ll_os.str0
 
 # ____________________________________________________________
 #

File pypy/rpython/test/test_extfunc.py

         a = RPythonAnnotator(policy=policy)
         s = a.build_types(f, [])
         assert isinstance(s, annmodel.SomeString)
+
+    def test_str0(self):
+        str0 = annmodel.SomeString(no_nul=True)
+        def os_open(s):
+            pass
+        register_external(os_open, [str0], None)
+        def f(s):
+            return os_open(s)
+        policy = AnnotatorPolicy()
+        policy.allow_someobjects = False
+        a = RPythonAnnotator(policy=policy)
+        a.build_types(f, [str])  # Does not raise
+        assert a.translator.config.translation.check_str_without_nul == False
+        # Now enable the str0 check, and try again with a similar function
+        a.translator.config.translation.check_str_without_nul=True
+        def g(s):
+            return os_open(s)
+        raises(Exception, a.build_types, g, [str])
+        a.build_types(g, [str0])  # Does not raise
+