Skip to content

Commit e3bf4fd

Browse files
committed
This removes the eating of the error in Archive::Child::getSize() when the characters
in the size field in the archive header for the member is not a number. To do this we have all of the needed methods return ErrorOr to push them up until we get out of lib. Then the tools and can handle the error in whatever way is appropriate for that tool. So the solution is to plumb all the ErrorOr stuff through everything that touches archives. This include its iterators as one can create an Archive object but the first or any other Child object may fail to be created due to a bad size field in its header. Thanks to Lang Hames on the changes making child_iterator contain an ErrorOr<Child> instead of a Child and the needed changes to ErrorOr.h to add operator overloading for * and -> . We don’t want to use llvm_unreachable() as it calls abort() and is produces a “crash” and using report_fatal_error() to move the error checking will cause the program to stop, neither of which are really correct in library code. There are still some uses of these that should be cleaned up in this library code for other than the size field. Also corrected the code where the size gets us to the “at the end of the archive” which is OK but past the end of the archive will return object_error::parse_failed now. The test cases use archives with text files so one can see the non-digit character, in this case a ‘%’, in the size field. llvm-svn: 250906
1 parent 998039e commit e3bf4fd

File tree

18 files changed

+349
-92
lines changed

18 files changed

+349
-92
lines changed

llvm/include/llvm/Object/Archive.h

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ class Archive : public Binary {
6565
bool isThinMember() const;
6666

6767
public:
68-
Child(const Archive *Parent, const char *Start);
68+
Child(const Archive *Parent, const char *Start,
69+
std::error_code *EC);
70+
static ErrorOr<std::unique_ptr<Child>> create(const Archive *Parent,
71+
const char *Start);
6972

7073
bool operator ==(const Child &other) const {
7174
assert(Parent == other.Parent);
@@ -77,7 +80,7 @@ class Archive : public Binary {
7780
}
7881

7982
const Archive *getParent() const { return Parent; }
80-
Child getNext() const;
83+
ErrorOr<Child> getNext() const;
8184

8285
ErrorOr<StringRef> getName() const;
8386
StringRef getRawName() const { return getHeader()->getName(); }
@@ -93,9 +96,9 @@ class Archive : public Binary {
9396
return getHeader()->getAccessMode();
9497
}
9598
/// \return the size of the archive member without the header or padding.
96-
uint64_t getSize() const;
99+
ErrorOr<uint64_t> getSize() const;
97100
/// \return the size in the archive header for this member.
98-
uint64_t getRawSize() const;
101+
ErrorOr<uint64_t> getRawSize() const;
99102

100103
ErrorOr<StringRef> getBuffer() const;
101104
uint64_t getChildOffset() const;
@@ -107,28 +110,35 @@ class Archive : public Binary {
107110
};
108111

109112
class child_iterator {
110-
Child child;
113+
ErrorOr<Child> child;
111114

112115
public:
113-
child_iterator() : child(Child(nullptr, nullptr)) {}
116+
child_iterator() : child(Child(nullptr, nullptr, nullptr)) {}
114117
child_iterator(const Child &c) : child(c) {}
115-
const Child *operator->() const { return &child; }
116-
const Child &operator*() const { return child; }
118+
child_iterator(std::error_code EC) : child(EC) {}
119+
const ErrorOr<Child> *operator->() const { return &child; }
120+
const ErrorOr<Child> &operator*() const { return child; }
117121

118122
bool operator==(const child_iterator &other) const {
119-
return child == other.child;
123+
if ((*this)->getError())
124+
return false;
125+
if (other->getError())
126+
return false;
127+
return (*this)->get() == other->get();
120128
}
121129

122130
bool operator!=(const child_iterator &other) const {
123131
return !(*this == other);
124132
}
125133

126-
bool operator<(const child_iterator &other) const {
127-
return child < other.child;
128-
}
134+
// No operator< as we can't do less than compares with iterators that
135+
// contain errors.
129136

137+
// Code in loops with child_iterators must check for errors on each loop
138+
// iteration. And if there is an error break out of the loop.
130139
child_iterator &operator++() { // Preincrement
131-
child = child.getNext();
140+
assert(child && "Can't increment iterator with error");
141+
child = child->getNext();
132142
return *this;
133143
}
134144
};
@@ -212,7 +222,7 @@ class Archive : public Binary {
212222
StringRef getSymbolTable() const {
213223
// We know that the symbol table is not an external file,
214224
// so we just assert there is no error.
215-
return *SymbolTable->getBuffer();
225+
return *(*SymbolTable)->getBuffer();
216226
}
217227
uint32_t getNumberOfSymbols() const;
218228

llvm/include/llvm/Support/ErrorOr.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ class ErrorOr {
9191
typedef typename std::remove_reference<T>::type &reference;
9292
typedef const typename std::remove_reference<T>::type &const_reference;
9393
typedef typename std::remove_reference<T>::type *pointer;
94+
typedef const typename std::remove_reference<T>::type *const_pointer;
9495

9596
public:
9697
template <class E>
@@ -183,10 +184,18 @@ class ErrorOr {
183184
return toPointer(getStorage());
184185
}
185186

187+
const_pointer operator ->() const {
188+
return toPointer(getStorage());
189+
}
190+
186191
reference operator *() {
187192
return *getStorage();
188193
}
189194

195+
const_reference operator *() const {
196+
return *getStorage();
197+
}
198+
190199
private:
191200
template <class OtherT>
192201
void copyConstruct(const ErrorOr<OtherT> &Other) {
@@ -246,10 +255,19 @@ class ErrorOr {
246255
return Val;
247256
}
248257

258+
const_pointer toPointer(const_pointer Val) const {
259+
return Val;
260+
}
261+
249262
pointer toPointer(wrap *Val) {
250263
return &Val->get();
251264
}
252265

266+
const_pointer toPointer(const wrap *Val) const {
267+
return &Val->get();
268+
}
269+
270+
253271
storage_type *getStorage() {
254272
assert(!HasError && "Cannot get value when an error exists!");
255273
return reinterpret_cast<storage_type*>(TStorage.buffer);

llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,10 +318,10 @@ RuntimeDyld::SymbolInfo MCJIT::findSymbol(const std::string &Name,
318318
object::Archive *A = OB.getBinary();
319319
// Look for our symbols in each Archive
320320
object::Archive::child_iterator ChildIt = A->findSym(Name);
321-
if (ChildIt != A->child_end()) {
321+
if (*ChildIt && ChildIt != A->child_end()) {
322322
// FIXME: Support nested archives?
323323
ErrorOr<std::unique_ptr<object::Binary>> ChildBinOrErr =
324-
ChildIt->getAsBinary();
324+
(*ChildIt)->getAsBinary();
325325
if (ChildBinOrErr.getError())
326326
continue;
327327
std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get();

llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,10 +253,10 @@ class OrcMCJITReplacement : public ExecutionEngine {
253253
object::Archive *A = OB.getBinary();
254254
// Look for our symbols in each Archive
255255
object::Archive::child_iterator ChildIt = A->findSym(Name);
256-
if (ChildIt != A->child_end()) {
256+
if (*ChildIt && ChildIt != A->child_end()) {
257257
// FIXME: Support nested archives?
258258
ErrorOr<std::unique_ptr<object::Binary>> ChildBinOrErr =
259-
ChildIt->getAsBinary();
259+
(*ChildIt)->getAsBinary();
260260
if (ChildBinOrErr.getError())
261261
continue;
262262
std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get();

0 commit comments

Comments
 (0)