This is an archive of the discontinued LLVM Phabricator instance.

[analyzer] pr36458: Fix retrieved value cast for symbolic void pointers.
ClosedPublic

Authored by NoQ on May 3 2018, 6:11 PM.

Details

Summary

Through C cast magic it's possible to put a raw void pointer into a variable of non-void pointer type. It is fine - generally, it's possible to put anything into anywhere by temporarily re-interpreting the anywhere. We cast it back to the correct type during load - with the help of StoreManager::CastRetrievedVal().

The attached example demonstrates that we're not casting the retrieved value pedantically enough when it comes to retrieving pointer values. In fact, we don't cast pointers-to-pointers at all because SValBuilder doesn't know how to do that or even that it needs to do that at all.

In this patch i perform the pointer cast manually for the situation that causes the crash. Performing the cast more carefully in other cases is possible, but i didn't manage to produce an observable effect (the second test passes just fine without it, and works correctly).

I cannot put the castRegion() call into SValBuilder because SValBuilder doesn't have access to StoreManager when doing casts. We really need to decouple this stuff and make a single good function for handling casts, because understanding how current code for pointer casts works is a nightmare.

Diff Detail

Repository
rC Clang

Event Timeline

NoQ created this revision.May 3 2018, 6:11 PM
NoQ updated this revision to Diff 145260.May 4 2018, 1:00 PM

Fix test names. Add one more test, just to make sure it works.

This revision was not accepted when it landed; it landed in state Needs Review.May 4 2018, 3:14 PM
This revision was automatically updated to reflect the committed changes.
isuckatcs added inline comments.
test/Analysis/casts.c
166

@NoQ why is this true for both x86_64 and i386?

On x86_64 sizeof(int *) == 8 and sizeof(int) == 4. This means that (*((int *)(&x))) = (int)&u; writes to the lower 4 bytes of x and leaves the upper 4 bytes uninitialized. See this godbolt example. If I compile and run this function on my machine it segfaults.

On i386 sizeof(int *) == 4 and sizeof(int) == 4, so on that platform this example is correct. See on godbolt.

In the x86_64 case don't we want the analyzer to report a warning a instead, as on that platform u is only partially initialized?

Herald added a project: Restricted Project. · View Herald TranscriptMay 20 2023, 2:23 PM