Skip to content

Commit 037310e

Browse files
authored
Use std::unique_ptr in pybind11_getbuffer (#5435)
* Use std::unique_ptr in pybind11_getbuffer * Move final assignment later
1 parent ce2f005 commit 037310e

File tree

1 file changed

+7
-10
lines changed

1 file changed

+7
-10
lines changed

include/pybind11/detail/class.h

+7-10
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)