Hello community,

here is the log from the commit of package python-cffi for openSUSE:Factory 
checked in at 2020-02-26 15:01:21
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-cffi (Old)
 and      /work/SRC/openSUSE:Factory/.python-cffi.new.26092 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-cffi"

Wed Feb 26 15:01:21 2020 rev:30 rq:778788 version:1.14.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-cffi/python-cffi.changes  2019-11-22 
10:26:11.821259876 +0100
+++ /work/SRC/openSUSE:Factory/.python-cffi.new.26092/python-cffi.changes       
2020-02-26 15:01:23.344753349 +0100
@@ -1,0 +2,8 @@
+Mon Feb 24 14:58:25 UTC 2020 - Ondřej Súkup <mimi...@gmail.com>
+
+- Update to 1.14.0
+ * ffi.dlopen() can now be called with a handle (as a void *) to an 
already-opened C library.
+ * fixed a stack overflow issue for calls like lib.myfunc([large list]).
+ * fixed a memory leak inside ffi.getwinerror() on CPython 3.x.
+
+-------------------------------------------------------------------

Old:
----
  cffi-1.13.2.tar.gz

New:
----
  cffi-1.14.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-cffi.spec ++++++
--- /var/tmp/diff_new_pack.qIv59X/_old  2020-02-26 15:01:24.472755599 +0100
+++ /var/tmp/diff_new_pack.qIv59X/_new  2020-02-26 15:01:24.472755599 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-cffi
 #
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,12 +18,11 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-cffi
-Version:        1.13.2
+Version:        1.14.0
 Release:        0
 Summary:        Foreign Function Interface for Python calling C code
 License:        MIT
-Group:          Development/Languages/Python
-URL:            http://cffi.readthedocs.org
+URL:            https://cffi.readthedocs.org
 Source0:        
https://files.pythonhosted.org/packages/source/c/cffi/cffi-%{version}.tar.gz
 Source1:        python-cffi-rpmlintrc
 BuildRequires:  %{python_module devel}
@@ -54,9 +53,7 @@
 %python_expand %fdupes %{buildroot}%{$python_sitearch}
 
 %check
-%{python_expand export PYTHONPATH=%{buildroot}%{$python_sitearch}
-py.test-%$python_bin_suffix -v -W ignore::UserWarning c/ testing/
-}
+%pytest_arch -W ignore::UserWarning c/ testing/
 
 %files %{python_files}
 %license LICENSE

++++++ cffi-1.13.2.tar.gz -> cffi-1.14.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/PKG-INFO new/cffi-1.14.0/PKG-INFO
--- old/cffi-1.13.2/PKG-INFO    2019-11-03 15:24:33.000000000 +0100
+++ new/cffi-1.14.0/PKG-INFO    2020-02-07 16:44:22.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: cffi
-Version: 1.13.2
+Version: 1.14.0
 Summary: Foreign Function Interface for Python calling C code.
 Home-page: http://cffi.readthedocs.org
 Author: Armin Rigo, Maciej Fijalkowski
@@ -31,3 +31,4 @@
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
+Classifier: License :: OSI Approved :: MIT License
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/c/_cffi_backend.c 
new/cffi-1.14.0/c/_cffi_backend.c
--- old/cffi-1.13.2/c/_cffi_backend.c   2019-11-03 15:22:31.000000000 +0100
+++ new/cffi-1.14.0/c/_cffi_backend.c   2020-02-07 16:40:09.000000000 +0100
@@ -2,7 +2,7 @@
 #include <Python.h>
 #include "structmember.h"
 
-#define CFFI_VERSION  "1.13.2"
+#define CFFI_VERSION  "1.14.0"
 
 #ifdef MS_WIN32
 #include <windows.h>
@@ -2991,6 +2991,10 @@
     CTypeDescrObject *fresult;
     char *resultdata;
     char *errormsg;
+    struct freeme_s {
+        struct freeme_s *next;
+        union_alignment alignment;
+    } *freeme = NULL;
 
     if (!(cd->c_type->ct_flags & CT_FUNCTIONPTR)) {
         PyErr_Format(PyExc_TypeError, "cdata '%s' is not callable",
@@ -3111,7 +3115,21 @@
             else if (datasize < 0)
                 goto error;
             else {
-                tmpbuf = alloca(datasize);
+                if (datasize <= 512) {
+                    tmpbuf = alloca(datasize);
+                }
+                else {
+                    struct freeme_s *fp = (struct freeme_s *)PyObject_Malloc(
+                        offsetof(struct freeme_s, alignment) +
+                        (size_t)datasize);
+                    if (fp == NULL) {
+                        PyErr_NoMemory();
+                        goto error;
+                    }
+                    fp->next = freeme;
+                    freeme = fp;
+                    tmpbuf = (char *)&fp->alignment;
+                }
                 memset(tmpbuf, 0, datasize);
                 *(char **)data = tmpbuf;
                 if (convert_array_from_object(tmpbuf, argtype, obj) < 0)
@@ -3156,6 +3174,11 @@
     /* fall-through */
 
  error:
+    while (freeme != NULL) {
+        void *p = (void *)freeme;
+        freeme = freeme->next;
+        PyObject_Free(p);
+    }
     if (buffer)
         PyObject_Free(buffer);
     if (fvarargs != NULL) {
@@ -4201,11 +4224,12 @@
     PyObject_HEAD
     void *dl_handle;
     char *dl_name;
+    int dl_auto_close;
 } DynLibObject;
 
 static void dl_dealloc(DynLibObject *dlobj)
 {
-    if (dlobj->dl_handle != NULL)
+    if (dlobj->dl_handle != NULL && dlobj->dl_auto_close)
         dlclose(dlobj->dl_handle);
     free(dlobj->dl_name);
     PyObject_Del(dlobj);
@@ -4370,7 +4394,7 @@
 };
 
 static void *b_do_dlopen(PyObject *args, const char **p_printable_filename,
-                         PyObject **p_temp)
+                         PyObject **p_temp, int *auto_close)
 {
     /* Logic to call the correct version of dlopen().  Returns NULL in case of 
error.
        Otherwise, '*p_printable_filename' will point to a printable char 
version of
@@ -4381,6 +4405,7 @@
     char *filename_or_null;
     int flags = 0;
     *p_temp = NULL;
+    *auto_close = 1;
     
     if (PyTuple_GET_SIZE(args) == 0 || PyTuple_GET_ITEM(args, 0) == Py_None) {
         PyObject *dummy;
@@ -4390,6 +4415,28 @@
         filename_or_null = NULL;
         *p_printable_filename = "<None>";
     }
+    else if (CData_Check(PyTuple_GET_ITEM(args, 0)))
+    {
+        CDataObject *cd;
+        if (!PyArg_ParseTuple(args, "O|i:load_library", &cd, &flags))
+            return NULL;
+        /* 'flags' is accepted but ignored in this case */
+        if ((cd->c_type->ct_flags & CT_IS_VOID_PTR) == 0) {
+            PyErr_Format(PyExc_TypeError,
+                "dlopen() takes a file name or 'void *' handle, not '%s'",
+                cd->c_type->ct_name);
+            return NULL;
+        }
+        handle = cd->c_data;
+        if (handle == NULL) {
+            PyErr_Format(PyExc_RuntimeError, "cannot call dlopen(NULL)");
+            return NULL;
+        }
+        *p_temp = PyText_FromFormat("%p", handle);
+        *p_printable_filename = PyText_AsUTF8(*p_temp);
+        *auto_close = 0;
+        return handle;
+    }
     else
     {
         PyObject *s = PyTuple_GET_ITEM(args, 0);
@@ -4451,8 +4498,9 @@
     PyObject *temp;
     void *handle;
     DynLibObject *dlobj = NULL;
+    int auto_close;
 
-    handle = b_do_dlopen(args, &printable_filename, &temp);
+    handle = b_do_dlopen(args, &printable_filename, &temp, &auto_close);
     if (handle == NULL)
         goto error;
 
@@ -4463,6 +4511,7 @@
     }
     dlobj->dl_handle = handle;
     dlobj->dl_name = strdup(printable_filename);
+    dlobj->dl_auto_close = auto_close;
  
  error:
     Py_XDECREF(temp);
@@ -4974,8 +5023,8 @@
         if (sflags & SF_STD_FIELD_POS) {
             PyErr_Format(FFIError,
                          "%s: %s%s%s (cdef says %zd, but C compiler says %zd)."
-                         " fix it or use \"...;\" in the cdef for %s to "
-                         "make it flexible",
+                         " fix it or use \"...;\" as the last field in the "
+                         "cdef for %s to make it flexible",
                          ct->ct_name, msg1, txt, msg2,
                          cdef_value, compiler_value,
                          ct->ct_name);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/c/cdlopen.c new/cffi-1.14.0/c/cdlopen.c
--- old/cffi-1.13.2/c/cdlopen.c 2019-11-03 15:22:31.000000000 +0100
+++ new/cffi-1.14.0/c/cdlopen.c 2020-02-07 16:40:09.000000000 +0100
@@ -43,12 +43,13 @@
     const char *modname;
     PyObject *temp, *result = NULL;
     void *handle;
+    int auto_close;
 
-    handle = b_do_dlopen(args, &modname, &temp);
+    handle = b_do_dlopen(args, &modname, &temp, &auto_close);
     if (handle != NULL)
     {
         result = (PyObject *)lib_internal_new((FFIObject *)self,
-                                              modname, handle);
+                                              modname, handle, auto_close);
     }
     Py_XDECREF(temp);
     return result;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/c/cffi1_module.c 
new/cffi-1.14.0/c/cffi1_module.c
--- old/cffi-1.13.2/c/cffi1_module.c    2019-11-03 15:22:31.000000000 +0100
+++ new/cffi-1.14.0/c/cffi1_module.c    2020-02-07 16:40:09.000000000 +0100
@@ -199,7 +199,7 @@
     if (ffi == NULL || PyModule_AddObject(m, "ffi", (PyObject *)ffi) < 0)
         return NULL;
 
-    lib = lib_internal_new(ffi, module_name, NULL);
+    lib = lib_internal_new(ffi, module_name, NULL, 0);
     if (lib == NULL || PyModule_AddObject(m, "lib", (PyObject *)lib) < 0)
         return NULL;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/c/lib_obj.c new/cffi-1.14.0/c/lib_obj.c
--- old/cffi-1.13.2/c/lib_obj.c 2019-11-03 15:22:31.000000000 +0100
+++ new/cffi-1.14.0/c/lib_obj.c 2020-02-07 16:40:09.000000000 +0100
@@ -29,6 +29,7 @@
     PyObject *l_libname;        /* some string that gives the name of the lib 
*/
     FFIObject *l_ffi;           /* reference back to the ffi object */
     void *l_libhandle;          /* the dlopen()ed handle, if any */
+    int l_auto_close;           /* if we must dlclose() this handle */
 };
 
 static struct CPyExtFunc_s *_cpyextfunc_get(PyObject *x)
@@ -91,7 +92,8 @@
 static void lib_dealloc(LibObject *lib)
 {
     PyObject_GC_UnTrack(lib);
-    cdlopen_close_ignore_errors(lib->l_libhandle);
+    if (lib->l_auto_close)
+        cdlopen_close_ignore_errors(lib->l_libhandle);
     Py_DECREF(lib->l_dict);
     Py_DECREF(lib->l_libname);
     Py_DECREF(lib->l_ffi);
@@ -624,7 +626,7 @@
 };
 
 static LibObject *lib_internal_new(FFIObject *ffi, const char *module_name,
-                                   void *dlopen_libhandle)
+                                   void *dlopen_libhandle, int auto_close)
 {
     LibObject *lib;
     PyObject *libname, *dict;
@@ -647,6 +649,7 @@
     Py_INCREF(ffi);
     lib->l_ffi = ffi;
     lib->l_libhandle = dlopen_libhandle;
+    lib->l_auto_close = auto_close;
     return lib;
 
  err3:
@@ -654,7 +657,8 @@
  err2:
     Py_DECREF(libname);
  err1:
-    cdlopen_close_ignore_errors(dlopen_libhandle);
+    if (auto_close)
+        cdlopen_close_ignore_errors(dlopen_libhandle);
     return NULL;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/c/misc_win32.h 
new/cffi-1.14.0/c/misc_win32.h
--- old/cffi-1.13.2/c/misc_win32.h      2019-11-03 15:22:31.000000000 +0100
+++ new/cffi-1.14.0/c/misc_win32.h      2020-02-07 16:40:09.000000000 +0100
@@ -124,8 +124,10 @@
             s_buf[--len] = L'\0';
         message = PyUnicode_FromWideChar(s_buf, len);
     }
-    if (message != NULL)
+    if (message != NULL) {
         v = Py_BuildValue("(iO)", err, message);
+        Py_DECREF(message);
+    }
     else
         v = NULL;
     LocalFree(s_buf);
@@ -168,7 +170,6 @@
         /* Only seen this in out of mem situations */
         sprintf(s_small_buf, "Windows Error 0x%X", err);
         s = s_small_buf;
-        s_buf = NULL;
     } else {
         s = s_buf;
         /* remove trailing cr/lf and dots */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/c/test_c.py new/cffi-1.14.0/c/test_c.py
--- old/cffi-1.13.2/c/test_c.py 2019-11-03 15:22:31.000000000 +0100
+++ new/cffi-1.14.0/c/test_c.py 2020-02-07 16:40:09.000000000 +0100
@@ -14,7 +14,7 @@
 # ____________________________________________________________
 
 import sys
-assert __version__ == "1.13.2", ("This test_c.py file is for testing a version"
+assert __version__ == "1.14.0", ("This test_c.py file is for testing a version"
                                  " of cffi that differs from the one that we"
                                  " get from 'import _cffi_backend'")
 if sys.version_info < (3,):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/cffi/__init__.py 
new/cffi-1.14.0/cffi/__init__.py
--- old/cffi-1.13.2/cffi/__init__.py    2019-11-03 15:22:31.000000000 +0100
+++ new/cffi-1.14.0/cffi/__init__.py    2020-02-07 16:40:09.000000000 +0100
@@ -5,8 +5,8 @@
 from .error import CDefError, FFIError, VerificationError, VerificationMissing
 from .error import PkgConfigError
 
-__version__ = "1.13.2"
-__version_info__ = (1, 13, 2)
+__version__ = "1.14.0"
+__version_info__ = (1, 14, 0)
 
 # The verifier module file names are based on the CRC32 of a string that
 # contains the following version number.  It may be older than __version__
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/cffi/_cffi_include.h 
new/cffi-1.14.0/cffi/_cffi_include.h
--- old/cffi-1.13.2/cffi/_cffi_include.h        2019-11-03 15:22:31.000000000 
+0100
+++ new/cffi-1.14.0/cffi/_cffi_include.h        2020-02-07 16:40:09.000000000 
+0100
@@ -261,14 +261,62 @@
         return (int)_cffi_to_c_wchar3216_t(o);
 }
 
-_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char32_t(int x)
+_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char32_t(unsigned int x)
 {
     if (sizeof(_cffi_wchar_t) == 4)
         return _cffi_from_c_wchar_t((_cffi_wchar_t)x);
     else
-        return _cffi_from_c_wchar3216_t(x);
+        return _cffi_from_c_wchar3216_t((int)x);
 }
 
+union _cffi_union_alignment_u {
+    unsigned char m_char;
+    unsigned short m_short;
+    unsigned int m_int;
+    unsigned long m_long;
+    unsigned long long m_longlong;
+    float m_float;
+    double m_double;
+    long double m_longdouble;
+};
+
+struct _cffi_freeme_s {
+    struct _cffi_freeme_s *next;
+    union _cffi_union_alignment_u alignment;
+};
+
+_CFFI_UNUSED_FN static int
+_cffi_convert_array_argument(struct _cffi_ctypedescr *ctptr, PyObject *arg,
+                             char **output_data, Py_ssize_t datasize,
+                             struct _cffi_freeme_s **freeme)
+{
+    char *p;
+    if (datasize < 0)
+        return -1;
+
+    p = *output_data;
+    if (p == NULL) {
+        struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc(
+            offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize);
+        if (fp == NULL)
+            return -1;
+        fp->next = *freeme;
+        *freeme = fp;
+        p = *output_data = (char *)&fp->alignment;
+    }
+    memset((void *)p, 0, (size_t)datasize);
+    return _cffi_convert_array_from_object(p, ctptr, arg);
+}
+
+_CFFI_UNUSED_FN static void
+_cffi_free_array_arguments(struct _cffi_freeme_s *freeme)
+{
+    do {
+        void *p = (void *)freeme;
+        freeme = freeme->next;
+        PyObject_Free(p);
+    } while (freeme != NULL);
+}
 
 /**********  end CPython-specific section  **********/
 #else
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/cffi/_embedding.h 
new/cffi-1.14.0/cffi/_embedding.h
--- old/cffi-1.13.2/cffi/_embedding.h   2019-11-03 15:22:31.000000000 +0100
+++ new/cffi-1.14.0/cffi/_embedding.h   2020-02-07 16:40:09.000000000 +0100
@@ -224,7 +224,7 @@
 
         if (f != NULL && f != Py_None) {
             PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
-                               "\ncompiled with cffi version: 1.13.2"
+                               "\ncompiled with cffi version: 1.14.0"
                                "\n_cffi_backend module: ", f);
             modules = PyImport_GetModuleDict();
             mod = PyDict_GetItemString(modules, "_cffi_backend");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/cffi/api.py new/cffi-1.14.0/cffi/api.py
--- old/cffi-1.13.2/cffi/api.py 2019-11-03 15:22:31.000000000 +0100
+++ new/cffi-1.14.0/cffi/api.py 2020-02-07 16:40:09.000000000 +0100
@@ -141,7 +141,11 @@
         linked to a particular library, just like C headers; in the
         library we only look for the actual (untyped) symbols.
         """
-        assert isinstance(name, basestring) or name is None
+        if not (isinstance(name, basestring) or
+                name is None or
+                isinstance(name, self.CData)):
+            raise TypeError("dlopen(name): name must be a file name, None, "
+                            "or an already-opened 'void *' handle")
         with self._lock:
             lib, function_cache = _make_ffi_library(self, name, flags)
             self._function_caches.append(function_cache)
@@ -799,9 +803,9 @@
 
 def _load_backend_lib(backend, name, flags):
     import os
-    if name is None:
-        if sys.platform != "win32":
-            return backend.load_library(None, flags)
+    if not isinstance(name, basestring):
+        if sys.platform != "win32" or name is not None:
+            return backend.load_library(name, flags)
         name = "c"    # Windows: load_library(None) fails, but this works
                       # on Python 2 (backward compatibility hack only)
     first_error = None
@@ -935,7 +939,7 @@
             backendlib.close_lib()
             self.__dict__.clear()
     #
-    if libname is not None:
+    if isinstance(libname, basestring):
         try:
             if not isinstance(libname, str):    # unicode, on Python 2
                 libname = libname.encode('utf-8')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/cffi/recompiler.py 
new/cffi-1.14.0/cffi/recompiler.py
--- old/cffi-1.13.2/cffi/recompiler.py  2019-11-03 15:22:31.000000000 +0100
+++ new/cffi-1.14.0/cffi/recompiler.py  2020-02-07 16:40:09.000000000 +0100
@@ -560,23 +560,24 @@
             tovar, tp.get_c_name(''), errvalue))
         self._prnt('    %s;' % errcode)
 
-    def _extra_local_variables(self, tp, localvars):
+    def _extra_local_variables(self, tp, localvars, freelines):
         if isinstance(tp, model.PointerType):
             localvars.add('Py_ssize_t datasize')
+            localvars.add('struct _cffi_freeme_s *large_args_free = NULL')
+            freelines.add('if (large_args_free != NULL)'
+                          ' _cffi_free_array_arguments(large_args_free);')
 
     def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode):
         self._prnt('  datasize = _cffi_prepare_pointer_call_argument(')
         self._prnt('      _cffi_type(%d), %s, (char **)&%s);' % (
             self._gettypenum(tp), fromvar, tovar))
         self._prnt('  if (datasize != 0) {')
-        self._prnt('    if (datasize < 0)')
-        self._prnt('      %s;' % errcode)
-        self._prnt('    %s = (%s)alloca((size_t)datasize);' % (
+        self._prnt('    %s = ((size_t)datasize) <= 640 ? '
+                   '(%s)alloca((size_t)datasize) : NULL;' % (
             tovar, tp.get_c_name('')))
-        self._prnt('    memset((void *)%s, 0, (size_t)datasize);' % (tovar,))
-        self._prnt('    if (_cffi_convert_array_from_object('
-                   '(char *)%s, _cffi_type(%d), %s) < 0)' % (
-            tovar, self._gettypenum(tp), fromvar))
+        self._prnt('    if (_cffi_convert_array_argument(_cffi_type(%d), %s, '
+                   '(char **)&%s,' % (self._gettypenum(tp), fromvar, tovar))
+        self._prnt('            datasize, &large_args_free) < 0)')
         self._prnt('      %s;' % errcode)
         self._prnt('  }')
 
@@ -699,9 +700,10 @@
             prnt('  %s;' % arg)
         #
         localvars = set()
+        freelines = set()
         for type in tp.args:
-            self._extra_local_variables(type, localvars)
-        for decl in localvars:
+            self._extra_local_variables(type, localvars, freelines)
+        for decl in sorted(localvars):
             prnt('  %s;' % (decl,))
         #
         if not isinstance(tp.result, model.VoidType):
@@ -709,6 +711,7 @@
             context = 'result of %s' % name
             result_decl = '  %s;' % tp.result.get_c_name(' result', context)
             prnt(result_decl)
+            prnt('  PyObject *pyresult;')
         else:
             result_decl = None
             result_code = ''
@@ -742,9 +745,14 @@
         if numargs == 0:
             prnt('  (void)noarg; /* unused */')
         if result_code:
-            prnt('  return %s;' %
+            prnt('  pyresult = %s;' %
                  self._convert_expr_from_c(tp.result, 'result', 'result type'))
+            for freeline in freelines:
+                prnt('  ' + freeline)
+            prnt('  return pyresult;')
         else:
+            for freeline in freelines:
+                prnt('  ' + freeline)
             prnt('  Py_INCREF(Py_None);')
             prnt('  return Py_None;')
         prnt('}')
@@ -1216,7 +1224,8 @@
             size_of_result = '(int)sizeof(%s)' % (
                 tp.result.get_c_name('', context),)
         prnt('static struct _cffi_externpy_s _cffi_externpy__%s =' % name)
-        prnt('  { "%s.%s", %s };' % (self.module_name, name, size_of_result))
+        prnt('  { "%s.%s", %s, 0, 0 };' % (
+            self.module_name, name, size_of_result))
         prnt()
         #
         arguments = []
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/cffi/vengine_cpy.py 
new/cffi-1.14.0/cffi/vengine_cpy.py
--- old/cffi-1.13.2/cffi/vengine_cpy.py 2019-11-03 15:22:31.000000000 +0100
+++ new/cffi-1.14.0/cffi/vengine_cpy.py 2020-02-07 16:40:09.000000000 +0100
@@ -275,22 +275,23 @@
             tovar, tp.get_c_name(''), errvalue))
         self._prnt('    %s;' % errcode)
 
-    def _extra_local_variables(self, tp, localvars):
+    def _extra_local_variables(self, tp, localvars, freelines):
         if isinstance(tp, model.PointerType):
             localvars.add('Py_ssize_t datasize')
+            localvars.add('struct _cffi_freeme_s *large_args_free = NULL')
+            freelines.add('if (large_args_free != NULL)'
+                          ' _cffi_free_array_arguments(large_args_free);')
 
     def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode):
         self._prnt('  datasize = _cffi_prepare_pointer_call_argument(')
         self._prnt('      _cffi_type(%d), %s, (char **)&%s);' % (
             self._gettypenum(tp), fromvar, tovar))
         self._prnt('  if (datasize != 0) {')
-        self._prnt('    if (datasize < 0)')
-        self._prnt('      %s;' % errcode)
-        self._prnt('    %s = alloca((size_t)datasize);' % (tovar,))
-        self._prnt('    memset((void *)%s, 0, (size_t)datasize);' % (tovar,))
-        self._prnt('    if (_cffi_convert_array_from_object('
-                   '(char *)%s, _cffi_type(%d), %s) < 0)' % (
-            tovar, self._gettypenum(tp), fromvar))
+        self._prnt('    %s = ((size_t)datasize) <= 640 ? '
+                   'alloca((size_t)datasize) : NULL;' % (tovar,))
+        self._prnt('    if (_cffi_convert_array_argument(_cffi_type(%d), %s, '
+                   '(char **)&%s,' % (self._gettypenum(tp), fromvar, tovar))
+        self._prnt('            datasize, &large_args_free) < 0)')
         self._prnt('      %s;' % errcode)
         self._prnt('  }')
 
@@ -369,15 +370,17 @@
             prnt('  %s;' % type.get_c_name(' x%d' % i, context))
         #
         localvars = set()
+        freelines = set()
         for type in tp.args:
-            self._extra_local_variables(type, localvars)
-        for decl in localvars:
+            self._extra_local_variables(type, localvars, freelines)
+        for decl in sorted(localvars):
             prnt('  %s;' % (decl,))
         #
         if not isinstance(tp.result, model.VoidType):
             result_code = 'result = '
             context = 'result of %s' % name
             prnt('  %s;' % tp.result.get_c_name(' result', context))
+            prnt('  PyObject *pyresult;')
         else:
             result_code = ''
         #
@@ -409,9 +412,14 @@
         if numargs == 0:
             prnt('  (void)noarg; /* unused */')
         if result_code:
-            prnt('  return %s;' %
+            prnt('  pyresult = %s;' %
                  self._convert_expr_from_c(tp.result, 'result', 'result type'))
+            for freeline in freelines:
+                prnt('  ' + freeline)
+            prnt('  return pyresult;')
         else:
+            for freeline in freelines:
+                prnt('  ' + freeline)
             prnt('  Py_INCREF(Py_None);')
             prnt('  return Py_None;')
         prnt('}')
@@ -981,6 +989,59 @@
     return PyBool_FromLong(was_alive);
 }
 
+union _cffi_union_alignment_u {
+    unsigned char m_char;
+    unsigned short m_short;
+    unsigned int m_int;
+    unsigned long m_long;
+    unsigned long long m_longlong;
+    float m_float;
+    double m_double;
+    long double m_longdouble;
+};
+
+struct _cffi_freeme_s {
+    struct _cffi_freeme_s *next;
+    union _cffi_union_alignment_u alignment;
+};
+
+#ifdef __GNUC__
+  __attribute__((unused))
+#endif
+static int _cffi_convert_array_argument(CTypeDescrObject *ctptr, PyObject *arg,
+                                        char **output_data, Py_ssize_t 
datasize,
+                                        struct _cffi_freeme_s **freeme)
+{
+    char *p;
+    if (datasize < 0)
+        return -1;
+
+    p = *output_data;
+    if (p == NULL) {
+        struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc(
+            offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize);
+        if (fp == NULL)
+            return -1;
+        fp->next = *freeme;
+        *freeme = fp;
+        p = *output_data = (char *)&fp->alignment;
+    }
+    memset((void *)p, 0, (size_t)datasize);
+    return _cffi_convert_array_from_object(p, ctptr, arg);
+}
+
+#ifdef __GNUC__
+  __attribute__((unused))
+#endif
+static void _cffi_free_array_arguments(struct _cffi_freeme_s *freeme)
+{
+    do {
+        void *p = (void *)freeme;
+        freeme = freeme->next;
+        PyObject_Free(p);
+    } while (freeme != NULL);
+}
+
 static int _cffi_init(void)
 {
     PyObject *module, *c_api_object = NULL;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/cffi.egg-info/PKG-INFO 
new/cffi-1.14.0/cffi.egg-info/PKG-INFO
--- old/cffi-1.13.2/cffi.egg-info/PKG-INFO      2019-11-03 15:24:33.000000000 
+0100
+++ new/cffi-1.14.0/cffi.egg-info/PKG-INFO      2020-02-07 16:44:22.000000000 
+0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: cffi
-Version: 1.13.2
+Version: 1.14.0
 Summary: Foreign Function Interface for Python calling C code.
 Home-page: http://cffi.readthedocs.org
 Author: Armin Rigo, Maciej Fijalkowski
@@ -31,3 +31,4 @@
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
+Classifier: License :: OSI Approved :: MIT License
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/doc/source/cdef.rst 
new/cffi-1.14.0/doc/source/cdef.rst
--- old/cffi-1.13.2/doc/source/cdef.rst 2019-11-03 15:22:31.000000000 +0100
+++ new/cffi-1.14.0/doc/source/cdef.rst 2020-02-07 16:40:09.000000000 +0100
@@ -235,7 +235,12 @@
 byte.  (Note that the packed attribute has no effect on bit fields so
 far, which mean that they may be packed differently than on GCC.
 Also, this has no effect on structs declared with ``"...;"``---more
-about it later in `Letting the C compiler fill the gaps`_.)
+about it later in `Letting the C compiler fill the gaps`_.  In
+particular, if your C source uses other attributes like
+``__attribute__((aligned(16)))``, there is no way to declare this fact
+in the ``cdef()``, but you can generally just declare the struct with
+``"...;"`` as the last field.)
+
 *New in version 1.12:*  In ABI mode, you can also pass ``pack=n``,
 with an integer ``n`` which must be a power of two.  Then the
 alignment of any field is limited to ``n`` if it would otherwise be
@@ -364,6 +369,16 @@
 ``ffi.dlopen(None)`` no longer work on Windows; try instead
 ``ffi.dlopen(ctypes.util.find_library('c'))``.
 
+*New in version 1.14:* ``ffi.dlopen(handle)``: instead of a file path,
+you can give an already-opened library handle, as a cdata of type
+``void *``.  Such a call converts this handle into a regular FFI object
+with the functions and global variables declared by ``ffi.cdef()``.
+Useful if you have special needs (e.g. you need the GNU extension
+``dlmopen()``, which you can itself declare and call using a different
+``ffi`` object).  Note that in this variant, ``dlclose()`` is not called
+automatically if the FFI object is garbage-collected (but you can still
+call ``ffi.dlclose()`` explicitly if needed).
+
 
 ffibuilder.set_source(): preparing out-of-line modules
 ------------------------------------------------------
@@ -471,10 +486,12 @@
 ``cdef()`` at various places, in order to ask the C compiler to fill
 in the details.  These places are:
 
-*  structure declarations: any ``struct { }`` that ends with "``...;``" as
-   the last "field" is
-   partial: it may be missing fields and/or have them declared out of order.
-   This declaration will be corrected by the compiler.  (But note that you
+*  structure declarations: any ``struct { }`` or ``union { }`` that ends
+   with "``...;``" as the last "field" is partial: it may be missing
+   fields, have them declared out of order, use non-standard alignment,
+   etc.  Precisely, the field offsets, total struct size, and total
+   struct alignment deduced by looking at the ``cdef`` are not relied
+   upon and will instead be corrected by the compiler.  (But note that you
    can only access fields that you declared, not others.)  Any ``struct``
    declaration which doesn't use "``...``" is assumed to be exact, but this is
    checked: you get an error if it is not correct.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/doc/source/conf.py 
new/cffi-1.14.0/doc/source/conf.py
--- old/cffi-1.13.2/doc/source/conf.py  2019-11-03 15:22:31.000000000 +0100
+++ new/cffi-1.14.0/doc/source/conf.py  2020-02-07 16:40:09.000000000 +0100
@@ -45,9 +45,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = '1.13'
+version = '1.14'
 # The full version, including alpha/beta/rc tags.
-release = '1.13.2'
+release = '1.14.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/doc/source/installation.rst 
new/cffi-1.14.0/doc/source/installation.rst
--- old/cffi-1.13.2/doc/source/installation.rst 2019-11-03 15:22:31.000000000 
+0100
+++ new/cffi-1.14.0/doc/source/installation.rst 2020-02-07 16:40:09.000000000 
+0100
@@ -52,7 +52,7 @@
 
 * https://pypi.python.org/pypi/cffi
 
-* Checksums of the "source" package version 1.13.2:
+* Checksums of the "source" package version 1.14.0:
 
    - MD5: ...
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/doc/source/overview.rst 
new/cffi-1.14.0/doc/source/overview.rst
--- old/cffi-1.13.2/doc/source/overview.rst     2019-11-03 15:22:31.000000000 
+0100
+++ new/cffi-1.14.0/doc/source/overview.rst     2020-02-07 16:40:09.000000000 
+0100
@@ -335,7 +335,7 @@
    
       ffibuilder.set_source("_pi",  # name of the output C extension
       """
-          #include "pi.h"',
+          #include "pi.h"
       """,
           sources=['pi.c'],   # includes pi.c as additional sources
           libraries=['m'])    # on Unix, link with the math library
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/doc/source/ref.rst 
new/cffi-1.14.0/doc/source/ref.rst
--- old/cffi-1.13.2/doc/source/ref.rst  2019-11-03 15:22:31.000000000 +0100
+++ new/cffi-1.14.0/doc/source/ref.rst  2020-02-07 16:40:09.000000000 +0100
@@ -37,7 +37,7 @@
 allocate an instance according to the specified C type and return a
 pointer to it.  The specified C type must be either a pointer or an
 array: ``new('X *')`` allocates an X and returns a pointer to it,
-whereas ``new('X[n]')`` allocates an array of n X'es and returns an
+whereas ``new('X[10]')`` allocates an array of 10 X'es and returns an
 array referencing it (which works mostly like a pointer, like in C).
 You can also use ``new('X[]', n)`` to allocate an array of a
 non-constant length n.  See the `detailed documentation`__ for other
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/doc/source/whatsnew.rst 
new/cffi-1.14.0/doc/source/whatsnew.rst
--- old/cffi-1.13.2/doc/source/whatsnew.rst     2019-11-03 15:22:31.000000000 
+0100
+++ new/cffi-1.14.0/doc/source/whatsnew.rst     2020-02-07 16:40:09.000000000 
+0100
@@ -2,6 +2,34 @@
 What's New
 ======================
 
+
+v1.14
+=====
+
+* ``ffi.dlopen()`` can now be called with a handle (as a ``void *``) to an
+  already-opened C library.
+
+* CPython only: fixed a stack overflow issue for calls like
+  ``lib.myfunc([large list])``.  If the function is declared as taking a
+  ``float *`` argument, for example, then the array is temporarily converted
+  into a C array of floats---however, the code used to use ``alloca()`` for
+  this temporary storage, no matter how large.  This is now fixed.
+
+  The fix concerns all modes: in-line/out-of-line API/ABI.  Also note that your
+  API-mode C extension modules need to be regenerated with cffi 1.14 in order
+  to get the fix; i.e. for API mode, the fix is in the generated C sources.
+  (The C sources generated from cffi 1.14 should also work when running in
+  a different environment in which we have an older version of cffi.  Also,
+  this change makes no difference on PyPy.)
+
+  As a workaround that works on all versions of cffi, you can write
+  ``lib.myfunc(ffi.new("float[]", [large list]))``, which is
+  equivalent but explicity builds the intermediate array as a regular
+  Python object on the heap.
+
+* fixed a memory leak inside ``ffi.getwinerror()`` on CPython 3.x.
+
+
 v1.13.2
 =======
 
@@ -83,7 +111,7 @@
   Like before, `Issue #350`_ mentions a workaround if you still want
   the ``Py_LIMITED_API`` flag and *either* you are not concerned about
   virtualenv *or* you are sure your module will not be used on CPython
-  <= 3.4: pass ``define_macros=[("Py_LIMITED_API", None)]`` to the
+  <= 3.4: pass ``define_macros=[("Py_LIMITED_API", None)]`` as a keyword to the
   ``ffibuilder.set_source()`` call.
 
 
@@ -155,8 +183,8 @@
 * CPython 3 on Windows: we no longer compile with ``Py_LIMITED_API``
   by default because such modules cannot be used with virtualenv.
   `Issue #350`_ mentions a workaround if you still want that and are not
-  concerned about virtualenv: pass a ``define_macros=[("Py_LIMITED_API",
-  None)]`` to the ``ffibuilder.set_source()`` call.
+  concerned about virtualenv: pass ``define_macros=[("Py_LIMITED_API",
+  None)]`` as a keyword to the ``ffibuilder.set_source()`` call.
 
 .. _`Issue #345`: https://bitbucket.org/cffi/cffi/issues/345/
 .. _`Issue #350`: https://bitbucket.org/cffi/cffi/issues/350/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/setup.py new/cffi-1.14.0/setup.py
--- old/cffi-1.13.2/setup.py    2019-11-03 15:22:31.000000000 +0100
+++ new/cffi-1.14.0/setup.py    2020-02-07 16:40:09.000000000 +0100
@@ -198,7 +198,7 @@
 
 `Mailing list <https://groups.google.com/forum/#!forum/python-cffi>`_
 """,
-        version='1.13.2',
+        version='1.14.0',
         packages=['cffi'] if cpython else [],
         package_data={'cffi': ['_cffi_include.h', 'parse_c_type.h', 
                                '_embedding.h', '_cffi_errors.h']}
@@ -246,5 +246,6 @@
             'Programming Language :: Python :: 3.6',
             'Programming Language :: Python :: Implementation :: CPython',
             'Programming Language :: Python :: Implementation :: PyPy',
+            'License :: OSI Approved :: MIT License',
         ],
     )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/testing/cffi0/backend_tests.py 
new/cffi-1.14.0/testing/cffi0/backend_tests.py
--- old/cffi-1.13.2/testing/cffi0/backend_tests.py      2019-11-03 
15:22:31.000000000 +0100
+++ new/cffi-1.14.0/testing/cffi0/backend_tests.py      2020-02-07 
16:40:09.000000000 +0100
@@ -1241,7 +1241,7 @@
             py.test.skip(str(e))
         f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
         f.seek(0)
-        assert f.read() == array.array('i', range(1000)).tostring()
+        assert f.read() == arraytostring(array.array('i', range(1000)))
         f.seek(0)
         b = ffi.new("int[]", 1005)
         f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int")))
@@ -1260,7 +1260,7 @@
             py.test.skip(str(e))
         f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
         f.seek(0)
-        assert f.read() == array.array('i', range(1000)).tostring()
+        assert f.read() == arraytostring(array.array('i', range(1000)))
         f.seek(0)
         b = ffi.new("int[]", 1005)
         f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int")))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/testing/cffi0/test_function.py 
new/cffi-1.14.0/testing/cffi0/test_function.py
--- old/cffi-1.13.2/testing/cffi0/test_function.py      2019-11-03 
15:22:31.000000000 +0100
+++ new/cffi-1.14.0/testing/cffi0/test_function.py      2020-02-07 
16:40:09.000000000 +0100
@@ -520,3 +520,16 @@
         assert str(e.value).startswith("library '")
         assert str(e.value).endswith("' has already been closed")
         ffi.dlclose(lib)    # does not raise
+
+    def test_passing_large_list(self):
+        if self.Backend is CTypesBackend:
+            py.test.skip("the ctypes backend doesn't support this")
+        ffi = FFI(backend=self.Backend())
+        ffi.cdef("""
+            void getenv(char *);
+        """)
+        needs_dlopen_none()
+        m = ffi.dlopen(None)
+        arg = [b"F", b"O", b"O"] + [b"\x00"] * 20000000
+        x = m.getenv(arg)
+        assert x is None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/testing/cffi0/test_ownlib.py 
new/cffi-1.14.0/testing/cffi0/test_ownlib.py
--- old/cffi-1.13.2/testing/cffi0/test_ownlib.py        2019-11-03 
15:22:31.000000000 +0100
+++ new/cffi-1.14.0/testing/cffi0/test_ownlib.py        2020-02-07 
16:40:09.000000000 +0100
@@ -371,3 +371,29 @@
         assert s.top == 22
         assert s.right == 33
         assert s.bottom == 44
+
+    def test_dlopen_handle(self):
+        if self.module is None:
+            py.test.skip("fix the auto-generation of the tiny test lib")
+        if sys.platform == 'win32':
+            py.test.skip("uses 'dl' explicitly")
+        if self.__class__.Backend is CTypesBackend:
+            py.test.skip("not for the ctypes backend")
+        backend = self.Backend()
+        ffi1 = FFI(backend=backend)
+        ffi1.cdef("""void *dlopen(const char *filename, int flags);
+                     int dlclose(void *handle);""")
+        lib1 = ffi1.dlopen('dl')
+        handle = lib1.dlopen(self.module.encode(sys.getfilesystemencoding()),
+                             backend.RTLD_LAZY)
+        assert ffi1.typeof(handle) == ffi1.typeof("void *")
+        assert handle
+
+        ffi = FFI(backend=backend)
+        ffi.cdef("""unsigned short foo_2bytes(unsigned short a);""")
+        lib = ffi.dlopen(handle)
+        x = lib.foo_2bytes(1000)
+        assert x == 1042
+
+        err = lib1.dlclose(handle)
+        assert err == 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/testing/cffi0/test_verify.py 
new/cffi-1.14.0/testing/cffi0/test_verify.py
--- old/cffi-1.13.2/testing/cffi0/test_verify.py        2019-11-03 
15:22:31.000000000 +0100
+++ new/cffi-1.14.0/testing/cffi0/test_verify.py        2020-02-07 
16:40:09.000000000 +0100
@@ -3,6 +3,7 @@
 import sys, os, math, weakref
 from cffi import FFI, VerificationError, VerificationMissing, model, FFIError
 from testing.support import *
+from testing.support import extra_compile_args
 
 
 lib_m = ['m']
@@ -13,17 +14,6 @@
         lib_m = ['msvcrt']
     pass      # no obvious -Werror equivalent on MSVC
 else:
-    if (sys.platform == 'darwin' and
-          [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]):
-        # assume a standard clang or gcc
-        extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion']
-        # special things for clang
-        extra_compile_args.append('-Qunused-arguments')
-    else:
-        # assume a standard gcc
-        extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion',
-                              '-Wno-unused-parameter']
-
     class FFI(FFI):
         def verify(self, *args, **kwds):
             return super(FFI, self).verify(
@@ -2560,3 +2550,13 @@
         """.replace('?', str(a)))
         # the verify() crashes if the values in the enum are different from
         # the values we computed ourselves from the cdef()
+
+def test_passing_large_list():
+    ffi = FFI()
+    ffi.cdef("""void passing_large_list(long[]);""")
+    lib = ffi.verify("""
+        static void passing_large_list(long a[]) { }
+    """)
+    arg = list(range(20000000))
+    lib.passing_large_list(arg)
+    # assert did not segfault
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/testing/cffi0/test_zdistutils.py 
new/cffi-1.14.0/testing/cffi0/test_zdistutils.py
--- old/cffi-1.13.2/testing/cffi0/test_zdistutils.py    2019-11-03 
15:22:31.000000000 +0100
+++ new/cffi-1.14.0/testing/cffi0/test_zdistutils.py    2020-02-07 
16:40:09.000000000 +0100
@@ -89,7 +89,7 @@
         csrc = '/*hi there %s!2*/\n#include <math.h>\n' % self
         v = Verifier(ffi, csrc, force_generic_engine=self.generic,
                      libraries=[self.lib_m])
-        basename = self.__class__.__name__ + 'test_compile_module'
+        basename = self.__class__.__name__[:10] + '_test_compile_module'
         v.modulefilename = filename = str(udir.join(basename + '.so'))
         v.compile_module()
         assert filename == v.modulefilename
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/testing/cffi1/test_new_ffi_1.py 
new/cffi-1.14.0/testing/cffi1/test_new_ffi_1.py
--- old/cffi-1.13.2/testing/cffi1/test_new_ffi_1.py     2019-11-03 
15:22:31.000000000 +0100
+++ new/cffi-1.14.0/testing/cffi1/test_new_ffi_1.py     2020-02-07 
16:40:09.000000000 +0100
@@ -1220,7 +1220,7 @@
             py.test.skip(str(e))
         f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
         f.seek(0)
-        assert f.read() == array.array('i', range(1000)).tostring()
+        assert f.read() == arraytostring(array.array('i', range(1000)))
         f.seek(0)
         b = ffi.new("int[]", 1005)
         f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int")))
@@ -1238,7 +1238,7 @@
             py.test.skip(str(e))
         f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
         f.seek(0)
-        assert f.read() == array.array('i', range(1000)).tostring()
+        assert f.read() == arraytostring(array.array('i', range(1000)))
         f.seek(0)
         b = ffi.new("int[]", 1005)
         f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int")))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/testing/cffi1/test_re_python.py 
new/cffi-1.14.0/testing/cffi1/test_re_python.py
--- old/cffi-1.13.2/testing/cffi1/test_re_python.py     2019-11-03 
15:22:31.000000000 +0100
+++ new/cffi-1.14.0/testing/cffi1/test_re_python.py     2020-02-07 
16:40:09.000000000 +0100
@@ -260,3 +260,24 @@
     # based on issue #429
     from re_python_pysrc import ffi
     ffi.new("selfref_ptr_t")
+
+def test_dlopen_handle():
+    import _cffi_backend
+    from re_python_pysrc import ffi
+    if sys.platform == 'win32':
+        py.test.skip("uses 'dl' explicitly")
+    ffi1 = FFI()
+    ffi1.cdef("""void *dlopen(const char *filename, int flags);
+                 int dlclose(void *handle);""")
+    lib1 = ffi1.dlopen('dl')
+    handle = lib1.dlopen(extmod.encode(sys.getfilesystemencoding()),
+                         _cffi_backend.RTLD_LAZY)
+    assert ffi1.typeof(handle) == ffi1.typeof("void *")
+    assert handle
+
+    lib = ffi.dlopen(handle)
+    assert lib.add42(-10) == 32
+    assert type(lib.add42) is _cffi_backend.FFI.CData
+
+    err = lib1.dlclose(handle)
+    assert err == 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/testing/cffi1/test_recompiler.py 
new/cffi-1.14.0/testing/cffi1/test_recompiler.py
--- old/cffi-1.13.2/testing/cffi1/test_recompiler.py    2019-11-03 
15:22:31.000000000 +0100
+++ new/cffi-1.14.0/testing/cffi1/test_recompiler.py    2020-02-07 
16:40:09.000000000 +0100
@@ -26,16 +26,18 @@
 
 def verify(ffi, module_name, source, *args, **kwds):
     no_cpp = kwds.pop('no_cpp', False)
+    ignore_warnings = kwds.pop('ignore_warnings', False)
     kwds.setdefault('undef_macros', ['NDEBUG'])
     module_name = '_CFFI_' + module_name
     ffi.set_source(module_name, source)
     if not os.environ.get('NO_CPP') and not no_cpp:   # test the .cpp mode too
         kwds.setdefault('source_extension', '.cpp')
         source = 'extern "C" {\n%s\n}' % (source,)
-    elif sys.platform != 'win32':
+    elif sys.platform != 'win32' and not ignore_warnings:
         # add '-Werror' to the existing 'extra_compile_args' flags
+        from testing.support import extra_compile_args
         kwds['extra_compile_args'] = (kwds.get('extra_compile_args', []) +
-                                      ['-Werror'])
+                                      extra_compile_args)
     return _verify(ffi, module_name, source, *args, **kwds)
 
 def test_set_source_no_slashes():
@@ -135,7 +137,8 @@
     import math
     ffi = FFI()
     ffi.cdef("float sin(double); double cos(double);")
-    lib = verify(ffi, 'test_math_sin', '#include <math.h>')
+    lib = verify(ffi, 'test_math_sin', '#include <math.h>',
+                 ignore_warnings=True)
     assert lib.cos(1.43) == math.cos(1.43)
 
 def test_repr_lib():
@@ -347,9 +350,9 @@
     lib = verify(ffi, 'test_verify_exact_field_offset',
                  """struct foo_s { short a; int b; };""")
     e = py.test.raises(ffi.error, ffi.new, "struct foo_s *", [])    # lazily
-    assert str(e.value) == ("struct foo_s: wrong offset for field 'b' (cdef "
-                       'says 0, but C compiler says 4). fix it or use "...;" '
-                       "in the cdef for struct foo_s to make it flexible")
+    assert str(e.value).startswith(
+        "struct foo_s: wrong offset for field 'b' (cdef "
+        'says 0, but C compiler says 4). fix it or use "...;" ')
 
 def test_type_caching():
     ffi1 = FFI(); ffi1.cdef("struct foo_s;")
@@ -644,7 +647,7 @@
     ffi.cdef("sshort_t ff3(sshort_t);")
     lib = verify(ffi, "test_include_3",
                  "typedef short sshort_t; //usually from a #include\n"
-                 "sshort_t ff3(sshort_t x) { return x + 42; }")
+                 "sshort_t ff3(sshort_t x) { return (sshort_t)(x + 42); }")
     assert lib.ff3(10) == 52
     assert ffi.typeof(ffi.cast("sshort_t", 42)) is ffi.typeof("short")
     assert ffi1.typeof("sshort_t") is ffi.typeof("sshort_t")
@@ -753,7 +756,7 @@
     ffi = FFI()
     ffi.cdef(unicode("float sin(double); double cos(double);"))
     lib = verify(ffi, 'test_math_sin_unicode', unicode('#include <math.h>'),
-                 libraries=[unicode(lib_m)])
+                 libraries=[unicode(lib_m)], ignore_warnings=True)
     assert lib.cos(1.43) == math.cos(1.43)
 
 def test_incomplete_struct_as_arg():
@@ -881,15 +884,20 @@
     e5 = py.test.raises(TypeError, lib.foo2)
     e6 = py.test.raises(TypeError, lib.foo2, 42)
     e7 = py.test.raises(TypeError, lib.foo2, 45, 46, 47)
-    assert str(e1.value) == "foo0() takes no arguments (1 given)"
-    assert str(e2.value) == "foo0() takes no arguments (2 given)"
-    assert str(e3.value) == "foo1() takes exactly one argument (0 given)"
-    assert str(e4.value) == "foo1() takes exactly one argument (2 given)"
-    assert str(e5.value) in ["foo2 expected 2 arguments, got 0",
+    def st1(s):
+        s = str(s)
+        if s.startswith("_CFFI_test_unpack_args.CompiledLib."):
+            s = s[len("_CFFI_test_unpack_args.CompiledLib."):]
+        return s
+    assert st1(e1.value) == "foo0() takes no arguments (1 given)"
+    assert st1(e2.value) == "foo0() takes no arguments (2 given)"
+    assert st1(e3.value) == "foo1() takes exactly one argument (0 given)"
+    assert st1(e4.value) == "foo1() takes exactly one argument (2 given)"
+    assert st1(e5.value) in ["foo2 expected 2 arguments, got 0",
                              "foo2() takes exactly 2 arguments (0 given)"]
-    assert str(e6.value) in ["foo2 expected 2 arguments, got 1",
+    assert st1(e6.value) in ["foo2 expected 2 arguments, got 1",
                              "foo2() takes exactly 2 arguments (1 given)"]
-    assert str(e7.value) in ["foo2 expected 2 arguments, got 3",
+    assert st1(e7.value) in ["foo2 expected 2 arguments, got 3",
                              "foo2() takes exactly 2 arguments (3 given)"]
 
 def test_address_of_function():
@@ -897,7 +905,7 @@
     ffi.cdef("long myfunc(long x);")
     lib = verify(ffi, "test_addressof_function", """
         char myfunc(char x) { return (char)(x + 42); }
-    """)
+    """, ignore_warnings=True)
     assert lib.myfunc(5) == 47
     assert lib.myfunc(0xABC05) == 47
     assert not isinstance(lib.myfunc, ffi.CData)
@@ -1170,7 +1178,7 @@
     lib = verify(ffi, 'test_some_float_invalid_3', """
         typedef long double foo_t;
         foo_t neg(foo_t x) { return -x; }
-    """)
+    """, ignore_warnings=True)
     if ffi.sizeof("long double") == ffi.sizeof("double"):
         assert lib.neg(12.3) == -12.3
     else:
@@ -1844,7 +1852,7 @@
     ffi = FFI()
     ffi.cdef("float f1(double);")
     lib = verify(ffi, 'test_introspect_function', """
-        float f1(double x) { return x; }
+        float f1(double x) { return (float)x; }
     """)
     assert dir(lib) == ['f1']
     FUNC = ffi.typeof(lib.f1)
@@ -2038,7 +2046,7 @@
     ffi.cdef("float _Complex f1(float a, float b);");
     lib = verify(ffi, "test_function_returns_float_complex", """
         #include <complex.h>
-        static float _Complex f1(float a, float b) { return a + I*2.0*b; }
+        static float _Complex f1(float a, float b) { return a + I*2.0f*b; }
     """, no_cpp=True)    # <complex.h> fails on some systems with C++
     result = lib.f1(1.25, 5.1)
     assert type(result) == complex
@@ -2149,7 +2157,8 @@
     lib = verify(ffi, "test_call_with_nested_anonymous_struct", """
         struct foo { int a; union { int b, c; }; };
         struct foo f(void) {
-            struct foo s = { 40 };
+            struct foo s;
+            s.a = 40;
             s.b = 200;
             return s;
         }
@@ -2436,3 +2445,13 @@
         };
     """)
     py.test.raises(RuntimeError, ffi.new, "struct BinaryTree *")
+
+def test_passing_large_list():
+    ffi = FFI()
+    ffi.cdef("""void passing_large_list(long[]);""")
+    lib = verify(ffi, "test_passing_large_list", """
+        static void passing_large_list(long a[]) { }
+    """)
+    arg = list(range(20000000))
+    lib.passing_large_list(arg)
+    # assert did not segfault
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/testing/cffi1/test_verify1.py 
new/cffi-1.14.0/testing/cffi1/test_verify1.py
--- old/cffi-1.13.2/testing/cffi1/test_verify1.py       2019-11-03 
15:22:31.000000000 +0100
+++ new/cffi-1.14.0/testing/cffi1/test_verify1.py       2020-02-07 
16:40:09.000000000 +0100
@@ -4,7 +4,7 @@
 from cffi import CDefError
 from cffi import recompiler
 from testing.support import *
-from testing.support import _verify
+from testing.support import _verify, extra_compile_args
 import _cffi_backend
 
 lib_m = ['m']
@@ -13,18 +13,6 @@
     import distutils.ccompiler
     if distutils.ccompiler.get_default_compiler() == 'msvc':
         lib_m = ['msvcrt']
-    extra_compile_args = []      # no obvious -Werror equivalent on MSVC
-else:
-    if (sys.platform == 'darwin' and
-          [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]):
-        # assume a standard clang or gcc
-        extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion']
-        # special things for clang
-        extra_compile_args.append('-Qunused-arguments')
-    else:
-        # assume a standard gcc
-        extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion',
-                              '-Wno-unused-parameter']
 
 class FFI(FFI):
     error = _cffi_backend.FFI.error
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cffi-1.13.2/testing/support.py 
new/cffi-1.14.0/testing/support.py
--- old/cffi-1.13.2/testing/support.py  2019-11-03 15:22:31.000000000 +0100
+++ new/cffi-1.14.0/testing/support.py  2020-02-07 16:40:09.000000000 +0100
@@ -1,7 +1,7 @@
-import sys
+import sys, os
 
 if sys.version_info < (3,):
-    __all__ = ['u']
+    __all__ = ['u', 'arraytostring']
 
     class U(object):
         def __add__(self, other):
@@ -12,12 +12,16 @@
     assert u+'a\x00b' == eval(r"u'a\x00b'")
     assert u+'a\u1234b' == eval(r"u'a\u1234b'")
     assert u+'a\U00012345b' == eval(r"u'a\U00012345b'")
+    def arraytostring(a):
+        return a.tostring()
 
 else:
-    __all__ = ['u', 'unicode', 'long']
+    __all__ = ['u', 'unicode', 'long', 'arraytostring']
     u = ""
     unicode = str
     long = int
+    def arraytostring(a):
+        return a.tobytes()
 
 
 class StdErrCapture(object):
@@ -86,3 +90,25 @@
         if not name.startswith('_') and not hasattr(module.ffi, name):
             setattr(ffi, name, NotImplemented)
     return module.lib
+
+
+# For testing, we call gcc with "-Werror".  This is fragile because newer
+# versions of gcc are always better at producing warnings, particularly for
+# auto-generated code.  We need here to adapt and silence them as needed.
+
+if sys.platform == 'win32':
+    extra_compile_args = []      # no obvious -Werror equivalent on MSVC
+else:
+    if (sys.platform == 'darwin' and
+          [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]):
+        # assume a standard clang or gcc
+        extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion',
+                              '-Wno-unused-parameter',
+                              '-Wno-unreachable-code']
+        # special things for clang
+        extra_compile_args.append('-Qunused-arguments')
+    else:
+        # assume a standard gcc
+        extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion',
+                              '-Wno-unused-parameter',
+                              '-Wno-unreachable-code']


Reply via email to