In Python's argument parsing code (convertsimple in     Python/getargs.c), a couple of format units* accept "read-only     bytes-like objects", aka read-only buffer objects.  They call a     helper function called convertbuffer() which uses the buffer     protocol to extract a pointer to the memory.
    
    Here's the relevant bit of code:
    
static Py_ssize_t
        convertbuffer(PyObject *arg, void **p, char **errmsg)
        {
        Py_buffer view;
        ...
        
        if (getbuffer(arg, &view, errmsg) < 0)
            return -1;
        count = view.len;
        *p = view.buf;
        PyBuffer_Release(&view);
        return count;
        }

    
    
    getbuffer() uses the buffer protocol to fill in the "view" buffer.      If it's successful, "view" is a valid buffer.  We store the pointer     to the buffer's memory in output parameter p.
    
    THEN WE RELEASE THE BUFFER.
    
    THEN WE RETURN TO THE CALLER.
    
    In case you missed the big helpful capital letters, we are returning     a pointer given to us by PyObject_GetBuffer(), which we have already     released by calling PyBuffer_Release().  The buffer protocol     documentation for          bf_releasebuffer makes it sound like this pointer could easily be     invalid after the release call finishes.
    
    Am I missing something, or is this code relying on an implementation     detail it shouldn't--namely that you can continue using a pointer to     some (most? all?) buffer memory even after releasing it?
    
    
    /arry
    
    * Specifically: s# y y# z#
   ">

(original) (raw)



In Python's argument parsing code (convertsimple in Python/getargs.c), a couple of format units\* accept "read-only bytes-like objects", aka read-only buffer objects. They call a helper function called convertbuffer() which uses the buffer protocol to extract a pointer to the memory.

Here's the relevant bit of code:
static Py\_ssize\_t
convertbuffer(PyObject \*arg, void \*\*p, char \*\*errmsg)
{
Py\_buffer view;
...

if (getbuffer(arg, &view, errmsg) < 0)
return -1;
count = view.len;
\*p = view.buf;
PyBuffer\_Release(&view);
return count;
}

getbuffer() uses the buffer protocol to fill in the "view" buffer. If it's successful, "view" is a valid buffer. We store the pointer to the buffer's memory in output parameter p.

THEN WE RELEASE THE BUFFER.

THEN WE RETURN TO THE CALLER.

In case you missed the big helpful capital letters, we are returning a pointer given to us by PyObject\_GetBuffer(), which we have already released by calling PyBuffer\_Release(). The buffer protocol documentation for bf\_releasebuffer makes it sound like this pointer could easily be invalid after the release call finishes.

Am I missing something, or is this code relying on an implementation detail it shouldn't--namely that you can continue using a pointer to some (most? all?) buffer memory even after releasing it?


/arry

\* Specifically: s# y y# z#