This is an archive of the discontinued LLVM Phabricator instance.

[clang][dataflow] Add support for disabling warnings on smart pointers.
ClosedPublic

Authored by ymandel on Mar 21 2022, 8:09 AM.

Details

Summary

This patch provides the user with the ability to disable all checked of accesses
to optionals that are the pointees of smart pointers. Since smart pointers are
not modeled (yet), the system cannot distinguish safe from unsafe accesses to
optionals through smart pointers. This results in false positives whenever
optionals are used through smart pointers. The patch gives the user the choice
of ignoring all positivess in these cases.

Diff Detail

Event Timeline

ymandel created this revision.Mar 21 2022, 8:09 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 21 2022, 8:09 AM
ymandel requested review of this revision.Mar 21 2022, 8:09 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 21 2022, 8:09 AM

Are smart pointers special? I would expect to see similar problems with containers (or even a nested optional). I wonder whether an allowlist instead of a denylist approach is better here. E.g., instead of disabling the modeling for smart pointers, we could enable it for cases that we actually support (or alternatively, we could add a confidence value to the unsafe access). Usually, these checks are pretty robust when we deal with objects on the stack of the analyzed function (locals, parameters), but it is really hard to reason about objects from the outside (e.g., when a reference to an object is acquired from a container or smart pointer) unless we have explicit modeling for the APIs. The confidence approach might be useful as we are unlikely to cover all the custom smart pointers the users have.

Are smart pointers special? I would expect to see similar problems with containers (or even a nested optional).

No, they're not. You're quite right -- containers in general are a problem. We happen to have support (landing soon) for nested optionals, but the general point still holds.

I wonder whether an allowlist instead of a denylist approach is better here. E.g., instead of disabling the modeling for smart pointers, we could enable it for cases that we actually support.

I like this idea, although we'll need to work out how to describe the set of things we track effectively. My argument against would be that it moves to "unsafe" as the default. But, given that we know we'll *always* report (right or wrong) in these situations, the safety argument isn't tht strong, because we're simply not adding anything of value in our reports -- users could just as well be told to always double check optionals in containers, etc.

So, do you mean to add a FIXME to move to allowlist, or do you mean to hold off until we've switched? I have a short-term interest in getting this through for a particular usecase, but I understand if you feel it just not a good idea. Regardless, I'm going to get started exploring an allowlist approach.

(or alternatively, we could add a confidence value to the unsafe access). Usually, these checks are pretty robust when we deal with objects on the stack of the analyzed function (locals, parameters), but it is really hard to reason about objects from the outside (e.g., when a reference to an object is acquired from a container or smart pointer) unless we have explicit modeling for the APIs. The confidence approach might be useful as we are unlikely to cover all the custom smart pointers the users have.

This idea sounds useful, but I'm not really sure how it would play out. I suppose we'd then let the user set a confidence level for diagnostics (like logging level?). Regardless, I think for a first attempt, I'd rather go with binary yes/no. But interested in exploring this approach.

So, do you mean to add a FIXME to move to allowlist, or do you mean to hold off until we've switched? I have a short-term interest in getting this through for a particular usecase, but I understand if you feel it just not a good idea. Regardless, I'm going to get started exploring an allowlist approach.

I see the precedent of FIXMEs getting followed up in this effort, so I'm fine with a FIXME for now :)

(or alternatively, we could add a confidence value to the unsafe access). Usually, these checks are pretty robust when we deal with objects on the stack of the analyzed function (locals, parameters), but it is really hard to reason about objects from the outside (e.g., when a reference to an object is acquired from a container or smart pointer) unless we have explicit modeling for the APIs. The confidence approach might be useful as we are unlikely to cover all the custom smart pointers the users have.

This idea sounds useful, but I'm not really sure how it would play out. I suppose we'd then let the user set a confidence level for diagnostics (like logging level?). Regardless, I think for a first attempt, I'd rather go with binary yes/no. But interested in exploring this approach.

Some tools I worked with will have separate warnings for high and low confidence reports, so users can chose to enable both or only one of them. It can be useful when different users have different expectations, e.g., some thinks of it like verification of a safety property and willing to make changes to make the tool happy while others would think of it as a bug finding tool and would be annoyed by false positives.

xazax.hun added inline comments.Mar 21 2022, 9:23 AM
clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
63

Maybe removing the duplication with something like: auto Exception = Ignorable? expr() : expr(unless(...)) and use it in the matcher?

349

It is probably rarely used, but one could use std::unique_ptr with an array of std::optionals and use operator[] to access the optional.

ymandel updated this revision to Diff 417032.Mar 21 2022, 11:10 AM

Addressed comments.

ymandel updated this revision to Diff 417033.Mar 21 2022, 11:13 AM

add fixme

ymandel marked 2 inline comments as done.Mar 21 2022, 11:15 AM

So, do you mean to add a FIXME to move to allowlist, or do you mean to hold off until we've switched? I have a short-term interest in getting this through for a particular usecase, but I understand if you feel it just not a good idea. Regardless, I'm going to get started exploring an allowlist approach.

I see the precedent of FIXMEs getting followed up in this effort, so I'm fine with a FIXME for now :)

Thanks for the confidence. FIXME added.

clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
349

I added a note to the option itself and also changed its name to be more specific.

kinu added a subscriber: kinu.Mar 21 2022, 7:03 PM
sgatev accepted this revision.Mar 22 2022, 2:53 AM
sgatev added inline comments.
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
31

Can you clarify what "smart pointer" refers to? It's not only standard types like unique_ptr, shared_ptr, and weak_ptr, right?

32
clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
1932–1936

Let's add this to a memory.h header.

1938

Why Member? I suggest either using one of the generic names that we use above or maybe something more descriptive.

This revision is now accepted and ready to land.Mar 22 2022, 2:53 AM
ymandel updated this revision to Diff 417243.Mar 22 2022, 4:41 AM
ymandel marked an inline comment as done.

Addressed comments

ymandel marked 4 inline comments as done.Mar 22 2022, 4:46 AM
ymandel added inline comments.
clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
31

I've rewritten it to specify the operators directly.

clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
1932–1936

I specifically wanted a locally-defined type. Notice that it's not in std. I've renamed to generic "smart_ptr" to emphasize that. WDYT?

1938

Went with generic. I think Member was from copy pasting...

This revision was landed with ongoing or failed builds.Mar 25 2022, 9:45 AM
This revision was automatically updated to reflect the committed changes.
ymandel marked 3 inline comments as done.