@@ -583,9 +583,9 @@ extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int fla
583583 return -1 ;
584584 }
585585 std::memset (view, 0 , sizeof (Py_buffer));
586- buffer_info * info = nullptr ;
586+ std::unique_ptr< buffer_info> info = nullptr ;
587587 try {
588- info = tinfo->get_buffer (obj, tinfo->get_buffer_data );
588+ info. reset ( tinfo->get_buffer (obj, tinfo->get_buffer_data ) );
589589 } catch (...) {
590590 try_translate_exceptions ();
591591 raise_from (PyExc_BufferError, " Error getting buffer" );
@@ -596,17 +596,13 @@ extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int fla
596596 }
597597
598598 if ((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE && info->readonly ) {
599- delete info;
600599 // view->obj = nullptr; // Was just memset to 0, so not necessary
601600 set_error (PyExc_BufferError, " Writable buffer requested for readonly storage" );
602601 return -1 ;
603602 }
604603
605604 // Fill in all the information, and then downgrade as requested by the caller, or raise an
606605 // error if that's not possible.
607- view->obj = obj;
608- view->internal = info;
609- view->buf = info->ptr ;
610606 view->itemsize = info->itemsize ;
611607 view->len = view->itemsize ;
612608 for (auto s : info->shape ) {
@@ -624,23 +620,20 @@ extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int fla
624620 if ((flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS) {
625621 if (PyBuffer_IsContiguous (view, ' C' ) == 0 ) {
626622 std::memset (view, 0 , sizeof (Py_buffer));
627- delete info;
628623 set_error (PyExc_BufferError,
629624 " C-contiguous buffer requested for discontiguous storage" );
630625 return -1 ;
631626 }
632627 } else if ((flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS) {
633628 if (PyBuffer_IsContiguous (view, ' F' ) == 0 ) {
634629 std::memset (view, 0 , sizeof (Py_buffer));
635- delete info;
636630 set_error (PyExc_BufferError,
637631 " Fortran-contiguous buffer requested for discontiguous storage" );
638632 return -1 ;
639633 }
640634 } else if ((flags & PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS) {
641635 if (PyBuffer_IsContiguous (view, ' A' ) == 0 ) {
642636 std::memset (view, 0 , sizeof (Py_buffer));
643- delete info;
644637 set_error (PyExc_BufferError, " Contiguous buffer requested for discontiguous storage" );
645638 return -1 ;
646639 }
@@ -650,7 +643,6 @@ extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int fla
650643 // https://docs.python.org/3/c-api/buffer.html#contiguity-requests
651644 if (PyBuffer_IsContiguous (view, ' C' ) == 0 ) {
652645 std::memset (view, 0 , sizeof (Py_buffer));
653- delete info;
654646 set_error (PyExc_BufferError,
655647 " C-contiguous buffer requested for discontiguous storage" );
656648 return -1 ;
@@ -665,6 +657,11 @@ extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int fla
665657 }
666658 }
667659
660+ // Set these after all checks so they don't leak out into the caller, and can be automatically
661+ // cleaned up on error.
662+ view->buf = info->ptr ;
663+ view->internal = info.release ();
664+ view->obj = obj;
668665 Py_INCREF (view->obj );
669666 return 0 ;
670667}
0 commit comments