llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.69k stars 11.86k forks source link

Unsafe buffer usage: calls to [[clang::unsafe_buffer_usage]] constructors are not warned on #80482

Open danakj opened 8 months ago

danakj commented 8 months ago

[[clang::unsafe_buffer_usage]] should be applied to any function which can cause OOB when given invalid inputs. However if a constructor is marked unsafe, calls to it do not cause a warning to be generated.

This prevents us from requiring annotations on dangerous constructor calls, such as those types like span.

https://godbolt.org/z/debqW3ahx

danakj commented 8 months ago

CC @haoNoQ @ziqingluo-90

haoNoQ commented 8 months ago

Yes looks like an omission, thanks a lot! Looks like we've unnecessarily restricted it to CallExpr so a few other C++ features may cause similar problems. We'll get to it!

jkorous-apple commented 8 months ago

This likely applies to operator() as well.

jkorous-apple commented 8 months ago

We might want to think about supporting the attribute on lambdas and function pointers although that'd be a separate topic entirely.

danakj commented 8 months ago

Another place where constructors appear is in field initializers. if all constructor calls are handled uniformly then the diagnostic shouldn't need to worry about it, but just in case, I thought I'd mention it because field initializers appear very different in the AST.

https://godbolt.org/z/Mz7r3WzqT

struct MySpan {
    [[clang::unsafe_buffer_usage]] explicit constexpr MySpan(int*, size_t) {}
};

struct S {
    S()
      : sp(nullptr, 5) {}  // No warning is generated.

    MySpan sp;
};

int main() {
    S();
}
danakj commented 6 months ago

Is this something that I should look into fixing? I don't want to waste time if someone else is making progress on it.

ziqingluo-90 commented 6 months ago

Is this something that I should look into fixing? I don't want to waste time if someone else is making progress on it.

As far as I know, no one is working on fixing this? @haoNoQ @jkorous-apple

danakj commented 5 months ago

I have this working now. Calling operator() is a CallExpr so it already matches, but constructors are CXXConstructExpr which is not a CallExpr subclass, which is why it does not.

The design challenge here is that UnsafeBufferUsageReporter::handleUnsafeOperation() is hard-coded that a CXXConstructExpr should generate the warning for the std::span ctor. Its inputs don't allow it to easy determine that this is a warning on a different ctor, without reproducing all of the matching logic.

So I am going to propose that we split up UnsafeBufferUsageReporter::handleUnsafeOperation() into two:

This is mostly straight forward except that then UnsafeBufferUsage.cpp has to decide which method to call. Either it has to dispatch through the Gadget, which would use virtual dispatch to choose the correct one, or it has to query the Gadget to determine if this is a WARNING_GADGET or a WARNING_CONTAINER_GADGET. I've got this working with the latter.

I tried the latter one first, but it's somewhat fragile, as you have to repeat the checks at all call sites. So I am going to try out the virtual dispatch.

jkorous-apple commented 5 months ago

I'd like @haoNoQ to comment on the proposed change.

danakj commented 5 months ago

The virtual one makes it easy to satisfy the TODO to remove getBaseStmt from the FixableGadget interface, which I will do in the same change then, so it seems like the better path forward between those two. I will send the PR shortly

danakj commented 5 months ago

PR: https://github.com/llvm/llvm-project/pull/91777

danakj commented 5 months ago

Constructor initializers will need a bit of a different approach as they are not Stmts. All of the matcher() machinery right now assumes everything is Stmt. I will look into this as another follow-up PR.

danakj commented 5 months ago

PR https://github.com/llvm/llvm-project/pull/91991 is on top of (includes the commits of) https://github.com/llvm/llvm-project/pull/91777 but has additional work to handle field and constructor initializers.

danakj commented 5 months ago

The PR has been sitting for a few days, who would be a good reviewer for it?

danakj commented 5 months ago

The PR has been sitting for a few days, who would be a good reviewer for it?

Oops, I see a reply is there, my bad!