This is an archive of the discontinued LLVM Phabricator instance.

Add nullptr check to isLandingPad
Needs ReviewPublic

Authored by ptersilie on Mar 4 2020, 3:36 AM.
This revision needs review, but all reviewers have resigned.

Details

Reviewers
lebedev.ri
Summary

Calling isLandingPad on an empty BasicBlock can lead to undefined behaviour, e.g. see the following program:

int main(void)
{
    // Start with a LLVM context.
    LLVMContext TheContext;

    // Make a module.
    Module *TheModule = new Module("mymod", TheContext);

    // Make a function
    std::vector<Type*> NoArgs = {};
    Type *u32 = Type::getInt32Ty(TheContext);
    FunctionType *FT = FunctionType::get(u32, NoArgs, false);
    Function *F = Function::Create(FT, Function::ExternalLinkage, "main", TheModule);

    // Make an empty block
    IRBuilder<> Builder(TheContext);
    BasicBlock *BB = BasicBlock::Create(TheContext, "entry", F);
    Builder.SetInsertPoint(BB);

    auto fnp = BB->getFirstNonPHI();
    assert(fnp == nullptr);

    // This can lead to UB!
    if (BB->isLandingPad()) {
        // do something
    }

    return 0;
}

This patch fixes this by using isa_and_nonnull instead of isa, which would result in isLandingPad always returning false when called on an empty BasicBlock. If there is a reason (e.g. performance) for not using isa_and_nonnull we could alternatively document that isLandingPad should not be called without checking getFirstNonPHI != nullptr first, which would avoid people making the same mistake I made.

Diff Detail

Event Timeline

ptersilie created this revision.Mar 4 2020, 3:36 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 4 2020, 3:36 AM
vext01 added a subscriber: vext01.Mar 4 2020, 4:10 AM

No idea who would be the appropriate reviewer here.
I guess this makes sense, but here's identical problem
with very next function, BasicBlock::getLandingPadInst().

fhahn added a subscriber: fhahn.Mar 6 2020, 3:02 AM

Hm I think calling isLandingPad on an empty (=invalid) basic block might be a pre-condition violation we legitimately want to crash on (with assertions isa<> assert != 0)? I suspect there are a lot of functions that expect BBs with at least a valid terminator and would crash for empty basic blocks. Unless I am missing something I think it might be better to avoid calling it on invalid block in the client code.

ptersilie added a comment.EditedMar 6 2020, 4:15 AM

isa does have an assertion that the argument must not be a nullptr. However, this assertion doesn't trigger when LLVM is compiled with assertions off (which as far as I can tell is the default), leading to undefined behaviour. I think at the very least we could add a comment to the documentation that isLandingPad should not be called without checking first that getFirstNonPHI() != nullptr. I'd be happy to update the PR if this is what you decide is the best course of action.

lebedev.ri resigned from this revision.Mar 9 2020, 6:33 AM

I suspect there are many functions that would need such comment.
Perhaps it would be best to place it somewhere in the docs, something along the lines of
"Warning: basic block with no terminator instruction is invalid, and must not be passed to certain API's",
but i think that might best go into a new patch.