[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