New submission from Mark Dickinson:

The argument-passing code for passing structs larger than 8 bytes is broken on 
64-bit Windows, leading to potential segmentation faults or other unpredictable 
behaviour.  According to 

   http://msdn.microsoft.com/en-us/library/zthk2dkh.aspx

structs not of size 1, 2, 4 or 8 bytes should be passed by pointer.  ctypes 
instead puts sizeof(struct) bytes onto the stack.  The offending code is in 
ffi_prep_args in /Modules/_ctypes/libffi_msvc/ffi.c, which apparently hasn't 
been kept up to date with the /Modules/_ctypes/libffi/src/x86/ffi.c.  The 
latter module works correctly: it has an extra #ifdef X86_WIN64 block (shown 
below) to take care of structs not of size 1, 2, 4 or 8. That block is missing 
in the libffi_msvc version.

      z = (*p_arg)->size;
#ifdef X86_WIN64
      if (z > sizeof(ffi_arg)
          || ((*p_arg)->type == FFI_TYPE_STRUCT
              && (z != 1 && z != 2 && z != 4 && z != 8))
#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
          || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
#endif
          )
        {
          z = sizeof(ffi_arg);
          *(void **)argp = *p_argv;
        }
      else if ((*p_arg)->type == FFI_TYPE_FLOAT)
        {
          memcpy(argp, *p_argv, z);
        }
      else
#endif


It looks to me as though issue 17310 may be related.

Credit for this discovery should go to Freek Mank.

----------
components: ctypes
messages: 207520
nosy: mark.dickinson
priority: high
severity: normal
status: open
title: broken ctypes calling convention on MSVC / 64-bit Windows (large structs)
type: crash
versions: Python 2.7, Python 3.3, Python 3.4

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue20160>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to