Skip to content

Commit 043a863

Browse files
committed
[SharedCache] Bubble up errors in CacheEntry::FromFile to the user
Prior to this we would not have meaningful errors shown to the user when we fail to construct a CacheEntry from a file. Apart of trying to make the opening of shared caches clearer.
1 parent 664bdcd commit 043a863

File tree

3 files changed

+24
-15
lines changed

3 files changed

+24
-15
lines changed

view/sharedcache/core/SharedCache.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ std::vector<std::string> CacheImage::GetDependencies() const
3636
}
3737

3838
CacheEntry::CacheEntry(std::string filePath, std::string fileName, CacheEntryType type, dyld_cache_header header,
39-
std::vector<dyld_cache_mapping_info> mappings, std::vector<std::pair<std::string, dyld_cache_image_info>> images)
39+
std::vector<dyld_cache_mapping_info>&& mappings, std::vector<std::pair<std::string, dyld_cache_image_info>>&& images)
4040
{
4141
m_filePath = std::move(filePath);
4242
m_fileName = std::move(fileName);
@@ -46,7 +46,7 @@ CacheEntry::CacheEntry(std::string filePath, std::string fileName, CacheEntryTyp
4646
m_images = std::move(images);
4747
}
4848

49-
std::optional<CacheEntry> CacheEntry::FromFile(const std::string& filePath, const std::string& fileName, CacheEntryType type)
49+
CacheEntry CacheEntry::FromFile(const std::string& filePath, const std::string& fileName, CacheEntryType type)
5050
{
5151
auto file = FileAccessorCache::Global().Open(filePath).lock();
5252

@@ -55,22 +55,33 @@ std::optional<CacheEntry> CacheEntry::FromFile(const std::string& filePath, cons
5555
// All entries must start with "dyld".
5656
DataBuffer sig = file->ReadBuffer(0, 4);
5757
if (sig.GetLength() != 4)
58-
return std::nullopt;
59-
const char* magic = (char*)sig.GetData();
58+
throw std::runtime_error("File is empty!");
59+
const char* magic = static_cast<char*>(sig.GetData());
6060
if (strncmp(magic, "dyld", 4) != 0)
61-
return std::nullopt;
61+
throw std::runtime_error("File does not start with `dyld`!");
6262

6363
// Read the header, this _should_ be compatible with all known DSC formats.
6464
// Mason: the above is not true! https://github.com/Vector35/binaryninja-api/issues/6073
6565
dyld_cache_header header = {};
6666
file->Read(&header, 0, sizeof(header));
6767

68+
// Adjust the array count to actually be the "real" number for comparisons with what we load.
69+
// This is required so we can check if we loaded the required number of caches, in view init.
70+
header.subCacheArrayCount += header.cacheSubType;
71+
6872
// Read the mappings using the headers `mappingCount` and `mappingOffset`.
6973
dyld_cache_mapping_info currentMapping = {};
7074
std::vector<dyld_cache_mapping_info> mappings;
7175
for (size_t i = 0; i < header.mappingCount; i++)
7276
{
7377
file->Read(&currentMapping, header.mappingOffset + (i * sizeof(currentMapping)), sizeof(currentMapping));
78+
79+
// Cancel adding the entry if we have an invalid mapping.
80+
if (currentMapping.fileOffset + currentMapping.size > file->Length())
81+
throw std::runtime_error("Invalid mapping in shared cache entry");
82+
83+
// TODO: Check initProt to make sure its in the range of expected values.
84+
7485
mappings.push_back(currentMapping);
7586
}
7687

@@ -134,7 +145,7 @@ std::optional<CacheEntry> CacheEntry::FromFile(const std::string& filePath, cons
134145
images.emplace_back(imageName, branchIslandImg);
135146
}
136147

137-
return CacheEntry(filePath, fileName, type, header, mappings, images);
148+
return {filePath, fileName, type, header, std::move(mappings), std::move(images)};
138149
}
139150

140151
WeakFileAccessor CacheEntry::GetAccessor() const

view/sharedcache/core/SharedCache.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ class CacheEntry
130130

131131
public:
132132
CacheEntry(std::string filePath, std::string fileName, CacheEntryType type, dyld_cache_header header,
133-
std::vector<dyld_cache_mapping_info> mappings, std::vector<std::pair<std::string, dyld_cache_image_info>> images);
133+
std::vector<dyld_cache_mapping_info>&& mappings, std::vector<std::pair<std::string, dyld_cache_image_info>>&& images);
134134

135135
CacheEntry() = default;
136136
CacheEntry(const CacheEntry&) = default;
@@ -139,7 +139,7 @@ class CacheEntry
139139
CacheEntry& operator=(CacheEntry&&) = default;
140140

141141
// Construct a cache entry from the file on disk.
142-
static std::optional<CacheEntry> FromFile(const std::string& filePath, const std::string& fileName, CacheEntryType type);
142+
static CacheEntry FromFile(const std::string& filePath, const std::string& fileName, CacheEntryType type);
143143

144144
WeakFileAccessor GetAccessor() const;
145145

view/sharedcache/core/SharedCacheBuilder.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,17 @@ bool SharedCacheBuilder::AddFile(
3737

3838
try
3939
{
40-
if (auto entry = CacheEntry::FromFile(filePath, fileName, cacheType))
41-
{
42-
m_cache.AddEntry(std::move(*entry));
43-
return true;
44-
}
40+
auto entry = CacheEntry::FromFile(filePath, fileName, cacheType);
41+
m_cache.AddEntry(std::move(entry));
4542
}
4643
catch (const std::exception& e)
4744
{
4845
// Just return false so the view init can continue.
49-
m_logger->LogErrorF("Failed to add file {}... {}", fileName, e.what());
46+
m_logger->LogErrorF("Failed to add file '{}': {}", fileName, e.what());
47+
return false;
5048
}
5149

52-
return false;
50+
return true;
5351
}
5452

5553
size_t SharedCacheBuilder::AddDirectory(const std::string& directoryPath)

0 commit comments

Comments
 (0)