This is an archive of the discontinued LLVM Phabricator instance.

[analyzer] Fix for the crash in #56873
ClosedPublic

Authored by isuckatcs on Aug 2 2022, 2:34 AM.

Details

Summary

In ExprEngine::bindReturnValue() we cast an SVal to DefinedOrUnknownSVal,
however this SVal can also be Undefined, which leads to an assertion failure.

Fixes: #56873

Diff Detail

Event Timeline

isuckatcs created this revision.Aug 2 2022, 2:34 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 2 2022, 2:34 AM
isuckatcs requested review of this revision.Aug 2 2022, 2:34 AM
martong accepted this revision.Aug 2 2022, 7:05 AM

Thanks, LGTM!

clang/test/Analysis/Issue56873.cpp
13

I think, MallocChecker (or another checker?) should issue a warning if the extent is undefined. Do you plan to address that?

This revision is now accepted and ready to land.Aug 2 2022, 7:05 AM
isuckatcs marked an inline comment as done.Aug 2 2022, 8:17 AM
isuckatcs added inline comments.
clang/test/Analysis/Issue56873.cpp
13

I agree that we should warn in this case, though I don't plan to address this in the near future. I keep this idea in mind, however if you or someone else wants to look into it, feel free to do so.

isuckatcs marked an inline comment as done.Aug 2 2022, 8:17 AM
This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptAug 3 2022, 10:25 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript

Some checker should have caught the uninitialized value earlier than the defaultEvalCall().
I guess, the MallocCkecher could have checked for it in PreStmt<CXXNewExpr>.
Or alternatively, the CallAndMessageChecker::preCall() already does something like this in the PreVisitProcessArg(). I know that CXXNewExpr is not a call, but you get the idea.
WDYT, worth catching it?

Other than that, I think it's a good practice to not rely on some checkers to catch things to prevent crashes; so this 'fix' seems reasonable to me.

clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
768

I'm not a fan of mutating values like this.
Alternatively we could have used something like this at the point of use:
Size.getAs<DefinedOrUnknownSVal>().getValueOr(UnknownVal{})
I'm not sure if it's more readable :D

Some checker should have caught the uninitialized value earlier than the defaultEvalCall().
I guess, the MallocCkecher could have checked for it in PreStmt<CXXNewExpr>.
Or alternatively, the CallAndMessageChecker::preCall() already does something like this in the PreVisitProcessArg(). I know that CXXNewExpr is not a call, but you get the idea.
WDYT, worth catching it?

I definitely think it's worth catching it. I'm working on a checker which addresses this in D131299. It was originally intended to be a part of MallocChecker but has been moved to a separate one.

Some checker should have caught the uninitialized value earlier than the defaultEvalCall().
I guess, the MallocCkecher could have checked for it in PreStmt<CXXNewExpr>.
Or alternatively, the CallAndMessageChecker::preCall() already does something like this in the PreVisitProcessArg(). I know that CXXNewExpr is not a call, but you get the idea.
WDYT, worth catching it?

I definitely think it's worth catching it. I'm working on a checker which addresses this in D131299. It was originally intended to be a part of MallocChecker but has been moved to a separate one.

If so, shouldn't be some dependencies across these revisions? You could also specify an additional RUN line to demonstrate that this can be caught by an experimental configuration.

If so, shouldn't be some dependencies across these revisions?

I don't think they are that closely related.

This patch is about fixing an assertion failure. This assertion failure happens because we don't handle a case not because the checker doesn't exist.
Also the checker alone wouldn't solve the problem, because if it's turned off, the same crash will happen.