Skip to content

[lldb/plugin] Fix heap-use-after-free in ScriptedProcess::ReadMemory #3676

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lldb/bindings/interface/SBData.i
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ public:
void
SetData (lldb::SBError& error, const void *buf, size_t size, lldb::ByteOrder endian, uint8_t addr_size);

void
SetDataWithOwnership (lldb::SBError& error, const void *buf, size_t size,
lldb::ByteOrder endian, uint8_t addr_size);

bool
Append (const SBData& rhs);

Expand Down
76 changes: 76 additions & 0 deletions lldb/bindings/python/static-binding/LLDBWrapPython.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19090,6 +19090,81 @@ SWIGINTERN PyObject *_wrap_SBData_SetData(PyObject *SWIGUNUSEDPARM(self), PyObje
}


SWIGINTERN PyObject *_wrap_SBData_SetDataWithOwnership(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
lldb::SBData *arg1 = (lldb::SBData *) 0 ;
lldb::SBError *arg2 = 0 ;
void *arg3 = (void *) 0 ;
size_t arg4 ;
lldb::ByteOrder arg5 ;
uint8_t arg6 ;
void *argp1 = 0 ;
int res1 = 0 ;
void *argp2 = 0 ;
int res2 = 0 ;
int val5 ;
int ecode5 = 0 ;
unsigned char val6 ;
int ecode6 = 0 ;
PyObject *swig_obj[5] ;

if (!SWIG_Python_UnpackTuple(args, "SBData_SetDataWithOwnership", 5, 5, swig_obj)) SWIG_fail;
res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_lldb__SBData, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SBData_SetDataWithOwnership" "', argument " "1"" of type '" "lldb::SBData *""'");
}
arg1 = reinterpret_cast< lldb::SBData * >(argp1);
res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_lldb__SBError, 0 );
if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SBData_SetDataWithOwnership" "', argument " "2"" of type '" "lldb::SBError &""'");
}
if (!argp2) {
SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SBData_SetDataWithOwnership" "', argument " "2"" of type '" "lldb::SBError &""'");
}
arg2 = reinterpret_cast< lldb::SBError * >(argp2);
{
if (PythonString::Check(swig_obj[2])) {
PythonString str(PyRefType::Borrowed, swig_obj[2]);
arg3 = (void*)str.GetString().data();
arg4 = str.GetSize();
}
else if(PythonByteArray::Check(swig_obj[2])) {
PythonByteArray bytearray(PyRefType::Borrowed, swig_obj[2]);
arg3 = (void*)bytearray.GetBytes().data();
arg4 = bytearray.GetSize();
}
else if (PythonBytes::Check(swig_obj[2])) {
PythonBytes bytes(PyRefType::Borrowed, swig_obj[2]);
arg3 = (void*)bytes.GetBytes().data();
arg4 = bytes.GetSize();
}
else {
PyErr_SetString(PyExc_ValueError, "Expecting a buffer");
return NULL;
}
}
ecode5 = SWIG_AsVal_int(swig_obj[3], &val5);
if (!SWIG_IsOK(ecode5)) {
SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SBData_SetDataWithOwnership" "', argument " "5"" of type '" "lldb::ByteOrder""'");
}
arg5 = static_cast< lldb::ByteOrder >(val5);
ecode6 = SWIG_AsVal_unsigned_SS_char(swig_obj[4], &val6);
if (!SWIG_IsOK(ecode6)) {
SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SBData_SetDataWithOwnership" "', argument " "6"" of type '" "uint8_t""'");
}
arg6 = static_cast< uint8_t >(val6);
{
SWIG_PYTHON_THREAD_BEGIN_ALLOW;
(arg1)->SetDataWithOwnership(*arg2,(void const *)arg3,arg4,arg5,arg6);
SWIG_PYTHON_THREAD_END_ALLOW;
}
resultobj = SWIG_Py_Void();
return resultobj;
fail:
return NULL;
}


SWIGINTERN PyObject *_wrap_SBData_Append(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
lldb::SBData *arg1 = (lldb::SBData *) 0 ;
Expand Down Expand Up @@ -82267,6 +82342,7 @@ static PyMethodDef SwigMethods[] = {
{ "SBData_GetDescription", _wrap_SBData_GetDescription, METH_VARARGS, "SBData_GetDescription(SBData self, SBStream description, lldb::addr_t base_addr) -> bool"},
{ "SBData_ReadRawData", _wrap_SBData_ReadRawData, METH_VARARGS, "SBData_ReadRawData(SBData self, SBError error, lldb::offset_t offset, void * buf) -> size_t"},
{ "SBData_SetData", _wrap_SBData_SetData, METH_VARARGS, "SBData_SetData(SBData self, SBError error, void const * buf, lldb::ByteOrder endian, uint8_t addr_size)"},
{ "SBData_SetDataWithOwnership", _wrap_SBData_SetDataWithOwnership, METH_VARARGS, "SBData_SetDataWithOwnership(SBData self, SBError error, void const * buf, lldb::ByteOrder endian, uint8_t addr_size)"},
{ "SBData_Append", _wrap_SBData_Append, METH_VARARGS, "SBData_Append(SBData self, SBData rhs) -> bool"},
{ "SBData_CreateDataFromCString", _wrap_SBData_CreateDataFromCString, METH_VARARGS, "SBData_CreateDataFromCString(lldb::ByteOrder endian, uint32_t addr_byte_size, char const * data) -> SBData"},
{ "SBData_CreateDataFromUInt64Array", _wrap_SBData_CreateDataFromUInt64Array, METH_VARARGS, "SBData_CreateDataFromUInt64Array(lldb::ByteOrder endian, uint32_t addr_byte_size, uint64_t * array) -> SBData"},
Expand Down
4 changes: 4 additions & 0 deletions lldb/bindings/python/static-binding/lldb.py
Original file line number Diff line number Diff line change
Expand Up @@ -3798,6 +3798,10 @@ def SetData(self, error, buf, endian, addr_size):
r"""SetData(SBData self, SBError error, void const * buf, lldb::ByteOrder endian, uint8_t addr_size)"""
return _lldb.SBData_SetData(self, error, buf, endian, addr_size)

def SetDataWithOwnership(self, error, buf, endian, addr_size):
r"""SetDataWithOwnership(SBData self, SBError error, void const * buf, lldb::ByteOrder endian, uint8_t addr_size)"""
return _lldb.SBData_SetDataWithOwnership(self, error, buf, endian, addr_size)

def Append(self, rhs):
r"""Append(SBData self, SBData rhs) -> bool"""
return _lldb.SBData_Append(self, rhs)
Expand Down
3 changes: 3 additions & 0 deletions lldb/include/lldb/API/SBData.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ class LLDB_API SBData {
void SetData(lldb::SBError &error, const void *buf, size_t size,
lldb::ByteOrder endian, uint8_t addr_size);

void SetDataWithOwnership(lldb::SBError &error, const void *buf, size_t size,
lldb::ByteOrder endian, uint8_t addr_size);

// see SetData() for why we don't have Append(const void* buf, size_t size)
bool Append(const SBData &rhs);

Expand Down
19 changes: 19 additions & 0 deletions lldb/source/API/SBData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,25 @@ void SBData::SetData(lldb::SBError &error, const void *buf, size_t size,
}
}

void SBData::SetDataWithOwnership(lldb::SBError &error, const void *buf,
size_t size, lldb::ByteOrder endian,
uint8_t addr_size) {
LLDB_RECORD_DUMMY(
void, SBData, SetData,
(lldb::SBError &, const void *, size_t, lldb::ByteOrder, uint8_t, bool),
error, buf, size, endian, addr_size, copy);

lldb::DataBufferSP buffer_sp = std::make_shared<DataBufferHeap>(buf, size);

if (!m_opaque_sp.get())
m_opaque_sp = std::make_shared<DataExtractor>(buf, size, endian, addr_size);
else {
m_opaque_sp->SetData(buffer_sp);
m_opaque_sp->SetByteOrder(endian);
m_opaque_sp->SetAddressByteSize(addr_size);
}
}

bool SBData::Append(const SBData &rhs) {
LLDB_RECORD_METHOD(bool, SBData, Append, (const lldb::SBData &), rhs);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ def create_stack_skinny_corefile(self, file):

@skipUnlessDarwin
@skipIfOutOfTreeDebugserver
@skipIfAsan # rdar://85954489
def test_launch_scripted_process_stack_frames(self):
"""Test that we can launch an lldb scripted process from the command
line, check its process ID and read string from memory."""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ def read_memory_at_address(self, addr: int, size: int) -> lldb.SBData:
if error.Fail():
return data

data.SetData(error, bytes_read, self.corefile_target.GetByteOrder(),
self.corefile_target.GetAddressByteSize())
data.SetDataWithOwnership(error, bytes_read,
self.corefile_target.GetByteOrder(),
self.corefile_target.GetAddressByteSize())

return data

Expand Down
11 changes: 11 additions & 0 deletions lldb/test/API/python_api/sbdata/TestSBData.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ def test_byte_order_and_address_byte_size(self):
self.assertEqual(addr, 0x8877665544332211);

@skipIfReproducer # SBData::SetData is not instrumented.
def test_byte_order_and_address_byte_size_with_ownership(self):
"""Test the SBData::SetDataWithOwnership() to ensure the byte order
and address byte size are obeyed even when source date is released"""
addr_data = b'\x11\x22\x33\x44\x55\x66\x77\x88'
error = lldb.SBError()
data = lldb.SBData()
data.SetDataWithOwnership(error, addr_data, lldb.eByteOrderBig, 8)
del addr_data
addr = data.GetAddress(error, 0)
self.assertEqual(addr, 0x1122334455667788);

def test_with_run_command(self):
"""Test the SBData APIs."""
self.build()
Expand Down