Skip to content

Commit e6cac17

Browse files
committed
[lldb] Extend SWIG SBProcess interface with WriteMemoryAsCString method
This patch tries to address an interoperability issue when writing python string into the process memory. Since the python string is not null-terminated, it would still be written to memory however, when trying to read it again with `SBProcess::ReadCStringFromMemory`, the memory read would fail, since the read string doens't contain a null-terminator, and therefore is not a valid C string. To address that, this patch extends the `SBProcess` SWIG interface to expose a new `WriteMemoryAsCString` method that is only exposed to the SWIG target language. That method checks that the buffer to write is null-terminated and otherwise, it appends a null byte at the end of it. Signed-off-by: Med Ismail Bennani <[email protected]>
1 parent c7af9ae commit e6cac17

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

lldb/bindings/interface/SBProcessExtensions.i

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,18 @@ STRING_EXTENSION_OUTSIDE(SBProcess)
22
%extend lldb::SBProcess {
33
#ifdef SWIGPYTHON
44
%pythoncode %{
5+
def WriteMemoryAsCString(self, addr, str, error):
6+
'''
7+
WriteMemoryAsCString(self, addr, str, error):
8+
This functions the same as `WriteMemory` except a null-terminator is appended
9+
to the end of the buffer if it is not there already.
10+
'''
11+
if not str or len(str) == 0:
12+
return 0
13+
if not str[-1] == '\0':
14+
str += '\0'
15+
return self.WriteMemory(addr, str, error)
16+
517
def __get_is_alive__(self):
618
'''Returns "True" if the process is currently alive, "False" otherwise'''
719
s = self.GetState()

lldb/test/API/python_api/process/TestProcessAPI.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,32 @@ def test_write_memory(self):
186186
exe=False,
187187
startstr=b'a')
188188

189+
# Get the SBValue for the global variable 'my_cstring'.
190+
val = frame.FindValue("my_cstring", lldb.eValueTypeVariableGlobal)
191+
self.DebugSBValue(val)
192+
193+
addr = val.AddressOf().GetValueAsUnsigned()
194+
195+
# Write an empty string to memory
196+
bytes_written = process.WriteMemoryAsCString(addr, "", error)
197+
self.assertEqual(bytes_written, 0)
198+
if not error.Success():
199+
self.fail("SBProcess.WriteMemoryAsCString() failed")
200+
201+
message = "Hello!"
202+
bytes_written = process.WriteMemoryAsCString(addr, message, error)
203+
self.assertEqual(bytes_written, len(message) + 1)
204+
if not error.Success():
205+
self.fail("SBProcess.WriteMemoryAsCString() failed")
206+
207+
cstring = process.ReadCStringFromMemory(
208+
val.AddressOf().GetValueAsUnsigned(), 256, error)
209+
if not error.Success():
210+
self.fail("SBProcess.ReadCStringFromMemory() failed")
211+
212+
self.assertEqual(cstring, message)
213+
214+
189215
def test_access_my_int(self):
190216
"""Test access 'my_int' using Python SBProcess.GetByteOrder() and other APIs."""
191217
self.build()

0 commit comments

Comments
 (0)