Armin Rigo avatar Armin Rigo committed 67ebe0b

Sanitize the arguments of ffi.new(array-type, ...).

Comments (0)

Files changed (3)

         typenode = self._parse_type(cdecl)
         return self._get_btype(typenode)
 
-    def new(self, cdecl, *args):
+    def new(self, cdecl, init=None):
         btype = self.typeof(cdecl)
-        return btype(*args)
+        return btype(init)
 
     def _parse_type(self, cdecl):
         try:
     def _get_btype(self, typenode):
         if isinstance(typenode, pycparser.c_ast.ArrayDecl):
             # array type
-            assert isinstance(typenode.dim, pycparser.c_ast.Constant), (
-                "non-constant array length")
-            length = int(typenode.dim.value)
+            if typenode.dim is None:
+                length = None
+            else:
+                assert isinstance(typenode.dim, pycparser.c_ast.Constant), (
+                    "non-constant array length")
+                length = int(typenode.dim.value)
             bitem = self._get_btype(typenode.type)
             return self._get_cached_btype('new_array_type', bitem, length)
         else:

ffi/backend_ctypes.py

         return CTypesInt
 
     def new_array_type(self, bitem, length):
-        ctype = bitem._ctype * length
+        # XXX array of integers only
         #
         class CTypesArray(object):
-            def __init__(self, *args):
-                if len(args) > length:
-                    raise TypeError("too many arguments: expected up to %d, "
-                                    "got %d" % (length, len(args)))
-                self._blob = ctype()
-                for i, value in enumerate(args):
-                    self[i] = value
+
+            def __init__(self, init):
+                if length is not None:
+                    len1 = length
+                else:
+                    if isinstance(init, (int, long)):
+                        len1 = init
+                        init = None
+                    else:
+                        len1 = len(init)
+                self._blob = (bitem._ctype * len1)()
+                if init is not None:
+                    for i, value in enumerate(init):
+                        self[i] = value
+
             def __getitem__(self, index):
-                if not (0 <= index < length):
+                if not (0 <= index < len(self._blob)):
                     raise IndexError
                 return self._blob[index]
+
             def __setitem__(self, index, value):
-                if not (0 <= index < length):
+                if not (0 <= index < len(self._blob)):
                     raise IndexError
                 self._blob[index] = value
         #

testing/backend_tests.py

 
     def test_new_array_args(self):
         ffi = FFI(backend=self.Backend())
-        p = ffi.new("int[5]", 10, 20, 30, 40, 50)
+        # this tries to be closer to C: where we say "int x[5] = {10, 20, ..}"
+        # then here we must enclose the items in a list
+        p = ffi.new("int[5]", [10, 20, 30, 40, 50])
         assert p[0] == 10
         assert p[1] == 20
         assert p[2] == 30
         assert p[3] == 40
         assert p[4] == 50
-        p = ffi.new("int[4]", 25)
+        p = ffi.new("int[4]", [25])
         assert p[0] == 25
         assert p[1] == 0     # follow C convention rather than LuaJIT's
         assert p[2] == 0
         assert p[3] == 0
+
+    def test_new_array_varsize(self):
+        ffi = FFI(backend=self.Backend())
+        p = ffi.new("int[]", 10)     # a single integer is the length
+        assert p[9] == 0
+        py.test.raises(IndexError, "p[10]")
+        #
+        py.test.raises(TypeError, ffi.new, "int[]")
+        #
+        p = ffi.new("int[]", [-6, -7])    # a list is all the items, like C
+        assert p[0] == -6
+        assert p[1] == -7
+        py.test.raises(IndexError, "p[2]")
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.