diff --git a/include/boost/dll/detail/elf_info.hpp b/include/boost/dll/detail/elf_info.hpp index 1f544f5f..44746d21 100644 --- a/include/boost/dll/detail/elf_info.hpp +++ b/include/boost/dll/detail/elf_info.hpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -154,14 +153,15 @@ class elf_info { private: template static void checked_seekg(std::ifstream& fs, Integer pos) { - /* TODO: use cmp_less, cmp_greater - if ((std::numeric_limits::max)() < pos) { - boost::throw_exception(std::runtime_error("Integral overflow while getting info from ELF file")); - } - if ((std::numeric_limits::min)() > pos){ + if (pos < 0) { boost::throw_exception(std::runtime_error("Integral underflow while getting info from ELF file")); } - */ + if (static_cast(pos) < 0) { + boost::throw_exception(std::runtime_error("Integral overflow while getting info from ELF file")); + } + + // `seekg` will throw exceptions on an attempt to get outsize of the + // file size. fs.seekg(static_cast(pos)); } diff --git a/include/boost/dll/detail/pe_info.hpp b/include/boost/dll/detail/pe_info.hpp index 63ab2b9e..28748502 100644 --- a/include/boost/dll/detail/pe_info.hpp +++ b/include/boost/dll/detail/pe_info.hpp @@ -20,8 +20,6 @@ #include // for std::getline #include -#include - namespace boost { namespace dll { namespace detail { // reference: @@ -221,7 +219,6 @@ class pe_info { } const std::size_t real_offset = get_file_offset(fs, exp_virtual_address, h); - BOOST_ASSERT(real_offset); fs.seekg(real_offset); read_raw(fs, exports); @@ -230,8 +227,6 @@ class pe_info { } static std::size_t get_file_offset(std::ifstream& fs, std::size_t virtual_address, const header_t& h) { - BOOST_ASSERT(virtual_address); - section_t image_section_header; { // fs.seekg to the beginning on section headers diff --git a/include/boost/dll/library_info.hpp b/include/boost/dll/library_info.hpp index d68d7a9a..b4f80397 100644 --- a/include/boost/dll/library_info.hpp +++ b/include/boost/dll/library_info.hpp @@ -116,6 +116,7 @@ class library_info: private boost::noncopyable { * \param library_path Path to the binary file from which the info must be extracted. * \param throw_if_not_native_format Throw an exception if this file format is not * supported by OS. + * \throws std::exception based exceptions. */ explicit library_info(const boost::dll::fs::path& library_path, bool throw_if_not_native_format = true) : f_( @@ -142,6 +143,7 @@ class library_info: private boost::noncopyable { /*! * \return List of sections that exist in binary file. + * \throws std::exception based exceptions. */ std::vector sections() { switch (fmt_) { @@ -158,6 +160,7 @@ class library_info: private boost::noncopyable { /*! * \return List of all the exportable symbols from all the sections that exist in binary file. + * \throws std::exception based exceptions. */ std::vector symbols() { switch (fmt_) { @@ -175,6 +178,7 @@ class library_info: private boost::noncopyable { /*! * \param section_name Name of the section from which symbol names must be returned. * \return List of symbols from the specified section. + * \throws std::exception based exceptions. */ std::vector symbols(const char* section_name) { switch (fmt_) { diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e69749c5..d2a52c11 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -76,6 +76,7 @@ project [ run shared_library_errors.cpp : : test_library : always_show_run_output shared ] [ run structures_tests.cpp ] [ run library_info_test.cpp ../example/tutorial4/static_plugin.cpp : : test_library : always_show_run_output shared ] + [ run broken_library_info_test.cpp : : : always_show_run_output shared ] [ run empty_library_info_test.cpp : : empty_library : always_show_run_output shared ] [ run ../example/getting_started.cpp : : getting_started_library : shared ] [ run ../example/tutorial1/tutorial1.cpp : : my_plugin_sum : shared ] diff --git a/test/broken_library_info_test.cpp b/test/broken_library_info_test.cpp new file mode 100644 index 00000000..e1ba062f --- /dev/null +++ b/test/broken_library_info_test.cpp @@ -0,0 +1,69 @@ +// Copyright Antony Polukhin, 2015-2024 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#include + +#include +#include + +#include + +int main(int argc, char* argv[]) { + BOOST_TEST(argc >= 1); + const auto self_binary = boost::filesystem::path(argv[0]); + const auto corrupted_binary = self_binary.parent_path() / "corrupted"; + + boost::filesystem::copy_file(self_binary, corrupted_binary, boost::filesystem::copy_options::overwrite_existing); + { + std::ofstream ofs{corrupted_binary.string(), std::ios::binary}; + ofs.seekp(0); + ofs << "bad"; + } + try { + boost::dll::library_info lib_info(corrupted_binary.string()); + BOOST_TEST(false); + } catch (const std::exception& ) {} + +#if BOOST_OS_WINDOWS + boost::filesystem::copy_file(self_binary, corrupted_binary, boost::filesystem::copy_options::overwrite_existing); + { + std::ofstream ofs{corrupted_binary.string(), std::ios::binary}; + ofs.seekp( + sizeof(boost::dll::detail::DWORD_) + + sizeof(boost::dll::detail::IMAGE_FILE_HEADER_) + + offsetof(boost::dll::detail::IMAGE_OPTIONAL_HEADER_template, NumberOfRvaAndSizes) + ); + const char data[] = "\0\0\0\0\0\0\0\0\0\0\0\0"; + ofs.write(data, sizeof(data)); + } + + try { + boost::dll::library_info lib_info(corrupted_binary.string()); + lib_info.sections(); + BOOST_TEST(false); + } catch (const std::exception& ) {} +#endif + +#if !BOOST_OS_WINDOWS && !BOOST_OS_MACOS && !BOOST_OS_IOS + // Elf + boost::filesystem::copy_file(self_binary, corrupted_binary, boost::filesystem::copy_options::overwrite_existing); + { + std::ofstream ofs{corrupted_binary.string(), std::ios::binary}; + ofs.seekp(40); // header->e_shoff + ofs << "\xff\xff\xff\xff"; + } + + try { + boost::dll::library_info lib_info(corrupted_binary.string()); + lib_info.sections(); + BOOST_TEST(false); + } catch (const std::exception& ) {} +#endif + + return boost::report_errors(); +}