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

Artem Razin via cfe-dev cfe-dev at lists.llvm.org
Mon May 7 09:21:05 PDT 2018


Sure, I will file new bug. Just sent a request to bugs-admin at lists.llvm.org
to get an access there.

I would be happy to fix it myself, but I really just started working with
clang analyzer. Any doc to quick start? Or the code itself is the best
documentation? :)

Thank you!

2018-05-04 23:10 GMT+03:00 Artem Dergachev <noqnoqneo at gmail.com>:

>
>
> 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>:
>
>> 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 listcfe-dev at lists.llvm.orghttp://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>
>>
>>
>
>
> --
> Best regards,
> Artem A. Razin
>
>
>


-- 
Best regards,
Artem A. Razin
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20180507/d9b9cde2/attachment.html>


More information about the cfe-dev mailing list