diff --git a/src/java_bytecode/jar_file.cpp b/src/java_bytecode/jar_file.cpp index 28a099ec934..4bab160e83d 100644 --- a/src/java_bytecode/jar_file.cpp +++ b/src/java_bytecode/jar_file.cpp @@ -62,17 +62,19 @@ jar_filet &jar_filet::operator=(jar_filet &&other) return *this; } -std::string jar_filet::get_entry(const std::string &name) +optionalt jar_filet::get_entry(const std::string &name) { const auto entry=m_name_to_index.find(name); - INVARIANT(entry!=m_name_to_index.end(), "File doesn't exist"); + if(entry==m_name_to_index.end()) + return {}; + try { return m_zip_archive.extract(entry->second); } catch(const std::runtime_error &) { - return ""; + return {}; } } @@ -96,21 +98,25 @@ static std::string trim( std::unordered_map jar_filet::get_manifest() { + const auto entry=get_entry("META-INF/MANIFEST.MF"); + + if(!entry.has_value()) + return {}; + std::unordered_map out; - const auto entry=m_name_to_index.find("META-INF/MANIFEST.MF"); - if(entry!=m_name_to_index.end()) + std::istringstream in(*entry); + std::string line; + while(std::getline(in, line)) { - std::istringstream in(this->get_entry(entry->first)); - std::string line; - while(std::getline(in, line)) + const auto key_end=std::find(line.cbegin(), line.cend(), ':'); + if(key_end!=line.cend()) { - const auto key_end=std::find(line.cbegin(), line.cend(), ':'); - if(key_end!=line.cend()) - out.emplace( - trim(line.cbegin(), key_end), - trim(std::next(key_end), line.cend())); + out.emplace( + trim(line.cbegin(), key_end), + trim(std::next(key_end), line.cend())); } } + return out; } diff --git a/src/java_bytecode/jar_file.h b/src/java_bytecode/jar_file.h index 61a89a1884c..4cf81d6f4bb 100644 --- a/src/java_bytecode/jar_file.h +++ b/src/java_bytecode/jar_file.h @@ -13,6 +13,9 @@ Author: Diffblue Ltd #include #include #include + +#include + #include "mz_zip_archive.h" class java_class_loader_limitt; @@ -41,19 +44,23 @@ class jar_filet final ~jar_filet()=default; /// Get contents of a file in the jar archive. - /// Terminates the program if file doesn't exist + /// Returns nullopt if file doesn't exist. /// \param filename Name of the file in the archive - std::string get_entry(const std::string &filename); + optionalt get_entry(const std::string &filename); + /// Get contents of the Manifest file in the jar archive std::unordered_map get_manifest(); + /// Get list of filenames in the archive std::vector filenames() const; + private: /// Loads the fileindex (m_name_to_index) with a map of loaded files to /// indices. void initialize_file_index(java_class_loader_limitt &limit); mz_zip_archivet m_zip_archive; + /// Map of filename to the file index in the zip archive. std::unordered_map m_name_to_index; }; diff --git a/src/java_bytecode/java_class_loader.cpp b/src/java_bytecode/java_class_loader.cpp index 6954e963af1..ca9c14f8062 100644 --- a/src/java_bytecode/java_class_loader.cpp +++ b/src/java_bytecode/java_class_loader.cpp @@ -91,11 +91,14 @@ optionalt java_class_loadert::get_class_from_jar( debug() << "Getting class `" << class_name << "' from JAR " << jar_file << eom; - std::string data = + auto data = jar_pool(class_loader_limit, jar_file).get_entry(jar_index_it->second); + if(!data.has_value()) + return {}; + java_bytecode_parse_treet parse_tree; - std::istringstream istream(data); + std::istringstream istream(*data); if(java_bytecode_parse(istream, parse_tree, get_message_handler())) return {}; return parse_tree;