vitorsousa pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=5d2948b016955410ca8137ec944b8b91b169dc07

commit 5d2948b016955410ca8137ec944b8b91b169dc07
Author: Vitor Sousa <vitorsousasi...@gmail.com>
Date:   Wed Aug 24 19:43:51 2016 -0300

    elm fileselector: fix possible premature deletion of Listing_Request struct
    
    In a case where eina_promise_then is executed immediately (like with some
    quick and light Efl.Model), the Listing_Request struct will be prematurely
    freed in the first iteration of the child processing loop, because the
    item_total counter had not accumulated the right number of items yet.
    
    With this commit, we traverse the children accessor first, so we can know
    the number of items.
    
    Also, no longer use the Listing_Request pointer after the loop, once it
    may have been deallocate already.
    And put a note about this too.
---
 src/lib/elementary/elc_fileselector.c | 32 ++++++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/src/lib/elementary/elc_fileselector.c 
b/src/lib/elementary/elc_fileselector.c
index ec30015..21bf9c4 100644
--- a/src/lib/elementary/elc_fileselector.c
+++ b/src/lib/elementary/elc_fileselector.c
@@ -774,7 +774,17 @@ _process_child_error_cb(void *data, Eina_Error err 
EINA_UNUSED)
 
    ERR("Failed to access to a model property");
 
-   lreq->item_total--;
+   ++(lreq->item_processed_count);
+   if (lreq->item_processed_count >= lreq->item_total)
+     {
+        if (!lreq->valid)
+          {
+             _listing_request_cleanup(lreq);
+             return;
+          }
+        _signal_first(lreq);
+        _process_last(lreq);
+     }
 }
 
 static void
@@ -800,8 +810,7 @@ _process_children_cb(void *data, void *values)
    Elm_Fileselector_Item_Data *it_data = NULL;
    const char *path = NULL;
    const char *selected_path = NULL;
-   void *child = NULL;
-   unsigned int i = 0;
+   unsigned int count = 0;
    Elm_Fileselector_Data *sd = lreq->sd;
 
    if (!lreq->valid)
@@ -829,7 +838,16 @@ _process_children_cb(void *data, void *values)
         lreq->path = eina_stringshare_add(path);
         if (children_accessor)
           {
-             EINA_ACCESSOR_FOREACH(children_accessor, i, child)
+             Eina_List *children = NULL;
+             void *child = NULL;
+             EINA_ACCESSOR_FOREACH(children_accessor, count, child)
+               {
+                  children = eina_list_append(children, child);
+               }
+
+             lreq->item_total = count;
+
+             EINA_LIST_FREE(children, child)
                {
                   Eina_Promise *promises[7];
                   Eina_Promise *promise_all = NULL;
@@ -862,11 +880,13 @@ _process_children_cb(void *data, void *values)
                   promises[6] = NULL;
 
                   promise_all = 
eina_promise_all(eina_carray_iterator_new((void**)promises));
-                  ++(lreq->item_total);
                   eina_promise_then(promise_all, _process_child_cb, 
_process_child_error_cb, it_data);
                }
+
+             // NOTE: lreq may have been deallocated in the previous loop
+             lreq = NULL;
           }
-        if (lreq->item_total == 0)
+        if (count == 0)
           {
              _signal_first(lreq);
              _process_last(lreq);

-- 


Reply via email to