From 54de8da70ff38d351057835b8d9216d58ed659e8 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Mon, 4 Aug 2025 13:49:09 -0700 Subject: [PATCH 1/2] [lldb] Use Python Bytes instead of Buffer for Binary I/O (NFC) Binary I/O (also called buffered I/O) expects bytes-like objects and produces bytes objects [1]. Switch from using a Python buffer to using Python bytes to read the data. This eliminates calls to functions that aren't part of the Python stable C API. [1] https://docs.python.org/3/library/io.html#binary-i-o --- .../Python/PythonDataObjects.cpp | 46 +++---------------- 1 file changed, 6 insertions(+), 40 deletions(-) diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index e124954057520..ed40bd46fd4a1 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -1085,40 +1085,6 @@ class SimplePythonFile : public OwnedPythonFile { char SimplePythonFile::ID = 0; } // namespace -namespace { -class PythonBuffer { -public: - PythonBuffer &operator=(const PythonBuffer &) = delete; - PythonBuffer(const PythonBuffer &) = delete; - - static Expected Create(PythonObject &obj, - int flags = PyBUF_SIMPLE) { - Py_buffer py_buffer = {}; - PyObject_GetBuffer(obj.get(), &py_buffer, flags); - if (!py_buffer.obj) - return llvm::make_error(); - return PythonBuffer(py_buffer); - } - - PythonBuffer(PythonBuffer &&other) { - m_buffer = other.m_buffer; - other.m_buffer.obj = nullptr; - } - - ~PythonBuffer() { - if (m_buffer.obj) - PyBuffer_Release(&m_buffer); - } - - Py_buffer &get() { return m_buffer; } - -private: - // takes ownership of the buffer. - PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {} - Py_buffer m_buffer; -}; -} // namespace - // Shared methods between TextPythonFile and BinaryPythonFile namespace { class PythonIOFile : public OwnedPythonFile { @@ -1212,12 +1178,12 @@ class BinaryPythonFile : public PythonIOFile { num_bytes = 0; return Status(); } - auto pybuffer = PythonBuffer::Create(pybuffer_obj.get()); - if (!pybuffer) - // Cloning since the wrapped exception may still reference the PyThread. - return Status::FromError(pybuffer.takeError()).Clone(); - memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len); - num_bytes = pybuffer.get().get().len; + PythonBytes pybytes(PyRefType::Borrowed, pybuffer_obj->get()); + if (!pybytes) + return Status::FromErrorString("not a byte array"); + llvm::ArrayRef bytes = pybytes.GetBytes(); + memcpy(buf, bytes.begin(), bytes.size()); + num_bytes = bytes.size(); return Status(); } }; From 8775809ebba16b9397bc7e722748fde09a4450f9 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Mon, 4 Aug 2025 14:45:31 -0700 Subject: [PATCH 2/2] Return PythonException --- .../Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index ed40bd46fd4a1..2c8ed6ba1c699 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -1180,7 +1180,7 @@ class BinaryPythonFile : public PythonIOFile { } PythonBytes pybytes(PyRefType::Borrowed, pybuffer_obj->get()); if (!pybytes) - return Status::FromErrorString("not a byte array"); + return Status::FromError(llvm::make_error()); llvm::ArrayRef bytes = pybytes.GetBytes(); memcpy(buf, bytes.begin(), bytes.size()); num_bytes = bytes.size();