This is an archive of the discontinued LLVM Phabricator instance.

[analyzer] Fix crash with pointer to members values
ClosedPublic

Authored by vsavchenko on Aug 12 2020, 1:17 AM.

Details

Summary

This fix unifies all of the different ways we handled pointer to
members into one. The crash was caused by the fact that the type
of pointer-to-member values was void *, and while this works
for the vast majority of cases it breaks when we actually need
to explain the path for the report.

rdar://problem/64202361

Diff Detail

Event Timeline

vsavchenko created this revision.Aug 12 2020, 1:17 AM
vsavchenko requested review of this revision.Aug 12 2020, 1:17 AM
NoQ added a comment.Aug 12 2020, 9:31 AM

That's a fix for https://bugs.llvm.org/show_bug.cgi?id=46264.

Your code looks great but i don't understand at a glance what the crash was caused by and how does your code fix it, can you explain? Like, the original test doesn't have any void *s and it doesn't have any indirect fields. Also the crash happens during visitor phase but the fixes are entirely during modeling phase.

clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
2533–2535

Ok so you're saying that there's *always* going to be a surrounding operator &? That kind of makes sense but if you add more explanation/proof of how you figured this out that'd be great.

clang/test/Analysis/PR46264.cpp
6

I'm pretty sure the namespace is not actually important for the test. creduce is great but sometimes it misses stuff. Generally, i'm a big fan of manually cleaning up creduced test to make them look more like real code. At least turn things like b h; and e *i; into something like A a; and B *b;. Also replace class with struct because we never care about this entire public/private business and struct provides a nice default.

10

It's worth it to comment where exactly is this conversion operator used in the text (i.e., within the if-condition). People do in fact sometimes do this kind of thing in real life: provide a conversion to pointer-to-member *instead of* conversion to bool because it causes fewer potential further accidental implicit conversions to be possible.

In D85817#2213435, @NoQ wrote:

That's a fix for https://bugs.llvm.org/show_bug.cgi?id=46264.

Your code looks great but i don't understand at a glance what the crash was caused by and how does your code fix it, can you explain? Like, the original test doesn't have any void *s and it doesn't have any indirect fields. Also the crash happens during visitor phase but the fixes are entirely during modeling phase.

Sure! The problem was in the deleted code, we modeled FieldDecl and IndirectFieldDecl in such matter that &b::d ended up as void * and it was totally fine for path exploration, but the moment we try to explain such value is where we hit the assertion (I tried to explain that in the summary). I could've fixed the symptom and patch that, but it didn't seem right. It is not a pointer to void and it never was. Then I found out about the fact that we actually have a mechanism to deal with pointer to members. So I decided to remove the code with 2 FIXMEs (by doing one of the FIXMEs). Removing only FieldDecl from the condition would've fixed the original problem, but wouldn't have solved a very similar example with indirect fields (maybe I should expand the test to include that one as well). That's how I came to fixing the behavior for indirect fields as well.

clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
2533–2535

I don't know actually that there's *always* a surrounding &, I mean it makes sense and I guess it is the only case we care about.

clang/test/Analysis/PR46264.cpp
6

I didn't change the code because it is the actual snippet from the bug report, but OK

10

OK, will do

NoQ accepted this revision.Aug 12 2020, 1:48 PM

Aha, i see, fair enough!

This revision is now accepted and ready to land.Aug 12 2020, 1:48 PM

Simplify the main test

Add "no crash" comments

This revision was automatically updated to reflect the committed changes.

@vsavchenko, why did you chose NamedDecl instead of ValueDecl to account for the indirect fields? I couldn't quite follow it from the discussion above.

@vsavchenko, why did you chose NamedDecl instead of ValueDecl to account for the indirect fields? I couldn't quite follow it from the discussion above.

Looking at it now, I also don't know why 🤷