Skip to content

Commit f4146ce

Browse files
authored
Merge pull request #9547 from swiftlang/cherrypick-e846fb48038a34d8df3ad7412bbdcf37e9e7acc9
[lldb] Prevent passing a nullptr to std::string in ObjectFileMachO (…
2 parents 19d1755 + 8dbed62 commit f4146ce

File tree

1 file changed

+104
-103
lines changed

1 file changed

+104
-103
lines changed

lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp

Lines changed: 104 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ using namespace lldb;
140140
using namespace lldb_private;
141141
using namespace llvm::MachO;
142142

143+
static constexpr llvm::StringLiteral g_loader_path = "@loader_path";
144+
static constexpr llvm::StringLiteral g_executable_path = "@executable_path";
145+
143146
LLDB_PLUGIN_DEFINE(ObjectFileMachO)
144147

145148
static void PrintRegisterValue(RegisterContext *reg_ctx, const char *name,
@@ -5145,123 +5148,121 @@ UUID ObjectFileMachO::GetUUID() {
51455148
}
51465149

51475150
uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
5151+
ModuleSP module_sp = GetModule();
5152+
if (!module_sp)
5153+
return 0;
5154+
51485155
uint32_t count = 0;
5149-
ModuleSP module_sp(GetModule());
5150-
if (module_sp) {
5151-
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
5152-
llvm::MachO::load_command load_cmd;
5153-
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
5154-
std::vector<std::string> rpath_paths;
5155-
std::vector<std::string> rpath_relative_paths;
5156-
std::vector<std::string> at_exec_relative_paths;
5157-
uint32_t i;
5158-
for (i = 0; i < m_header.ncmds; ++i) {
5159-
const uint32_t cmd_offset = offset;
5160-
if (m_data.GetU32(&offset, &load_cmd, 2) == nullptr)
5161-
break;
5156+
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
5157+
llvm::MachO::load_command load_cmd;
5158+
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
5159+
std::vector<std::string> rpath_paths;
5160+
std::vector<std::string> rpath_relative_paths;
5161+
std::vector<std::string> at_exec_relative_paths;
5162+
uint32_t i;
5163+
for (i = 0; i < m_header.ncmds; ++i) {
5164+
const uint32_t cmd_offset = offset;
5165+
if (m_data.GetU32(&offset, &load_cmd, 2) == nullptr)
5166+
break;
51625167

5163-
switch (load_cmd.cmd) {
5164-
case LC_RPATH:
5165-
case LC_LOAD_DYLIB:
5166-
case LC_LOAD_WEAK_DYLIB:
5167-
case LC_REEXPORT_DYLIB:
5168-
case LC_LOAD_DYLINKER:
5169-
case LC_LOADFVMLIB:
5170-
case LC_LOAD_UPWARD_DYLIB: {
5171-
uint32_t name_offset = cmd_offset + m_data.GetU32(&offset);
5172-
// For LC_LOAD_DYLIB there is an alternate encoding
5173-
// which adds a uint32_t `flags` field for `DYLD_USE_*`
5174-
// flags. This can be detected by a timestamp field with
5175-
// the `DYLIB_USE_MARKER` constant value.
5176-
bool is_delayed_init = false;
5177-
uint32_t use_command_marker = m_data.GetU32(&offset);
5178-
if (use_command_marker == 0x1a741800 /* DYLIB_USE_MARKER */) {
5179-
offset += 4; /* uint32_t current_version */
5180-
offset += 4; /* uint32_t compat_version */
5181-
uint32_t flags = m_data.GetU32(&offset);
5182-
// If this LC_LOAD_DYLIB is marked delay-init,
5183-
// don't report it as a dependent library -- it
5184-
// may be loaded in the process at some point,
5185-
// but will most likely not be load at launch.
5186-
if (flags & 0x08 /* DYLIB_USE_DELAYED_INIT */)
5187-
is_delayed_init = true;
5188-
}
5189-
const char *path = m_data.PeekCStr(name_offset);
5190-
if (path && !is_delayed_init) {
5191-
if (load_cmd.cmd == LC_RPATH)
5192-
rpath_paths.push_back(path);
5193-
else {
5194-
if (path[0] == '@') {
5195-
if (strncmp(path, "@rpath", strlen("@rpath")) == 0)
5196-
rpath_relative_paths.push_back(path + strlen("@rpath"));
5197-
else if (strncmp(path, "@executable_path",
5198-
strlen("@executable_path")) == 0)
5199-
at_exec_relative_paths.push_back(path +
5200-
strlen("@executable_path"));
5201-
} else {
5202-
FileSpec file_spec(path);
5203-
if (files.AppendIfUnique(file_spec))
5204-
count++;
5205-
}
5168+
switch (load_cmd.cmd) {
5169+
case LC_RPATH:
5170+
case LC_LOAD_DYLIB:
5171+
case LC_LOAD_WEAK_DYLIB:
5172+
case LC_REEXPORT_DYLIB:
5173+
case LC_LOAD_DYLINKER:
5174+
case LC_LOADFVMLIB:
5175+
case LC_LOAD_UPWARD_DYLIB: {
5176+
uint32_t name_offset = cmd_offset + m_data.GetU32(&offset);
5177+
// For LC_LOAD_DYLIB there is an alternate encoding
5178+
// which adds a uint32_t `flags` field for `DYLD_USE_*`
5179+
// flags. This can be detected by a timestamp field with
5180+
// the `DYLIB_USE_MARKER` constant value.
5181+
bool is_delayed_init = false;
5182+
uint32_t use_command_marker = m_data.GetU32(&offset);
5183+
if (use_command_marker == 0x1a741800 /* DYLIB_USE_MARKER */) {
5184+
offset += 4; /* uint32_t current_version */
5185+
offset += 4; /* uint32_t compat_version */
5186+
uint32_t flags = m_data.GetU32(&offset);
5187+
// If this LC_LOAD_DYLIB is marked delay-init,
5188+
// don't report it as a dependent library -- it
5189+
// may be loaded in the process at some point,
5190+
// but will most likely not be load at launch.
5191+
if (flags & 0x08 /* DYLIB_USE_DELAYED_INIT */)
5192+
is_delayed_init = true;
5193+
}
5194+
const char *path = m_data.PeekCStr(name_offset);
5195+
if (path && !is_delayed_init) {
5196+
if (load_cmd.cmd == LC_RPATH)
5197+
rpath_paths.push_back(path);
5198+
else {
5199+
if (path[0] == '@') {
5200+
if (strncmp(path, "@rpath", strlen("@rpath")) == 0)
5201+
rpath_relative_paths.push_back(path + strlen("@rpath"));
5202+
else if (strncmp(path, "@executable_path",
5203+
strlen("@executable_path")) == 0)
5204+
at_exec_relative_paths.push_back(path +
5205+
strlen("@executable_path"));
5206+
} else {
5207+
FileSpec file_spec(path);
5208+
if (files.AppendIfUnique(file_spec))
5209+
count++;
52065210
}
52075211
}
5208-
} break;
5209-
5210-
default:
5211-
break;
52125212
}
5213-
offset = cmd_offset + load_cmd.cmdsize;
5214-
}
5213+
} break;
52155214

5216-
FileSpec this_file_spec(m_file);
5217-
FileSystem::Instance().Resolve(this_file_spec);
5218-
5219-
if (!rpath_paths.empty()) {
5220-
// Fixup all LC_RPATH values to be absolute paths
5221-
std::string loader_path("@loader_path");
5222-
std::string executable_path("@executable_path");
5223-
for (auto &rpath : rpath_paths) {
5224-
if (llvm::StringRef(rpath).starts_with(loader_path)) {
5225-
rpath.erase(0, loader_path.size());
5226-
rpath.insert(0, this_file_spec.GetDirectory().GetCString());
5227-
} else if (llvm::StringRef(rpath).starts_with(executable_path)) {
5228-
rpath.erase(0, executable_path.size());
5229-
rpath.insert(0, this_file_spec.GetDirectory().GetCString());
5230-
}
5231-
}
5215+
default:
5216+
break;
5217+
}
5218+
offset = cmd_offset + load_cmd.cmdsize;
5219+
}
52325220

5233-
for (const auto &rpath_relative_path : rpath_relative_paths) {
5234-
for (const auto &rpath : rpath_paths) {
5235-
std::string path = rpath;
5236-
path += rpath_relative_path;
5237-
// It is OK to resolve this path because we must find a file on disk
5238-
// for us to accept it anyway if it is rpath relative.
5239-
FileSpec file_spec(path);
5240-
FileSystem::Instance().Resolve(file_spec);
5241-
if (FileSystem::Instance().Exists(file_spec) &&
5242-
files.AppendIfUnique(file_spec)) {
5243-
count++;
5244-
break;
5245-
}
5246-
}
5247-
}
5221+
FileSpec this_file_spec(m_file);
5222+
FileSystem::Instance().Resolve(this_file_spec);
5223+
5224+
if (!rpath_paths.empty()) {
5225+
// Fixup all LC_RPATH values to be absolute paths.
5226+
const std::string this_directory =
5227+
this_file_spec.GetDirectory().GetString();
5228+
for (auto &rpath : rpath_paths) {
5229+
if (llvm::StringRef(rpath).starts_with(g_loader_path))
5230+
rpath = this_directory + rpath.substr(g_loader_path.size());
5231+
else if (llvm::StringRef(rpath).starts_with(g_executable_path))
5232+
rpath = this_directory + rpath.substr(g_executable_path.size());
52485233
}
52495234

5250-
// We may have @executable_paths but no RPATHS. Figure those out here.
5251-
// Only do this if this object file is the executable. We have no way to
5252-
// get back to the actual executable otherwise, so we won't get the right
5253-
// path.
5254-
if (!at_exec_relative_paths.empty() && CalculateType() == eTypeExecutable) {
5255-
FileSpec exec_dir = this_file_spec.CopyByRemovingLastPathComponent();
5256-
for (const auto &at_exec_relative_path : at_exec_relative_paths) {
5257-
FileSpec file_spec =
5258-
exec_dir.CopyByAppendingPathComponent(at_exec_relative_path);
5235+
for (const auto &rpath_relative_path : rpath_relative_paths) {
5236+
for (const auto &rpath : rpath_paths) {
5237+
std::string path = rpath;
5238+
path += rpath_relative_path;
5239+
// It is OK to resolve this path because we must find a file on disk
5240+
// for us to accept it anyway if it is rpath relative.
5241+
FileSpec file_spec(path);
5242+
FileSystem::Instance().Resolve(file_spec);
52595243
if (FileSystem::Instance().Exists(file_spec) &&
5260-
files.AppendIfUnique(file_spec))
5244+
files.AppendIfUnique(file_spec)) {
52615245
count++;
5246+
break;
5247+
}
52625248
}
52635249
}
52645250
}
5251+
5252+
// We may have @executable_paths but no RPATHS. Figure those out here.
5253+
// Only do this if this object file is the executable. We have no way to
5254+
// get back to the actual executable otherwise, so we won't get the right
5255+
// path.
5256+
if (!at_exec_relative_paths.empty() && CalculateType() == eTypeExecutable) {
5257+
FileSpec exec_dir = this_file_spec.CopyByRemovingLastPathComponent();
5258+
for (const auto &at_exec_relative_path : at_exec_relative_paths) {
5259+
FileSpec file_spec =
5260+
exec_dir.CopyByAppendingPathComponent(at_exec_relative_path);
5261+
if (FileSystem::Instance().Exists(file_spec) &&
5262+
files.AppendIfUnique(file_spec))
5263+
count++;
5264+
}
5265+
}
52655266
return count;
52665267
}
52675268

0 commit comments

Comments
 (0)