ffi.from_buffer("c type", python_buffer)

Issue #398 new
Armin Rigo
created an issue

One problem of ffi.from_buffer(python_buffer) is that it returns a char[], and if we actually want another type we need to cast. But the original char[] holds the python_buffer alive, whereas the casted version no longer does. Think about allowing ffi.from_buffer("ptr-or-array-type", python_buffer).

Comments (3)

  1. Dark F

    Bizarrely, I just ran into this same issue tonight and was going to report it.

    Here's a test case. It should segfault unless you uncomment the line making a reference to it:

    import mmap
    import cffi
    
    ffi = cffi.FFI()
    
    ffi.cdef("struct test { int x; };")
    
    ref = None
    
    def alloc():
        global ref
    
        mem = mmap.mmap(-1, 0x1000, mmap.MAP_SHARED, mmap.PROT_READ | mmap.PROT_WRITE)
    
        # Uncomment this to keep mem alive
        #ref = mem
    
        return ffi.cast("struct test *", ffi.from_buffer(mem))
    
    def main():
        test = alloc()
        print(test.x)
    
    if __name__ == "__main__":
        main()
    
  2. Armin Rigo reporter

    I have now implemented it, but you can only say ffi.from_buffer("array-type", mem). Do you really have a test case where you need just a struct pointer, and not an array of structs? The two are kind of similar, but you don't have the shortcut test.x if test is a <cdata 'struct test[]'>.

  3. Dark F

    Yes, I have an mmap'd region with a big struct (plus some other data after it; this is actually for KVM which tells you how much to allocate beforehand, the struct going first and then some data at unknown offsets later on.)

    I'm currently just working around this by keeping the buffer around which I need anyway, but it would be nice if that weren't necessary -- if it's too much to implement, then at least explicitly document this behavior in from_buffer and/or cast, so it doesn't lead to surprise segfaults.

  4. Log in to comment