diff options
author | Vitor Sousa <vitorsousasilva@gmail.com> | 2016-08-24 19:43:51 -0300 |
---|---|---|
committer | Vitor Sousa <vitorsousasilva@gmail.com> | 2016-08-26 19:45:26 -0300 |
commit | 5d2948b016955410ca8137ec944b8b91b169dc07 (patch) | |
tree | b0a58041163afaf86a2d919b7af5d7cc2b8d98b7 | |
parent | 1ab1e3697dc4dfead65fadc02747d876c993f935 (diff) |
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.
-rw-r--r-- | src/lib/elementary/elc_fileselector.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/src/lib/elementary/elc_fileselector.c b/src/lib/elementary/elc_fileselector.c index ec30015fb3..21bf9c4f65 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) | |||
774 | 774 | ||
775 | ERR("Failed to access to a model property"); | 775 | ERR("Failed to access to a model property"); |
776 | 776 | ||
777 | lreq->item_total--; | 777 | ++(lreq->item_processed_count); |
778 | if (lreq->item_processed_count >= lreq->item_total) | ||
779 | { | ||
780 | if (!lreq->valid) | ||
781 | { | ||
782 | _listing_request_cleanup(lreq); | ||
783 | return; | ||
784 | } | ||
785 | _signal_first(lreq); | ||
786 | _process_last(lreq); | ||
787 | } | ||
778 | } | 788 | } |
779 | 789 | ||
780 | static void | 790 | static void |
@@ -800,8 +810,7 @@ _process_children_cb(void *data, void *values) | |||
800 | Elm_Fileselector_Item_Data *it_data = NULL; | 810 | Elm_Fileselector_Item_Data *it_data = NULL; |
801 | const char *path = NULL; | 811 | const char *path = NULL; |
802 | const char *selected_path = NULL; | 812 | const char *selected_path = NULL; |
803 | void *child = NULL; | 813 | unsigned int count = 0; |
804 | unsigned int i = 0; | ||
805 | Elm_Fileselector_Data *sd = lreq->sd; | 814 | Elm_Fileselector_Data *sd = lreq->sd; |
806 | 815 | ||
807 | if (!lreq->valid) | 816 | if (!lreq->valid) |
@@ -829,7 +838,16 @@ _process_children_cb(void *data, void *values) | |||
829 | lreq->path = eina_stringshare_add(path); | 838 | lreq->path = eina_stringshare_add(path); |
830 | if (children_accessor) | 839 | if (children_accessor) |
831 | { | 840 | { |
832 | EINA_ACCESSOR_FOREACH(children_accessor, i, child) | 841 | Eina_List *children = NULL; |
842 | void *child = NULL; | ||
843 | EINA_ACCESSOR_FOREACH(children_accessor, count, child) | ||
844 | { | ||
845 | children = eina_list_append(children, child); | ||
846 | } | ||
847 | |||
848 | lreq->item_total = count; | ||
849 | |||
850 | EINA_LIST_FREE(children, child) | ||
833 | { | 851 | { |
834 | Eina_Promise *promises[7]; | 852 | Eina_Promise *promises[7]; |
835 | Eina_Promise *promise_all = NULL; | 853 | Eina_Promise *promise_all = NULL; |
@@ -862,11 +880,13 @@ _process_children_cb(void *data, void *values) | |||
862 | promises[6] = NULL; | 880 | promises[6] = NULL; |
863 | 881 | ||
864 | promise_all = eina_promise_all(eina_carray_iterator_new((void**)promises)); | 882 | promise_all = eina_promise_all(eina_carray_iterator_new((void**)promises)); |
865 | ++(lreq->item_total); | ||
866 | eina_promise_then(promise_all, _process_child_cb, _process_child_error_cb, it_data); | 883 | eina_promise_then(promise_all, _process_child_cb, _process_child_error_cb, it_data); |
867 | } | 884 | } |
885 | |||
886 | // NOTE: lreq may have been deallocated in the previous loop | ||
887 | lreq = NULL; | ||
868 | } | 888 | } |
869 | if (lreq->item_total == 0) | 889 | if (count == 0) |
870 | { | 890 | { |
871 | _signal_first(lreq); | 891 | _signal_first(lreq); |
872 | _process_last(lreq); | 892 | _process_last(lreq); |