From: Marcin Niesluchowski Date: Fri, 14 Nov 2014 17:48:01 +0000 (+0100) Subject: Add protection against cynara_async_finish() call in callbacks X-Git-Tag: submit/R4/20141115.054144~14 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bf838ebf47eabea59dae47d83f1fdc360693f5cb;p=platform%2Fcore%2Fsecurity%2Fcynara.git Add protection against cynara_async_finish() call in callbacks cynara_async_finish() called in callbacks is ignored in all cases. Change-Id: I3c2268a0462413b279215f837e4603a7d6acb96d --- diff --git a/src/client-async/api/ApiInterface.h b/src/client-async/api/ApiInterface.h index 31478da..59c82fb 100644 --- a/src/client-async/api/ApiInterface.h +++ b/src/client-async/api/ApiInterface.h @@ -42,6 +42,7 @@ public: void *userResponseData) = 0; virtual int process(void) = 0; virtual int cancelRequest(cynara_check_id checkId) = 0; + virtual bool isFinishPermitted(void) = 0; }; } // namespace Cynara diff --git a/src/client-async/api/client-async-api.cpp b/src/client-async/api/client-async-api.cpp index 1e3479e..13e5a16 100644 --- a/src/client-async/api/client-async-api.cpp +++ b/src/client-async/api/client-async-api.cpp @@ -61,6 +61,9 @@ int cynara_async_initialize(cynara_async **pp_cynara, CYNARA_API void cynara_async_finish(cynara_async *p_cynara) { + if (!p_cynara->impl->isFinishPermitted()) + return; + delete p_cynara; } diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp index 5e0157d..48b8bad 100644 --- a/src/client-async/logic/Logic.cpp +++ b/src/client-async/logic/Logic.cpp @@ -43,7 +43,8 @@ namespace Cynara { Logic::Logic(cynara_status_callback callback, void *userStatusData) - : m_statusCallback(callback, userStatusData), m_operationPermitted(true) { + : m_statusCallback(callback, userStatusData), m_operationPermitted(true), + m_inAnswerCancelResponseCallback(false) { m_socketClient = std::make_shared( PathConfig::SocketPath::client, std::make_shared()); @@ -130,12 +131,21 @@ int Logic::cancelRequest(cynara_check_id checkId) { m_socketClient->appendRequest(std::make_shared(it->first)); it->second.cancel(); + + bool onAnswerCancel = m_inAnswerCancelResponseCallback; + m_inAnswerCancelResponseCallback = true; it->second.callback().onCancel(it->first); + m_inAnswerCancelResponseCallback = onAnswerCancel; + onStatusChange(m_socketClient->getSockFd(), cynara_async_status::CYNARA_STATUS_FOR_RW); return CYNARA_API_SUCCESS; } +bool Logic::isFinishPermitted(void) { + return m_operationPermitted && !m_inAnswerCancelResponseCallback; +} + bool Logic::checkCacheValid(void) { return m_socketClient->isConnected(); } @@ -180,9 +190,13 @@ void Logic::processCheckResponse(CheckResponsePtr checkResponse) { CheckData checkData(std::move(it->second)); m_sequenceContainer.release(it->first); m_checks.erase(it); - if (!checkData.cancelled()) + if (!checkData.cancelled()) { + bool onAnswerCancel = m_inAnswerCancelResponseCallback; + m_inAnswerCancelResponseCallback = true; checkData.callback().onAnswer( static_cast(checkResponse->sequenceNumber()), result); + m_inAnswerCancelResponseCallback = onAnswerCancel; + } } void Logic::processCancelResponse(CancelResponsePtr cancelResponse) { diff --git a/src/client-async/logic/Logic.h b/src/client-async/logic/Logic.h index 6f30fdb..6d41412 100644 --- a/src/client-async/logic/Logic.h +++ b/src/client-async/logic/Logic.h @@ -49,6 +49,7 @@ public: void *userResponseData); virtual int process(void); virtual int cancelRequest(cynara_check_id checkId); + virtual bool isFinishPermitted(void); private: typedef std::map CheckMap; @@ -60,6 +61,7 @@ private: CheckMap m_checks; SequenceContainer m_sequenceContainer; bool m_operationPermitted; + bool m_inAnswerCancelResponseCallback; bool checkCacheValid(void); void prepareRequestsToSend(void); diff --git a/src/include/cynara-client-async.h b/src/include/cynara-client-async.h index b9675f1..d9b4d2f 100644 --- a/src/include/cynara-client-async.h +++ b/src/include/cynara-client-async.h @@ -86,6 +86,7 @@ typedef enum { * - probably cynara is unoperational (CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE) * Api functions called during this callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE * or CYNARA_CALL_CAUSE_FINISH cause will return CYNARA_API_OPERATION_NOT_ALLOWED. + * cynara_async_finish() will be ignored if called from within this callback. * * \param[in] check_id Number identifying check request. Number is generated in * cynara_async_create_request() and returned to user. It can be used to match @@ -116,6 +117,7 @@ typedef void (*cynara_response_callback) (cynara_check_id check_id, cynara_async * so user should not use it in other way than waiting on it in event loop. * In particular user should not write to, read from or close this fd. * CYNARA_API_OPERATION_NOT_ALLOWED will be returned for every api function called in this callback. + * cynara_async_finish() will be ignored if called from within this callback. * * \param[in] old_fd Old descriptor which should be unregistered from event loop, * Special value -1 is used when callback is called after first @@ -207,6 +209,8 @@ int cynara_async_initialize(cynara_async **pp_cynara, const cynara_async_configu * * \par Important notes: * No other call to cynara-async-client library should be made after call to cynara_async_finish(). + * cynara_async_finish() called from within cynara_response_callback or cynara_status_callback will + * be ignored. * * \param[in] p_cynara cynara_async structure. If NULL, then the call has no effect. */