aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar David Leverton <levertond@googlemail.com> 2007-10-26 14:00:49 +0000
committerAvatar David Leverton <levertond@googlemail.com> 2007-10-26 14:00:49 +0000
commit9bd1a81d8d6c6692aa49b988413c135f3b055cba (patch)
tree51623ecfa76725bc7b7ca99ff6b6713eb6561b40
parentf46e0731d1fc5f4216e8c40ae7b5bc2d6ffeb74b (diff)
downloadpaludis-9bd1a81d8d6c6692aa49b988413c135f3b055cba.tar.gz
paludis-9bd1a81d8d6c6692aa49b988413c135f3b055cba.tar.xz
Be more strict / robust / compliant.
-rw-r--r--src/clients/reconcilio/littlelf/elf.cc58
-rw-r--r--src/clients/reconcilio/littlelf/elf_dynamic_section.cc33
-rw-r--r--src/clients/reconcilio/littlelf/elf_sections.cc2
-rw-r--r--src/clients/reconcilio/littlelf/elf_symbol_section.cc29
4 files changed, 88 insertions, 34 deletions
diff --git a/src/clients/reconcilio/littlelf/elf.cc b/src/clients/reconcilio/littlelf/elf.cc
index aedde96..cdcf7b6 100644
--- a/src/clients/reconcilio/littlelf/elf.cc
+++ b/src/clients/reconcilio/littlelf/elf.cc
@@ -14,6 +14,7 @@
#include <string>
#include <exception>
+#include <stdexcept>
#include <istream>
#include <vector>
@@ -73,12 +74,18 @@ namespace
virtual void visit(SymbolSection<ElfType_> & section)
{
- section.resolve_symbols(*_elf_object->get_section_by_index(section.get_link_index()));
+ typename ElfObject<ElfType_>::SectionIterator sec(_elf_object->get_section_by_index(section.get_link_index()));
+ if (_elf_object->section_end() == sec)
+ throw InvalidElfFileError();
+ section.resolve_symbols(*sec);
}
virtual void visit(DynamicSection<ElfType_> & section)
{
- section.resolve_entry_names(*_elf_object->get_section_by_index(section.get_link_index()));
+ typename ElfObject<ElfType_>::SectionIterator sec(_elf_object->get_section_by_index(section.get_link_index()));
+ if (_elf_object->section_end() == sec)
+ throw InvalidElfFileError();
+ section.resolve_entry_names(*sec);
}
};
}
@@ -103,8 +110,15 @@ namespace littlelf_internals
virtual void visit(const StringSection<ElfType_> & section)
{
- for (typename ElfObject<ElfType_>::SectionIterator i = _begin; i != _end; ++i)
- i->resolve_section_name(section.get_string(i->get_name_index()));
+ try
+ {
+ for (typename ElfObject<ElfType_>::SectionIterator i = _begin; i != _end; ++i)
+ i->resolve_section_name(section.get_string(i->get_name_index()));
+ }
+ catch (std::out_of_range &)
+ {
+ throw InvalidElfFileError();
+ }
}
};
}
@@ -167,10 +181,33 @@ ElfObject<ElfType_>::ElfObject(std::istream & stream) :
stream.seekg(0, std::ios::beg);
stream.read(reinterpret_cast<char *>(&_hdr), sizeof(typename ElfType_::Header));
- stream.seekg(_hdr.e_shoff, std::ios::beg);
- // The standard guarantees that there's at least one section
- std::vector<typename ElfType_::SectionHeader> shdrs(_hdr.e_shnum);
- stream.read(reinterpret_cast<char *>(&shdrs.front()), sizeof(typename ElfType_::SectionHeader) * _hdr.e_shnum);
+
+ std::vector<typename ElfType_::SectionHeader> shdrs;
+ if (_hdr.e_shoff)
+ {
+ if (sizeof(typename ElfType_::SectionHeader) != _hdr.e_shentsize)
+ throw InvalidElfFileError();
+ stream.seekg(_hdr.e_shoff, std::ios::beg);
+
+ if (_hdr.e_shnum)
+ {
+ std::vector<typename ElfType_::SectionHeader> my_shdrs(_hdr.e_shnum);
+ stream.read(reinterpret_cast<char *>(&my_shdrs.front()), sizeof(typename ElfType_::SectionHeader) * _hdr.e_shnum);
+ shdrs.swap(my_shdrs);
+ }
+ else
+ {
+ typename ElfType_::SectionHeader first_shdr;
+ stream.read(reinterpret_cast<char *>(&first_shdr), sizeof(typename ElfType_::SectionHeader));
+ if (0 == first_shdr.sh_size)
+ throw InvalidElfFileError();
+
+ std::vector<typename ElfType_::SectionHeader> my_shdrs(first_shdr.sh_size);
+ my_shdrs[0] = first_shdr;
+ stream.read(reinterpret_cast<char *>(&my_shdrs[1]), sizeof(typename ElfType_::SectionHeader) * (first_shdr.sh_size - 1));
+ shdrs.swap(my_shdrs);
+ }
+ }
for (typename std::vector<typename ElfType_::SectionHeader>::iterator i = shdrs.begin(); i != shdrs.end(); ++i)
{
@@ -190,9 +227,12 @@ ElfObject<ElfType_>::ElfObject(std::istream & stream) :
if (! _hdr.e_shstrndx)
return;
+ typename ElfType_::Half shstrndx(SHN_XINDEX == _hdr.e_shstrndx ? shdrs[0].sh_link : _hdr.e_shstrndx);
+ if (_imp->sections.size() <= shstrndx)
+ throw InvalidElfFileError();
littlelf_internals::SectionNameResolvingVisitor<ElfType_> res(section_begin(), section_end());
- _imp->sections[_hdr.e_shstrndx]->accept(res);
+ _imp->sections[shstrndx]->accept(res);
}
catch (const std::ios_base::failure &)
{
diff --git a/src/clients/reconcilio/littlelf/elf_dynamic_section.cc b/src/clients/reconcilio/littlelf/elf_dynamic_section.cc
index 18aa4eb..293f508 100644
--- a/src/clients/reconcilio/littlelf/elf_dynamic_section.cc
+++ b/src/clients/reconcilio/littlelf/elf_dynamic_section.cc
@@ -1,6 +1,7 @@
#include "elf_dynamic_section.hh"
#include "elf_types.hh"
+#include "elf.hh"
#include <paludis/util/clone-impl.hh>
#include <paludis/util/instantiation_policy-impl.hh>
@@ -14,6 +15,7 @@
#include <istream>
#include <map>
#include <vector>
+#include <stdexcept>
using namespace paludis;
@@ -51,7 +53,14 @@ namespace littlelf_internals
virtual void visit(DynamicEntryString<ElfType_> & entry)
{
- entry.resolve_string(_string_section.get_string(entry.get_string_index()));
+ try
+ {
+ entry.resolve_string(_string_section.get_string(entry.get_string_index()));
+ }
+ catch (std::out_of_range &)
+ {
+ throw InvalidElfFileError();
+ }
}
};
}
@@ -233,18 +242,18 @@ DynamicSection<ElfType_>::DynamicSection(const typename ElfType_::SectionHeader
Section<ElfType_>(shdr),
PrivateImplementationPattern<DynamicSection>(new Implementation<DynamicSection>)
{
- if (0 != shdr.sh_entsize)
+ if (sizeof(typename ElfType_::DynamicEntry) != shdr.sh_entsize)
+ throw InvalidElfFileError();
+
+ stream.seekg(shdr.sh_offset, std::ios::beg);
+ std::vector<typename ElfType_::DynamicEntry> tmp_entries(shdr.sh_size / sizeof(typename ElfType_::DynamicEntry));
+ stream.read( reinterpret_cast<char *>(&tmp_entries.front()), shdr.sh_size );
+
+ for (typename std::vector<typename ElfType_::DynamicEntry>::iterator i = tmp_entries.begin(); i != tmp_entries.end(); ++i)
{
- stream.seekg(shdr.sh_offset, std::ios::beg);
- std::vector<typename ElfType_::DynamicEntry> tmp_entries(shdr.sh_size / shdr.sh_entsize);
- stream.read( reinterpret_cast<char *>(&tmp_entries.front()), shdr.sh_size );
-
- for (typename std::vector<typename ElfType_::DynamicEntry>::iterator i = tmp_entries.begin(); i != tmp_entries.end(); ++i)
- {
- paludis::tr1::shared_ptr<DynamicEntry<ElfType_> > instance(DynamicEntries<ElfType_>::get_instance()->get_entry(i->d_tag));
- instance->initialize(*i);
- _imp->dynamic_entries.push_back(instance);
- }
+ paludis::tr1::shared_ptr<DynamicEntry<ElfType_> > instance(DynamicEntries<ElfType_>::get_instance()->get_entry(i->d_tag));
+ instance->initialize(*i);
+ _imp->dynamic_entries.push_back(instance);
}
}
diff --git a/src/clients/reconcilio/littlelf/elf_sections.cc b/src/clients/reconcilio/littlelf/elf_sections.cc
index c50419d..5e00621 100644
--- a/src/clients/reconcilio/littlelf/elf_sections.cc
+++ b/src/clients/reconcilio/littlelf/elf_sections.cc
@@ -60,8 +60,6 @@ template <typename ElfType_>
std::string
StringSection<ElfType_>::get_string(typename ElfType_::Word index) const
{
- if (index > _stringTable.size())
- return "";
typename ElfType_::Word end(_stringTable.find_first_of('\0', index));
return _stringTable.substr(index, end-index);
}
diff --git a/src/clients/reconcilio/littlelf/elf_symbol_section.cc b/src/clients/reconcilio/littlelf/elf_symbol_section.cc
index 1082c98..6ddcab0 100644
--- a/src/clients/reconcilio/littlelf/elf_symbol_section.cc
+++ b/src/clients/reconcilio/littlelf/elf_symbol_section.cc
@@ -1,6 +1,7 @@
#include "elf_symbol_section.hh"
#include "elf_types.hh"
+#include "elf.hh"
#include <paludis/util/private_implementation_pattern-impl.hh>
#include <paludis/util/visitor-impl.hh>
@@ -9,6 +10,7 @@
#include <istream>
#include <vector>
+#include <stdexcept>
using namespace paludis;
@@ -41,9 +43,15 @@ namespace littlelf_internals
virtual void visit(StringSection<ElfType_> & section)
{
- std::string str;
- for (typename std::vector<Symbol<ElfType_> >::iterator i = _begin; i != _end; ++i)
- i->resolve_symbol(section.get_string(i->get_symbol_index()));
+ try
+ {
+ for (typename std::vector<Symbol<ElfType_> >::iterator i = _begin; i != _end; ++i)
+ i->resolve_symbol(section.get_string(i->get_symbol_index()));
+ }
+ catch (std::out_of_range &)
+ {
+ throw InvalidElfFileError();
+ }
}
};
}
@@ -116,14 +124,13 @@ SymbolSection<ElfType_>::SymbolSection(const typename ElfType_::SectionHeader &
else if (shdr.sh_type == SHT_SYMTAB)
_type = "SYMTAB";
- if (0 != shdr.sh_entsize)
- {
- std::vector<typename ElfType_::Symbol> symbols(shdr.sh_size / shdr.sh_entsize);
- stream.seekg(shdr.sh_offset, std::ios::beg);
- stream.read( reinterpret_cast<char *>(&symbols.front()), shdr.sh_size );
- for (typename std::vector<typename ElfType_::Symbol>::iterator i = symbols.begin(); i != symbols.end(); ++i)
- _imp->symbols.push_back(Symbol<ElfType_>(*i));
- }
+ if (sizeof(typename ElfType_::Symbol) != shdr.sh_entsize)
+ throw InvalidElfFileError();
+ std::vector<typename ElfType_::Symbol> symbols(shdr.sh_size / sizeof(typename ElfType_::Symbol));
+ stream.seekg(shdr.sh_offset, std::ios::beg);
+ stream.read( reinterpret_cast<char *>(&symbols.front()), shdr.sh_size );
+ for (typename std::vector<typename ElfType_::Symbol>::iterator i = symbols.begin(); i != symbols.end(); ++i)
+ _imp->symbols.push_back(Symbol<ElfType_>(*i));
}
template <typename ElfType_>