[cfe-dev] CallEvent::isCalled() alternative if a function is called by pointer

Artem Dergachev via cfe-dev cfe-dev at lists.llvm.org
Fri May 4 13:10:11 PDT 2018



On 5/3/18 8:35 AM, Artem Razin wrote:
> Hi Artem,
>
> It seems I was wrong, the situation is not so simple as I thought 
> initially.
>
> First of all, here the checkPreCall() call, it checks a call against 
> CloseHandle and outputs result along with passed function information:
>
> void HandleChecker::checkPreCall(
> const CallEvent &Call,
> CheckerContext &C) const
> {
> if (Call.isCalled(_closeHandleFn))
> fprintf(stderr, "It's CloseHandle: ");
> else
> fprintf(stderr, "It's NOT CloseHandle: ");
> Call.dump();
> }
>
> The first sample uses usual CloseHandle call, without function pointer:
> CloseHandle(NULL);
>
> So it works.
>
> My original code that didn't work has used template class. The 
> simplified code:
>
> typedef BOOL (WINAPI *P_CloseHandle)(HANDLE);
>
> template <P_CloseHandle pCloseHandle> struct AutoCloseHandle
> {
>   AutoCloseHandle(HANDLE h) : _h(h) {}
>   ~AutoCloseHandle() { pCloseHandle(_h); };
>   HANDLE _h;
> };
>
> int main()
> {
>   AutoCloseHandle<&CloseHandle> autoCloseHandle(NULL);
>   return 1;
> }
>
> The output:
>
> It's NOT CloseHandle: &CloseHandle(this->_h)
> It's NOT CloseHandle: 0
> It's NOT CloseHandle: Call to ~AutoCloseHandle<&CloseHandle>() noexcept {
>     &CloseHandle(this->_h);
> }
> It's NOT CloseHandle: &CloseHandle(this->_h)
>
> > Could you see if you can get Call.getOriginExpr()->dump() and/or 
> Call.getDecl()->dump()? These should be more informative.
>
> Sure, I've added it. Call.getDecl() is NULL for that call. 
> Call.getOriginExpr() is the following:
>
> CallExpr 0x64ecb10 'BOOL':'int'
> |-SubstNonTypeTemplateParmExpr 0x64ecac0 'BOOL (*)(HANDLE) 
> __attribute__((stdcall))'
> | `-UnaryOperator 0x64ecaa8 'BOOL (*)(HANDLE) 
> __attribute__((stdcall))' prefix '&' cannot overflow
> |   `-DeclRefExpr 0x64eca90 'BOOL (HANDLE) 
> __attribute__((stdcall))':'BOOL (HANDLE) __attribute__((stdcall))' 
> lvalue Function

Aha, interesting. At a glance it seems that we know how to evaluate a 
function pointer (i.e. ExprEngine::Visit()), but we don't know how to 
constant-fold it (i.e. Environment::getSVal() -> 
SValBuilder::getConstantVal()). And we don't evaluate anything within 
SubstNonTypeTemplateParmExpr (see ExprEngine::Visit() again) because 
it's supposed to be constant-foldable.

Constant-folding should be easy, but it should be followed up with a 
cleanup work to remove the evaluation.

Would you be willing to file a bug against me in bugzilla (or fix it)?


> 0x57b8890 'CloseHandle' 'BOOL (HANDLE) __attribute__((stdcall))':'BOOL 
> (HANDLE) __attribute__((stdcall))'
> `-ImplicitCastExpr 0x64ecb30 'HANDLE':'void *' <LValueToRValue>
>   `-MemberExpr 0x64ecae8 'HANDLE':'void *' lvalue ->_h 0x64dc710
>     `-CXXThisExpr 0x64ecad8 'struct AutoCloseHandle<&CloseHandle> *' this
>
> Call.dump()'s result:
>
> &CloseHandle(this->_h)
>
> Thank you!
>
> 2018-05-02 23:32 GMT+03:00 Artem Dergachev <noqnoqneo at gmail.com 
> <mailto:noqnoqneo at gmail.com>>:
>
>     On 5/2/18 3:58 AM, Artem Razin via cfe-dev wrote:
>>     Hi All,
>>
>>     I hope this is right place to ask such a newbie question like the
>>     following.
>>
>>     I am trying to write a checker to catch potential handle leaks
>>     (it's on Windows: a handle is closed by CloseHandle).
>>
>>     So I took SimpleStreamChecker as a base, now my checkPreCall()
>>     checks if "CloseHandle" is called. Call.isCalled() works great
>>     except one case when CloseHandle is called by pointer. It happens
>>     because of using a template class that took a pointer to closing
>>     function as template parameter (useful to close different types
>>     of handles by appropriate functions: FindClose, CloseHandle etc.).
>>
>>     Call.dump() prints "&CloseHandle(this->m_h)" in this case, so it
>>     understands that this a pointer and that this is a pointer of
>>     CloseHandle.But how to "extract" the the identifier of CloseHandle?
>
>     I'm not quite understanding that dump, it looks a bit weird. What
>     is the actual code under analysis? Could you see if you can get
>     Call.getOriginExpr()->dump() and/or Call.getDecl()->dump()? These
>     should be more informative.
>
>     In general the analyzer does indeed understand calls through
>     function pointers, as long as it can at all be tracked by looking
>     at the current execution path.
>
>     And when it is tracked, CallEvent::isCalled() should "just work"
>     because it only looks at Call.getDecl() which should be the
>     path-specific decl.
>
>>
>>     Thank you in advance!
>>
>>     -- 
>>     Best regards,
>>     Artem A. Razin
>>
>>     _______________________________________________
>>     cfe-dev mailing list
>>     cfe-dev at lists.llvm.org  <mailto:cfe-dev at lists.llvm.org>
>>     http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev  <http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev>
>
>
>
>
> -- 
> Best regards,
> Artem A. Razin

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20180504/57a6b3b4/attachment.html>


More information about the cfe-dev mailing list