This is an archive of the discontinued LLVM Phabricator instance.

Fix SegFault in Expected
ClosedPublic

Authored by yuyichao on Oct 29 2016, 5:06 PM.

Details

Reviewers
lhames
Summary

The placement new on getErrorStorage() is of the wrong type.

AFAICT this is the intent in https://reviews.llvm.org/rL265446 which somehow starts to trigger a segfault when the destructor of the unique_ptr is called after https://reviews.llvm.org/rL285426. Ref https://github.com/JuliaLang/julia/issues/19154

Diff Detail

Event Timeline

yuyichao updated this revision to Diff 76323.Oct 29 2016, 5:06 PM
yuyichao retitled this revision from to Fix SegFault in Expected.
yuyichao updated this object.
yuyichao added a reviewer: lhames.
yuyichao added a subscriber: llvm-commits.

And I think it didn't cause any problem because Error and unique_ptr has the same layout except for the lowest bit. Before https://reviews.llvm.org/rL285426, the lowest bit should never be set when the Expected is checked/assertion is disabled but this is not true anymore for an unchecked Expected on a release build after the change.

vsk added a subscriber: vsk.Nov 2 2016, 8:03 AM

(I'm just trying to wrap my head around this.)

It looks like getErrorStorage() provides a pointer to an error_type (std::unique_ptr<ErrorInfoBase>), but we're storing an Error (funky pointer-int pair) into it. Since this started causing problems after r285426, I'm wondering what the reproducer looks like / why we haven't seen this issue already. Would you need to look into an unchecked Error?, e.g:

auto E = Expected<int>(make_error<MyErrorInfo>(...));
ASSERT_DEATH(*E);

If there's a way to add a unit test to unittests/Support/ErrorTest without introducing a death test, that would be great.

Since this started causing problems after r285426, I'm wondering what the reproducer looks like / why we haven't seen this issue already.

Any code that doesn't check for the error when assertion is disabled should trigger this error and the reason was that r285426 introduces the tag bit in this case. The code path we had to trigger it is https://github.com/JuliaLang/julia/blob/10ffbaeaa809a5a9cdc7866aa659ad2a4e525a6a/src/debuginfo.cpp#L1255, which clears the error before assigning the next attempt to it if assertion is enabled.

lhames accepted this revision.Nov 3 2016, 3:12 PM
lhames edited edge metadata.

This is great. Thanks Yichao!

I've committed it in r285970.

This revision is now accepted and ready to land.Nov 3 2016, 3:12 PM
yuyichao closed this revision.Nov 4 2016, 10:07 AM

I assume the patch is actually merged even though somehow it doesn't trigger the hook that closes this?

Hopefully this is the right way to close a PR...