This is an archive of the discontinued LLVM Phabricator instance.

[lldb] Update some uses of Python2 API in typemaps.
ClosedPublic

Authored by jgorbe on Mar 21 2023, 3:50 PM.

Details

Summary

Python 3 doesn't have a distinction between PyInt and PyLong, it's all
PyLong now.

This also fixes a bug in SetNumberFromObject. This used to crash LLDB:

lldb -o "script data=lldb.SBData(); data.SetDataFromUInt64Array([2**63])"

The problem happened in the PyInt path:

if (PyInt_Check(obj))
    number = static_cast<T>(PyInt_AsLong(obj));

when obj doesn't fit in a signed long, PyInt_AsLong would fail with
"OverflowError: Python int too large to convert to C long".

The existing long path does the right thing, as it will call
PyLong_AsUnsignedLongLong for uint64_t.

Diff Detail

Event Timeline

jgorbe created this revision.Mar 21 2023, 3:50 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 21 2023, 3:50 PM
jgorbe requested review of this revision.Mar 21 2023, 3:50 PM

Can you add a regression test that invokes lldb -o "script data=lldb.SBData(); data.SetDataFromUInt64Array([2**63])"? Just a simple shell test should suffice.

LGTM, but it'd be nice if someone else can look too. Adding some other people that have been here recently.

lldb -o "script data=lldb.SBData(); data.SetDataFromUInt64Array([2**63])"

Just tried this, didn't crash LLDB but it does give me the OverflowError you mentioned.

Either way, this is probably okay? What do you think @mib?

lldb -o "script data=lldb.SBData(); data.SetDataFromUInt64Array([2**63])"

Just tried this, didn't crash LLDB but it does give me the OverflowError you mentioned.

Here's what the crash looks like for me:

$ bin/lldb -o "script data=lldb.SBData(); data.SetDataFromUInt64Array([2**63])"
(lldb) script data=lldb.SBData(); data.SetDataFromUInt64Array([2**63])
free(): double free detected in tcache 2
LLDB diagnostics will be written to /tmp/diagnostics-98b663
Please include the directory content when filing a bug report
Aborted
mib accepted this revision.Mar 21 2023, 7:25 PM

Yep, LGTM!

This revision is now accepted and ready to land.Mar 21 2023, 7:25 PM
jgorbe updated this revision to Diff 507442.Mar 22 2023, 11:25 AM

Modified one of the existing test cases for SBData.SetDataFromUInt64Array to add a 2**63 to actually exercise the uint64 range.

This revision was landed with ongoing or failed builds.Mar 22 2023, 11:30 AM
This revision was automatically updated to reflect the committed changes.

I found the actual reason for the crash I was talking about. This patch only addressed the incorrect OverflowError, but the crash comes from a double free (as @rupprecht mentioned) in the error handling logic. The error path here does both free($1); and SWIG_fail;. The same goes for another error check a few lines below that. In the generated code, the SWIG_fail macro is expanded to goto fail and the fail label also frees the same memory buffer.

I believe (but I don't have any experience with SWIG typemaps so this is an educated guess) that the call to free in the error path comes from the %typemap(freearg) immediately after that one. So if freearg already takes care of it, the error handling logic in %typemap(in) should just call SWIG_fail. Does that sound correct?

I believe (but I don't have any experience with SWIG typemaps so this is an educated guess) that the call to free in the error path comes from the %typemap(freearg) immediately after that one. So if freearg already takes care of it, the error handling logic in %typemap(in) should just call SWIG_fail. Does that sound correct?

Makes sense to me.

I found the actual reason for the crash I was talking about. This patch only addressed the incorrect OverflowError, but the crash comes from a double free (as @rupprecht mentioned) in the error handling logic. The error path here does both free($1); and SWIG_fail;. The same goes for another error check a few lines below that. In the generated code, the SWIG_fail macro is expanded to goto fail and the fail label also frees the same memory buffer.

I believe (but I don't have any experience with SWIG typemaps so this is an educated guess) that the call to free in the error path comes from the %typemap(freearg) immediately after that one. So if freearg already takes care of it, the error handling logic in %typemap(in) should just call SWIG_fail. Does that sound correct?

Yea, after reading the SWIG documentation, this diagnosis looks correct. If you'd like to fix this feel free to upload a patch and list myself and @mib as reviewers. Otherwise let me know and I can take care of it. Thanks for doing that investigation!

Yea, after reading the SWIG documentation, this diagnosis looks correct. If you'd like to fix this feel free to upload a patch and list myself and @mib as reviewers. Otherwise let me know and I can take care of it. Thanks for doing that investigation!

Thanks! Just sent you all https://reviews.llvm.org/D147007