Manage callbacks lifetime to fix potential use after free 27/204827/4
authorErnest Borowski <e.borowski@partner.samsung.com>
Fri, 26 Apr 2019 15:21:55 +0000 (17:21 +0200)
committerErnest Borowski <e.borowski@partner.samsung.com>
Thu, 6 Jun 2019 13:06:41 +0000 (15:06 +0200)
Askuser notification has callbacks in:
a) timer for delaying exit when home button is pressed
b) transitions for changing popup message to next request

Change-Id: I0326e625a7b91115b67096682e355fc0444faf3e
Signed-off-by: Ernest Borowski <e.borowski@partner.samsung.com>
src/notification-daemon/ui/PopupCheck.h
src/notification-daemon/ui/Popupper.cpp
src/notification-daemon/ui/Popupper.h

index 7f7020b..e6a3dbc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2017 - 2018 Samsung Electronics Co.
+ *  Copyright (c) 2017 - 2019 Samsung Electronics Co.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
 
 #pragma once
 
+#include <memory>
 #include <sstream>
 #include <string>
 
@@ -68,12 +69,14 @@ public:
         PopupCheck *popupCheck = static_cast<PopupCheck*>(data);
         popupCheck->changePopupMessage();
         popupCheck->resetPopupContentState();
+        (void)popupCheck->m_transitOutPtr.release();
     }
 
     static void enableButtonsAfterTransitionCallback(void* data, Elm_Transit*) {
         PopupCheck *popupCheck = static_cast<PopupCheck*>(data);
         elm_object_disabled_set(popupCheck->m_denyButton, EINA_FALSE);
         elm_object_disabled_set(popupCheck->m_allowButton, EINA_FALSE);
+        (void)popupCheck->m_transitPtr.release();
     }
 
     virtual Evas_Object* getAnimatedLayout() = 0;
@@ -91,13 +94,12 @@ public:
 
         m_msg = msg;
         double animation_length_in_sec = 0.075 * 2;
-        Elm_Transit *transitOut = elm_transit_add();// fade out
-        Elm_Transit *transitBetween = elm_transit_add();// slightly delay for changing message
-        Elm_Transit *transit = elm_transit_add();// fade in
-        if (!transitOut || !transitBetween || !transit) { // just change text without transitions
-            elm_transit_del(transitOut);
-            elm_transit_del(transitBetween);
-            elm_transit_del(transit);
+        m_transitOutPtr.reset(elm_transit_add()); // fade out
+        m_transitBetweenPtr.reset(elm_transit_add()); // slightly delay for changing message
+        m_transitPtr.reset(elm_transit_add()); // fade in
+        if (!m_transitOutPtr || !m_transitBetweenPtr || !m_transitPtr) {
+            // just change text without transitions
+            ALOGE("Failed to initialize transition");
             changePopupMessageCallback(this, NULL);
             return true;
         }
@@ -105,30 +107,34 @@ public:
         elm_object_disabled_set(m_denyButton, EINA_TRUE);
         elm_object_disabled_set(m_allowButton, EINA_TRUE);
 
-        elm_transit_effect_wipe_add(transitOut,
+        elm_transit_effect_wipe_add(m_transitOutPtr.get(),
                                     ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE,
                                     ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT);
-        elm_transit_duration_set(transitOut, animation_length_in_sec);
-        elm_transit_tween_mode_set(transitOut, ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL);
+        elm_transit_duration_set(m_transitOutPtr.get(), animation_length_in_sec);
+        elm_transit_tween_mode_set(m_transitOutPtr.get(), ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL);
 
-        elm_transit_object_add(transitBetween, layout);
-        elm_transit_effect_translation_add(transitBetween, -10000, -10000, -10000, -10000);
-        elm_transit_duration_set(transitBetween, animation_length_in_sec);
+        elm_transit_object_add(m_transitBetweenPtr.get(), layout);
+        elm_transit_effect_translation_add(m_transitBetweenPtr.get(), -10000, -10000, -10000, -10000);
+        elm_transit_duration_set(m_transitBetweenPtr.get(), animation_length_in_sec);
 
-        elm_transit_object_add(transit, layout);
-        elm_transit_effect_wipe_add(transit,
+        elm_transit_object_add(m_transitPtr.get(), layout);
+        elm_transit_effect_wipe_add(m_transitPtr.get(),
                                     ELM_TRANSIT_EFFECT_WIPE_TYPE_SHOW,
                                     ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT);
 
 
-        elm_transit_tween_mode_set(transit, ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL);
-        elm_transit_duration_set(transit, animation_length_in_sec);
+        elm_transit_tween_mode_set(m_transitPtr.get(), ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL);
+        elm_transit_duration_set(m_transitPtr.get(), animation_length_in_sec);
 
-        elm_transit_chain_transit_add(transitOut, transitBetween);
-        elm_transit_chain_transit_add(transitBetween, transit);
-        elm_transit_del_cb_set(transitOut, changePopupMessageCallback, this);
-        elm_transit_del_cb_set(transit, enableButtonsAfterTransitionCallback, this);
-        elm_transit_go(transitOut);
+        elm_transit_chain_transit_add(m_transitOutPtr.get(), m_transitBetweenPtr.get());
+        elm_transit_chain_transit_add(m_transitBetweenPtr.get(), m_transitPtr.get());
+        elm_transit_del_cb_set(m_transitOutPtr.get(), changePopupMessageCallback, this);
+        elm_transit_del_cb_set(m_transitPtr.get(), enableButtonsAfterTransitionCallback, this);
+        elm_transit_del_cb_set(m_transitBetweenPtr.get(), [] (void* data, Elm_Transit*) {
+            PopupCheck *popupCheck = static_cast<PopupCheck*>(data);
+            (void)popupCheck->m_transitBetweenPtr.release();
+            }, this);
+        elm_transit_go(m_transitOutPtr.get());
         return true;
     }
 
@@ -138,6 +144,17 @@ public:
 
 protected:
     Evas_Object *m_checkBox = nullptr;
+    struct transitionPtrDeleter {
+        void operator () (Elm_Transit* et) {
+            if (et) {
+                elm_transit_del_cb_set(et, nullptr, nullptr);
+                elm_transit_del(et);
+            }
+        }
+    };
+    std::unique_ptr<Elm_Transit, transitionPtrDeleter> m_transitPtr;
+    std::unique_ptr<Elm_Transit, transitionPtrDeleter> m_transitOutPtr;
+    std::unique_ptr<Elm_Transit, transitionPtrDeleter> m_transitBetweenPtr;
 };
 
 } /* namespace Notification */
index 56b77ff..6f7c31f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2017 - 2018 Samsung Electronics Co.
+ *  Copyright (c) 2017 - 2019 Samsung Electronics Co.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -136,9 +136,11 @@ Eina_Bool Popupper::hwKeyClickedCb(void *data, int type, void *event)
         ALOGD("Respond as deny once.");
         if (!strcmp("XF86Back", ev->key))
             delay = 0;
-        ecore_timer_add(delay,
+        runner->closeDelayTimer(false);
+        runner->m_ecoreDelayExitPtr = ecore_timer_add(delay,
             [](void *data) -> Eina_Bool {
                 Popupper *runner = static_cast<Popupper *>(data);
+                runner->m_ecoreDelayExitPtr = nullptr;
                 runner->respondToRest(NResponseType::None);
                 return ECORE_CALLBACK_CANCEL;
             },
@@ -148,7 +150,17 @@ Eina_Bool Popupper::hwKeyClickedCb(void *data, int type, void *event)
 }
 
 Popupper::~Popupper()
-{}
+{
+    closeDelayTimer();
+}
+
+void Popupper::closeDelayTimer(bool sendRequestResponses) {
+    if (m_ecoreDelayExitPtr) {
+        ecore_timer_del(m_ecoreDelayExitPtr);
+        if (sendRequestResponses)
+            respondToRest(NResponseType::None);
+    }
+}
 
 void Popupper::initialize()
 {
index f9cb337..fbce729 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2017 - 2018 Samsung Electronics Co.
+ *  Copyright (c) 2017 - 2019 Samsung Electronics Co.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -63,11 +63,13 @@ private:
     static Eina_Bool hwKeyClickedCb(void *data, int type, void *event);
 
     void buttonAnswer(IAnswerable::Button button);
+    void closeDelayTimer(bool sendRequestResponses = true);
     void respondToRest(NResponseType response);
     void show();
 
     PopupHandler m_popupResponseHandler;
 
+    Ecore_Timer *m_ecoreDelayExitPtr = nullptr;
     Evas_Object *m_win = nullptr;
     std::unique_ptr<UIElement> m_elementPtr;
     std::unique_ptr<IAnswerable> m_answerablePtr;