This is an archive of the discontinued LLVM Phabricator instance.

[cfi] Safe handling of unaddressable vtable pointers (clang).
ClosedPublic

Authored by eugenis on Feb 2 2016, 2:17 PM.

Details

Reviewers
kcc
samsonov
pcc
Summary

Avoid crashing when printing diagnostics for vtable-related CFI
errors. In diagnostic mode, the frontend does an additional check of
the vtable pointer against the set of all known vtable addresses and
lets the runtime handler know if it is safe to inspect the vtable.

Diff Detail

Repository
rL LLVM

Event Timeline

eugenis updated this revision to Diff 46703.Feb 2 2016, 2:17 PM
eugenis retitled this revision from to [cfi] Safe handling of unaddressable vtable pointers (clang)..
eugenis updated this object.
eugenis added reviewers: pcc, kcc.
eugenis set the repository for this revision to rL LLVM.
eugenis added a subscriber: cfe-commits.
samsonov added inline comments.
lib/CodeGen/CGExpr.cpp
2493

This is really ugly. Why are you not passing it down in DynamicArgs? Is it performance penalty you don't want to pay if the check will not succeed? How large will it be?

eugenis added inline comments.Feb 2 2016, 2:45 PM
lib/CodeGen/CGExpr.cpp
2493

Yes, I want this code to be on the failing side of the check.
This would cost about the same as the check itself, so I suspect it could double the overhead.

pcc added inline comments.Feb 2 2016, 2:55 PM
lib/CodeGen/CGExpr.cpp
2493

I would just emit the call unconditionally. We don't care too much about the performance in non-trapping mode, and if it becomes a problem in practice we can see if we can have the optimizer move the call into the conditional block (which I suspect it already knows how to do).

lib/CodeGen/CodeGenModule.cpp
4061

This conditional doesn't look right. It should be something like

if (sanitize.has(this) && !sanitizetrap.has(this)) ||
   (sanitize.has(that) && !sanitizetrap.has(that)) ||
...

But that's sufficiently ugly that I wonder if we should just do this unconditionally. It shouldn't make a difference to the generated code either way.

eugenis added inline comments.Feb 2 2016, 3:43 PM
lib/CodeGen/CGExpr.cpp
2493

I care about performance in non-trapping mode.
Doing this change would not make the code any less ugly. For example, EmitCheck may not use the argument if the check has -fsanitize-trap behaviour, in which case we get an unused llvm.bitset.test call that affects some of the clang tests.

eugenis updated this revision to Diff 46718.Feb 2 2016, 4:08 PM

Moved bitset.text call outside.
LLVM is smart enough to sink it along the cold branch, so performance should not suffer.

eugenis updated this revision to Diff 46723.Feb 2 2016, 4:23 PM
eugenis marked an inline comment as done.
eugenis added inline comments.
lib/CodeGen/CodeGenModule.cpp
4061

I don't like emitting all these bitset entries if they are not needed.
Fixed.

samsonov added inline comments.Feb 2 2016, 5:38 PM
lib/CodeGen/CGExpr.cpp
2642

This is almost the same as EmitVTablePtrCheck, but with ZExt? Is the difference intentional/important? Is it possible to extract this logic (getting "all-vtables" metadata and running bitset test) to a function?

lib/CodeGen/CodeGenModule.cpp
4028

Hm, can you write this as a loop?

eugenis added inline comments.Feb 2 2016, 6:03 PM
lib/CodeGen/CGExpr.cpp
2642

Not important. Zext makes the test a bit simpler.
Extracting these two lines to a function is surely possible, but is it worth it?

samsonov accepted this revision.Feb 3 2016, 10:38 AM
samsonov added a reviewer: samsonov.

LGTM

lib/CodeGen/CGClass.cpp
2608

Can we rewrite this as if-elseif-else block now?

lib/CodeGen/CGExpr.cpp
2642

Probably not, as long as we have the test coverage.

This revision is now accepted and ready to land.Feb 3 2016, 10:38 AM
eugenis updated this revision to Diff 46807.Feb 3 2016, 11:38 AM
eugenis edited edge metadata.
eugenis added inline comments.
lib/CodeGen/CGClass.cpp
2608

even better, with 2 early returns.