[cfe-dev] [Analyzer] Pointer escape vs. pointer invalidation on function call
Artem Dergachev via cfe-dev
cfe-dev at lists.llvm.org
Tue May 30 12:45:01 PDT 2017
30/05/2017 10:12 PM, Anna Zaks wrote:
>
>
> On Tue, May 30, 2017 at 6:47 AM, Artem Dergachev <noqnoqneo at gmail.com
> <mailto:noqnoqneo at gmail.com>> wrote:
>
> +Devin.
>
> Yep, this behavior can be improved quite a bit. It's indeed overly
> conservative to believe that a single escaping pointer argument
> would cause other const pointer arguments' pointed-to regions
> invalidated.
>
> argumentsMayEscape() should still be relied upon, it seems,
> because it contains a nice blacklist of weird functions, eg.
> https://stackoverflow.com/questions/7726329/what-is-the-purpose-of-const-pointer-to-void/7726359
> <https://stackoverflow.com/questions/7726329/what-is-the-purpose-of-const-pointer-to-void/7726359>
>
> However, making argumentsMayEscape() more fine-grained, eg.
> letting it provide a list of arguments that may escape, should be
> quite an improvement.
>
> Additionally, when structures are passed into functions, we could
> consider const-qualifiers on pointer fields in these structures
> and avoid invalidating through pointers stored in const-pointer
> fields - might be an improvement as well. Direct parameters are
> not special.
>
> Possible aliasing between arguments should still be taken into
> account, eg. tests with testMixedConstNonConstCalls() added in
> https://reviews.llvm.org/D19057 <https://reviews.llvm.org/D19057>
> should remain "UNKNOWN". So i'd imagine a two-pass procedure,
> where on the first pass we mark base regions of all const pointers
> passed into the function with TK_PreserveContents, and on the
> second pass we remove TK_PreserveContents from base regions of
> non-const pointers.
>
> Finally, i agree that argumentsMayEscape() makes sense for plain C
> system library functions only. It should ideally check that the
> function is within the standard library, and is a plain-C
> function, and avoid jumping to conclusions if this is not the case.
>
> We do rely on argumentsMayEscape() to support other languages,
> specifically, there is ObjC specific code. I suspect, we would benefit
> from reasoning about C++ as well, but currently, C++ method decls
> overloads are not implemented. I suspect we need to do more
> investigation on libc++.
Yep. My point was mostly about the fact that in
AnyFunctionCall::argumentsMayEscape() (which i incorrectly referred to
as argumentsMayEscape()) we check the identifier of the function, but we
don't check if it's a plain C function (a C++ method may have the same
identifier, and we're not checking that it's not a method; overrides are
not necessary to break the contract of this method, just add some
classes with methods of given names; ObjC messages cannot make it into
AnyFunctionCall::argumentsMayEscape() because ObjC message isn't any
function) or if it comes from a system library (probably an ObjC library
in case of NS*Insert*, but it's still a C-style function, not a method,
not a message), so the code in this function doesn't make much sense
unless it is called in the context in which we have already checked all
this stuff.
>
> As Alexey pointed out, argumentsMayEscape() is used/called mainly
> after we know that the function comes from the system header. I do not
> recall if there are cases where it is needed for non-system calls, but
> we could envision having heuristics and treating some non-system calls
> with specific names the same way we treat system calls.
>
> Note, that the implementation itself does include generic heuristics,
> applicable to any functions, not just system functions. For example,
> it call:
> /// \brief Returns true if any of the arguments appear to represent
> callbacks.
> bool hasNonZeroCallbackArg() const;
>
> Further investigation would be great here as that code is somewhat
> convoluted!
>
>
> 25/05/2017 8:07 PM, Aleksei Sidorin wrote:
>
> Hi all,
>
> I have some questions about CSA invalidation behaviour for the
> case where some arguments can escape after call.
>
> 1. There is a condition in CallEvent::invalidateRegions():
>
> if (!argumentsMayEscape())
> findPtrToConstParams(PreserveArgs, *this);
>
> The contents of PreserveArgs changed by findPtrToConstParams()
> is used later for setting a special invalidation trait for its
> items: TK_PreserveContents. But, as I understand, if some
> pointer passed to function can escape, all the pointers passed
> to function get invalidated independently on can they escape
> or not. Why we don't just filter the escaping regions and
> invalidate them but invalidate all the pointers instead?
>
> 2. For AnyFunctionCall, we think that void* arguments of can
> escape:
>
> if (CallEvent::argumentsMayEscape() ||
> hasVoidPointerToNonConstArg())
> return true;
>
> But because of (1), this means that all other pointers passed
> to such function (including pointers to const) are
> invalidated. Checkers that use argumentsMayEscape() method
> explicitly check that the call is located in system header.
> So, should we move the check for system header into
> argumentsMayEscape()? It looks like the commit that introduced
> this behaviour was targeting system header functions only. And
> should we avoid the invalidation of pointers to constant
> memory if some pointer argument can escape?
>
>
>
More information about the cfe-dev
mailing list