Skip to content

Crash when returning a 64-bit char pointer in Python 2.6.3 ctypes #51409

Closed

Description

@creachadair
BPO 7160
Nosy @theller, @Trundle
Files
  • testlib.c: Test program to reproduce the described error.
  • crash-report.txt: MacOS X crash reporter log
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/theller'
    closed_at = <Date 2009-10-19.14:50:22.603>
    created_at = <Date 2009-10-17.16:31:03.204>
    labels = ['ctypes', 'type-crash']
    title = 'Crash when returning a 64-bit char pointer in Python 2.6.3 ctypes'
    updated_at = <Date 2009-10-19.14:50:22.602>
    user = 'https://bugs.python.org/creachadair'

    bugs.python.org fields:

    activity = <Date 2009-10-19.14:50:22.602>
    actor = 'creachadair'
    assignee = 'theller'
    closed = True
    closed_date = <Date 2009-10-19.14:50:22.603>
    closer = 'creachadair'
    components = ['ctypes']
    creation = <Date 2009-10-17.16:31:03.204>
    creator = 'creachadair'
    dependencies = []
    files = ['15154', '15155']
    hgrepos = []
    issue_num = 7160
    keywords = []
    message_count = 4.0
    messages = ['94181', '94182', '94183', '94239']
    nosy_count = 3.0
    nosy_names = ['theller', 'Trundle', 'creachadair']
    pr_nums = []
    priority = 'normal'
    resolution = None
    stage = None
    status = 'closed'
    superseder = None
    type = 'crash'
    url = 'https://bugs.python.org/issue7160'
    versions = ['Python 2.6']

    Activity

    1. creachadair commented on Oct 17, 2009

      creachadairmannequin
      MannequinAuthor

      A segmentation fault is generated in _ctypes.so when calling a function that returns a char pointer on a system
      with 64-bit pointer types. The attached crash dump is from a Python 2.6.3 built from MacPorts ("port install
      python26 +no_tkinter"), but the same behaviour occurs with the Python 2.6.1 installed by Apple.

      To reproduce, build the attached sample program ("testlib.c"):

      % gcc -Wall -c testlib.o
      % ld -dylib -o testlib.so testlib.o

      Then, in Python:

      # Common setup for each of the cases below.
      >>> from ctypes import *
      >>> lib = CDLL('testlib.so')
      
      # Case 1: Integer return value (no crash).
      >>> get_value = CFUNCTYPE(c_int)(lib.get_value)
      >>> get_value()
      12345
      
      # Case 2: Pointer argument value (no crash).
      >>> buf = create_string_buffer(256)
      >>> copy_message = CFUNCTYPE(None, c_char_p)(lib.copy_message)
      >>> copy_message(buf)
      
      # Case 3: Pointer return value (crash).
      >>> get_message = CFUNCTYPE(c_char_p)(lib.get_message)
      >>> get_message()
      Segmentation fault

      -- System information:

      % uname -a
      MacOS 10.6.1
      Darwin gorion.local 10.0.0 Darwin Kernel Version 10.0.0: Fri Jul 31 22:47:34 PDT 2009; root:xnu-
      1456.1.25~1/RELEASE_I386 i386

      % python
      Python 2.6.3 (r263:75183, Oct 17 2009, 01:49:30)
      [GCC 4.2.1 (Apple Inc. build 5646) (dot 1)] on darwin

      % gcc --version
      i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5646) (dot 1)

    2. creachadair commented on Oct 17, 2009

      creachadairmannequin
      MannequinAuthor

      I believe this error occurs because a pointer value is being truncated to
      32 bits. The exception code is

      KERN_INVALID_ADDRESS at 0x00000000002fe020

      If you add a diagnostic printout to the body of get_message(), you will
      see that its return value is 0x1002fe020, so in other words, the high-
      order word 0x00000001 is being discarded somewhere.

    3. Trundle commented on Oct 17, 2009

      Trundlemannequin
      Mannequin

      You are using CFUNCTYPE wrong. CFUNCTYPE returns a type which will
      take a Python function (or an address of a function as integer). You
      provide lib.get_message as Python function, which is a wrapper object
      for the C function. By default, ctypes assumes an int as return type for
      C functions. On your platform, the size of an int is not the same as the
      size of a pointer. Therefore, the return value is truncated. You call
      the CFUNCTION which then calls lib.get_message which returns the
      truncated pointer as integer and then ctypes tries to make a c_char_p
      out of the integer which segfaults because it's truncated.

      I think what you are really looking for is lib.get_message.restype = c_char_p.

    4. creachadair commented on Oct 19, 2009

      creachadairmannequin
      MannequinAuthor

      Thank you for setting me straight.

      I see now that I misunderstood the scope of CFUNCTYPE, as I was using
      it as a general wrapper when in fact it's only needed for callbacks.
      Mistakenly, I inferred from reading section 16.15.2.4 of the ctypes
      manual [1] that it would be necessary to create prototype wrappers for
      calls into the foreign library as well. Obviously that is not the case,
      since your described solution works fine.

      [1] <http://www.python.org/doc/2.6.3/library/ctypes.html#function-
      prototypes>

    5. transferred this issue fromon Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    Labels

    topic-ctypestype-crashA hard crash of the interpreter, possibly with a core dump

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions