Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check *all* errors in LLVMRustArchiveIterator* API #38676

Merged
merged 1 commit into from
Dec 30, 2016

Conversation

hanna-kruppe
Copy link
Contributor

@hanna-kruppe hanna-kruppe commented Dec 29, 2016

Incrementing the Archive::child_iterator fetches and validates the next child.
This can trigger an error, which we previously checked on the next call to LLVMRustArchiveIteratorNext().
This means we ignore the last error if we stop iterating halfway through.
This is harmless (we don't access the child, after all) but LLVM 4.0 calls abort() if any error goes unchecked, even a success value.
This means that basically any rustc invocation that opens an archive and searches through it would die.

The solution implemented here is to change the order of operations, such that
advancing the iterator and fetching the newly-validated iterator happens in the same Next() call.
This keeps the error handling behavior as before but ensures all Errors get checked.

@rust-highfive
Copy link
Collaborator

r? @alexcrichton

(rust_highfive has picked a reviewer for you, use r? to override)

@hanna-kruppe
Copy link
Contributor Author

cc @dylanmckay @shepmaster
cc #37609

// that complicates the API.
// As a broken archive is bad news anyway, let's just return NULL
// "one child too soon".
#ifdef LLVM_VERSION_GE(3, 9)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be #if, right?

Also, if this branch is taken, that should free ret, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, yes.

@alexcrichton
Copy link
Member

Could we perhaps tweak this to check errors at the appropriate time instead? That is, only advance the cursor on calls to next?

@hanna-kruppe
Copy link
Contributor Author

We do only advance the cursor when calling next. The way the API works, next is effectively *it++, i.e., it fetches the current child and then advances the iterator. Simply flipping that (advance, then fetch) would skip the first child.

@alexcrichton
Copy link
Member

Oh right yeah what I mean is that we only advance the internal iterator when we need to actually fetch the result of the advance. I think we could store some boolean flags or something like that to avoid skipping the first child, right?

@hanna-kruppe
Copy link
Contributor Author

That would be pretty icky, but so is this hack. I'll give it a shot.

@shepmaster shepmaster mentioned this pull request Dec 29, 2016
23 tasks
@hanna-kruppe hanna-kruppe force-pushed the llvm-check-success branch 3 times, most recently from 9883a01 to c99d716 Compare December 29, 2016 19:36
@hanna-kruppe
Copy link
Contributor Author

@alexcrichton Updated.

return NULL;
}

if (rai->cur == rai->end) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should happen first to prevent a segfault from calling next too much, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm yeah, it should be above as well, but it's needed here, too (I got segfaults without it).

}
const Archive::Child &child = cur->get();
#else
const Archive::Child &child = *rai->cur.operator->();
#endif
Archive::Child *ret = new Archive::Child(child);

++rai->cur;
rai->first = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this could go in an else above with the check to ensure it always happens?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea!

Incrementing the `Archive::child_iterator` fetches and validates the next child.
This can trigger an error, which we previously checked on the *next* call to `LLVMRustArchiveIteratorNext()`.
This means we ignore the last error if we stop iterating halfway through.
This is harmless (we don't access the child, after all) but LLVM 4.0 calls `abort()` if *any* error goes unchecked, even a success value.
This means that basically any rustc invocation that opens an archive and searches through it would die.

The solution implemented here is to change the order of operations, such that
advancing the iterator and fetching the newly-validated iterator happens in the same `Next()` call.
This keeps the error handling behavior as before but ensures all `Error`s get checked.
@hanna-kruppe
Copy link
Contributor Author

Updated.

@alexcrichton
Copy link
Member

@bors: r+

Thanks!

@bors
Copy link
Contributor

bors commented Dec 29, 2016

📌 Commit 8d50857 has been approved by alexcrichton

alexcrichton added a commit to alexcrichton/rust that referenced this pull request Dec 30, 2016
…richton

Check *all* errors in LLVMRustArchiveIterator* API

Incrementing the `Archive::child_iterator` fetches and validates the next child.
This can trigger an error, which we previously checked on the *next* call to `LLVMRustArchiveIteratorNext()`.
This means we ignore the last error if we stop iterating halfway through.
This is harmless (we don't access the child, after all) but LLVM 4.0 calls `abort()` if *any* error goes unchecked, even a success value.
This means that basically any rustc invocation that opens an archive and searches through it would die.

The solution implemented here is to change the order of operations, such that
advancing the iterator and fetching the newly-validated iterator happens in the same `Next()` call.
This keeps the error handling behavior as before but ensures all `Error`s get checked.
bors added a commit that referenced this pull request Dec 30, 2016
@bors bors merged commit 8d50857 into rust-lang:master Dec 30, 2016
@bors
Copy link
Contributor

bors commented Dec 30, 2016

⌛ Testing commit 8d50857 with merge 7f2d2af...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants