This is an archive of the discontinued LLVM Phabricator instance.

[BSDArchive] NULL check the child object file ptr before accessing its member
ClosedPublic

Authored by kusmour on Jul 26 2023, 2:03 PM.

Details

Summary

Recently we've observed lldb crashes caused by missing object file linked to a thin archive (.a) files. The crash is due to a missing NULL check in the code when looking for child object file referred by the thin archive. Malformed archive file should not crash LLDB. Instead, it should report the error and continue.

New error message will look like the following

error: libfoo.a(__objects__/foo/barAppDelegate.mm.o) failed to load objfile for path/to/libfoo.a.
Debugging will be degraded for this module.

Test Plan:

llvm-lit test

./bin/llvm-lit -sv ../llvm-project/lldb/test/API/functionalities/archives/TestBSDArchives.py

Test without code change will error out with LLDB crash

--
Command Output (stderr):
--
PASS: LLDB (~/llvm-upstream/Debug/bin/clang-arm64) :: test (TestBSDArchives.BSDArchivesTestCase)
PASS: LLDB (~/llvm-upstream/Debug/bin/clang-arm64) :: test_frame_var_errors_when_archive_missing (TestBSDArchives.BSDArchivesTestCase)
FAIL: LLDB (~/llvm-upstream/Debug/bin/clang-arm64) :: test_frame_var_errors_when_mtime_mistmatch_for_object_in_archive (TestBSDArchives.BSDArchivesTestCase)
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      HandleCommand(command = "b a")
1.      HandleCommand(command = "breakpoint set --name 'a'")
Fatal Python error: Segmentation fault

Current thread 0x00000001f7b99e00 (most recent call first):
  File "~/llvm-upstream/Debug/bin/LLDB.framework/Resources/Python/lldb/__init__.py", line 3270 in HandleCommand
  File "~/llvm-upstream/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 2070 in runCmd
  File "~/llvm-upstream/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 2421 in expect
  File "~/llvm-upstream/llvm-project/lldb/test/API/functionalities/archives/TestBSDArchives.py", line 156 in test_frame_var_errors_when_thin_archive_malformed
...

Diff Detail

Event Timeline

kusmour created this revision.Jul 26 2023, 2:03 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 26 2023, 2:03 PM
kusmour requested review of this revision.Jul 26 2023, 2:03 PM
kusmour edited the summary of this revision. (Show Details)Jul 26 2023, 2:18 PM
bulbazord requested changes to this revision.Jul 26 2023, 2:26 PM

This makes sense to me. I have one question and one change request though.

lldb/source/Core/Module.cpp
1288–1290

Why did you switch from the llvm::formatv style to the printf style?

lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
543–545

This will only fail if child_data_sp is valid and the sizes aren't matching. You probably want to fail if child_data_sp is invalid every time, not just if the sizes differ.

This revision now requires changes to proceed.Jul 26 2023, 2:26 PM
kusmour added inline comments.Jul 26 2023, 2:37 PM
lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
543–545

If we fail on invalid child_data_sp every time, then it won't fall back to FindPlugin below. Is it guarantee that invalid child_data_sp indicates failure finding object file?

How hard it is to add an invalid archive to trigger the crash and test this code path?

kusmour updated this revision to Diff 544539.Jul 26 2023, 3:13 PM

Switch back to use llvm::formatv printf and rebase

Comment aside, I think Jeffrey brings up a good point. Can you add a test to trigger this code path? I'm not sure if you can create an archive from yaml2obj, but perhaps you can use yaml2obj to create an object file and put it into an archive?

lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
543–545

Hmm, that's a good point. Reading the implementation of ObjectFile::FindPlugin, it looks like it does have a check for child_data_sp and handles this case explicitly. My suggestion doesn't apply and what you've written is likely correct.

How hard it is to add an invalid archive to trigger the crash and test this code path?

There's API test for archive already, I will add one more test case :D

clayborg added inline comments.Jul 26 2023, 3:54 PM
lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
543–545

We should only continue calling into ObjectFile::FindPlugin if child_data_sp is valid. So this should be:

543–545

In any ObjectContainer subclasss, like ObjectContainerBSDArchive, the idea is one files contain multiple different object files. If we fail to extract the part of the data from the current container file, then there is no reason to continue. I suggest using the code I suggested above which is exactly what Alex suggested as they is the right thing to do!

How hard it is to add an invalid archive to trigger the crash and test this code path?

There's API test for archive already, I will add one more test case :D

You might see if "obj2yaml" supports BSD files. If so, you can create a simple BSD file with one .o file and then run obj2yaml on it so it can then test by running yaml2obj. The idea is you might be able to edit the yaml so that the file offsets are incorrect so we can reproduce. This might case the "yaml2obj" to fail though as there may be checks that prohibit bad BSD files from being created. Otherwise we might need to check in a .a file with a single small .o file and then do some hex editing on the file to mess up the file offset and or file size.

Another possible way to make a bad .a file is to truncate the file. We would need to figure out where to truncate it, but that might be an easier way to make a bad .a file

kusmour updated this revision to Diff 544595.Jul 26 2023, 9:49 PM
kusmour marked 4 inline comments as done.
kusmour edited the summary of this revision. (Show Details)

Added API test for malformed thin BSD archive
Addressed comments

kusmour marked an inline comment as done.Jul 26 2023, 9:50 PM
yinghuitan accepted this revision.Jul 27 2023, 9:00 AM

Assuming the test fails/crashes without the change then LGTM.

kusmour edited the summary of this revision. (Show Details)Jul 27 2023, 9:33 AM
kusmour edited the summary of this revision. (Show Details)Jul 27 2023, 9:37 AM
kusmour edited the summary of this revision. (Show Details)
bulbazord accepted this revision.Jul 27 2023, 10:13 AM

My concerns have been addressed. LGTM

This revision is now accepted and ready to land.Jul 27 2023, 10:13 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 27 2023, 10:22 AM

Hey, I think this may have broken the green dragon bots. Could you take a look and fix forward or revert? Thanks

https://green.lab.llvm.org/green/view/LLDB/job/as-lldb-cmake/3262/ (You can ignore the import-std-module tests, those have been broken some time and are being worked on AFAIK).

Hey, I think this may have broken the green dragon bots. Could you take a look and fix forward or revert? Thanks

https://green.lab.llvm.org/green/view/LLDB/job/as-lldb-cmake/3262/ (You can ignore the import-std-module tests, those have been broken some time and are being worked on AFAIK).

Fixed by commit: 4520cc066b2ffe5ac261e3aca887cba3f113b1ff