summaryrefslogtreecommitdiff
path: root/lib/Object/Archive.cpp
diff options
context:
space:
mode:
authorMichael J. Spencer <bigcheesegs@gmail.com>2012-11-14 00:04:13 +0000
committerMichael J. Spencer <bigcheesegs@gmail.com>2012-11-14 00:04:13 +0000
commit768a707fdfd0be3587864b9b9edcc74aa0acdf92 (patch)
tree0317439bb55daad88910b9e3bda6ea62ed02d274 /lib/Object/Archive.cpp
parente123fd9c5956962d414693ee8ad83498413af6ce (diff)
downloadllvm-768a707fdfd0be3587864b9b9edcc74aa0acdf92.tar.gz
llvm-768a707fdfd0be3587864b9b9edcc74aa0acdf92.tar.bz2
llvm-768a707fdfd0be3587864b9b9edcc74aa0acdf92.tar.xz
[Object] Fix endianess bug by refactoring Archive::Symbol::getMember.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@167893 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Object/Archive.cpp')
-rw-r--r--lib/Object/Archive.cpp50
1 files changed, 32 insertions, 18 deletions
diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp
index b55dab8f85..28d052e12d 100644
--- a/lib/Object/Archive.cpp
+++ b/lib/Object/Archive.cpp
@@ -265,31 +265,45 @@ error_code Archive::Symbol::getName(StringRef &Result) const {
}
error_code Archive::Symbol::getMember(child_iterator &Result) const {
- const char *buf = Parent->SymbolTable->getBuffer()->getBufferStart();
- const char *offsets = buf + 4;
- uint32_t offset = 0;
+ const char *Buf = Parent->SymbolTable->getBuffer()->getBufferStart();
+ const char *Offsets = Buf + 4;
+ uint32_t Offset = 0;
if (Parent->kind() == K_GNU) {
- offset = *(reinterpret_cast<const support::ubig32_t*>(offsets)
- + SymbolIndex);
+ Offset = *(reinterpret_cast<const support::ubig32_t*>(Offsets)
+ + SymbolIndex);
} else if (Parent->kind() == K_BSD) {
assert("BSD format is not supported");
} else {
- uint32_t member_count = 0;
- member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
- buf += 4 + (member_count * 4); // Skip offsets.
- const char *indicies = buf + 4;
- uint16_t offsetindex =
- *(reinterpret_cast<const support::ulittle16_t*>(indicies)
+ uint32_t MemberCount = *reinterpret_cast<const support::ulittle32_t*>(Buf);
+
+ // Skip offsets.
+ Buf += sizeof(support::ulittle32_t)
+ + (MemberCount * sizeof(support::ulittle32_t));
+
+ uint32_t SymbolCount = *reinterpret_cast<const support::ulittle32_t*>(Buf);
+
+ if (SymbolIndex >= SymbolCount)
+ return object_error::parse_failed;
+
+ // Skip SymbolCount to get to the indicies table.
+ const char *Indicies = Buf + sizeof(support::ulittle32_t);
+
+ // Get the index of the offset in the file member offset table for this
+ // symbol.
+ uint16_t OffsetIndex =
+ *(reinterpret_cast<const support::ulittle16_t*>(Indicies)
+ SymbolIndex);
- uint32_t *offsetaddr =
- (uint32_t *)(reinterpret_cast<const support::ulittle32_t*>(offsets)
- + (offsetindex - 1));
- assert((const char *)offsetaddr <
- Parent->SymbolTable->getBuffer()->getBufferEnd());
- offset = *(offsetaddr);
+ // Subtract 1 since OffsetIndex is 1 based.
+ --OffsetIndex;
+
+ if (OffsetIndex >= MemberCount)
+ return object_error::parse_failed;
+
+ Offset = *(reinterpret_cast<const support::ulittle32_t*>(Offsets)
+ + OffsetIndex);
}
- const char *Loc = Parent->getData().begin() + offset;
+ const char *Loc = Parent->getData().begin() + Offset;
size_t Size = sizeof(ArchiveMemberHeader) +
ToHeader(Loc)->getSize();
Result = Child(Parent, StringRef(Loc, Size));