summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJérémy Zurcher <jeremy@asynk.ch>2014-11-18 15:24:39 +0000
committerTom Hacohen <tom@stosb.com>2014-11-18 15:25:34 +0000
commit18ceed4daf31d2f19261e0fe018c870581357ed0 (patch)
treee66a4a1564982d4d7d67f1ef3509740c767cf926
parentee3bcaf71d978d225518edf570985525caafa3c9 (diff)
Eo: protect against recursive object destruction calls, fixes T1741
Summary: Eo: semantic obj->del replaced by obj->destructed Eo: protect against recursive object destruction calls Eo: add tests for bfada4b Reviewers: JackDanielZ, tasn Reviewed By: tasn Subscribers: cedric Maniphest Tasks: T1741 Differential Revision: https://phab.enlightenment.org/D1675 Fixes T1741 @fix
-rw-r--r--src/Makefile_Eo.am1
-rw-r--r--src/lib/eo/eo.c4
-rw-r--r--src/lib/eo/eo_private.h16
-rw-r--r--src/tests/eo/suite/eo_suite.c1
-rw-r--r--src/tests/eo/suite/eo_suite.h1
-rw-r--r--src/tests/eo/suite/eo_test_class_behaviour_errors.c63
6 files changed, 80 insertions, 6 deletions
diff --git a/src/Makefile_Eo.am b/src/Makefile_Eo.am
index 306c8c3623..1b3ea4a75d 100644
--- a/src/Makefile_Eo.am
+++ b/src/Makefile_Eo.am
@@ -121,6 +121,7 @@ tests/eo/suite/eo_suite.h \
121tests/eo/suite/eo_error_msgs.h \ 121tests/eo/suite/eo_error_msgs.h \
122tests/eo/suite/eo_error_msgs.c \ 122tests/eo/suite/eo_error_msgs.c \
123tests/eo/suite/eo_test_class_errors.c \ 123tests/eo/suite/eo_test_class_errors.c \
124tests/eo/suite/eo_test_class_behaviour_errors.c \
124tests/eo/suite/eo_test_call_errors.c \ 125tests/eo/suite/eo_test_call_errors.c \
125tests/eo/suite/eo_test_general.c \ 126tests/eo/suite/eo_test_general.c \
126tests/eo/suite/eo_test_value.c \ 127tests/eo/suite/eo_test_value.c \
diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c
index 37dae75deb..cc1f8b9f02 100644
--- a/src/lib/eo/eo.c
+++ b/src/lib/eo/eo.c
@@ -1855,7 +1855,7 @@ eo_destructed_is(const Eo *obj_id)
1855{ 1855{
1856 EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, EINA_FALSE); 1856 EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, EINA_FALSE);
1857 1857
1858 return obj->del; 1858 return obj->destructed;
1859} 1859}
1860 1860
1861EAPI void 1861EAPI void
@@ -1876,7 +1876,7 @@ eo_manual_free(Eo *obj_id)
1876 return EINA_FALSE; 1876 return EINA_FALSE;
1877 } 1877 }
1878 1878
1879 if (!obj->del) 1879 if (!obj->destructed)
1880 { 1880 {
1881 ERR("Tried deleting the object %p while still referenced(%d).", obj_id, obj->refcount); 1881 ERR("Tried deleting the object %p while still referenced(%d).", obj_id, obj->refcount);
1882 return EINA_FALSE; 1882 return EINA_FALSE;
diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h
index c652271dd6..7ea501450f 100644
--- a/src/lib/eo/eo_private.h
+++ b/src/lib/eo/eo_private.h
@@ -104,7 +104,8 @@ struct _Eo_Object
104 Eina_Bool finalized:1; 104 Eina_Bool finalized:1;
105 105
106 Eina_Bool composite:1; 106 Eina_Bool composite:1;
107 Eina_Bool del:1; 107 Eina_Bool del_triggered:1;
108 Eina_Bool destructed:1;
108 Eina_Bool manual_free:1; 109 Eina_Bool manual_free:1;
109}; 110};
110 111
@@ -235,7 +236,7 @@ _eo_del_internal(const char *file, int line, _Eo_Object *obj)
235 } 236 }
236 } 237 }
237 238
238 obj->del = EINA_TRUE; 239 obj->destructed = EINA_TRUE;
239 obj->refcount--; 240 obj->refcount--;
240} 241}
241 242
@@ -278,9 +279,16 @@ _eo_unref(_Eo_Object *obj)
278 --(obj->refcount); 279 --(obj->refcount);
279 if (obj->refcount == 0) 280 if (obj->refcount == 0)
280 { 281 {
281 if (obj->del) 282 if (obj->del_triggered)
282 { 283 {
283 ERR("Object %p already deleted.", obj); 284 ERR("Object %p deletion already triggered. You wrongly call eo_unref() within a destructor.", obj);
285 return;
286 }
287 obj->del_triggered = EINA_TRUE;
288
289 if (obj->destructed)
290 {
291 ERR("Object %p already destructed.", obj);
284 return; 292 return;
285 } 293 }
286 294
diff --git a/src/tests/eo/suite/eo_suite.c b/src/tests/eo/suite/eo_suite.c
index 42c6645156..90f557745d 100644
--- a/src/tests/eo/suite/eo_suite.c
+++ b/src/tests/eo/suite/eo_suite.c
@@ -20,6 +20,7 @@ static const Eo_Test_Case etc[] = {
20 { "Eo init", eo_test_init }, 20 { "Eo init", eo_test_init },
21 { "Eo general", eo_test_general }, 21 { "Eo general", eo_test_general },
22 { "Eo class errors", eo_test_class_errors }, 22 { "Eo class errors", eo_test_class_errors },
23 { "Eo class behaviour errors", eo_test_class_behaviour_errors },
23 { "Eo call errors", eo_test_call_errors }, 24 { "Eo call errors", eo_test_call_errors },
24 { "Eo eina value", eo_test_value }, 25 { "Eo eina value", eo_test_value },
25 { "Eo threaded eo calls", eo_test_threaded_calls }, 26 { "Eo threaded eo calls", eo_test_threaded_calls },
diff --git a/src/tests/eo/suite/eo_suite.h b/src/tests/eo/suite/eo_suite.h
index 94d88bd1fe..ba07799bc9 100644
--- a/src/tests/eo/suite/eo_suite.h
+++ b/src/tests/eo/suite/eo_suite.h
@@ -6,6 +6,7 @@
6void eo_test_init(TCase *tc); 6void eo_test_init(TCase *tc);
7void eo_test_general(TCase *tc); 7void eo_test_general(TCase *tc);
8void eo_test_class_errors(TCase *tc); 8void eo_test_class_errors(TCase *tc);
9void eo_test_class_behaviour_errors(TCase *tc);
9void eo_test_call_errors(TCase *tc); 10void eo_test_call_errors(TCase *tc);
10void eo_test_value(TCase *tc); 11void eo_test_value(TCase *tc);
11void eo_test_threaded_calls(TCase *tc); 12void eo_test_threaded_calls(TCase *tc);
diff --git a/src/tests/eo/suite/eo_test_class_behaviour_errors.c b/src/tests/eo/suite/eo_test_class_behaviour_errors.c
new file mode 100644
index 0000000000..1bd0e15c76
--- /dev/null
+++ b/src/tests/eo/suite/eo_test_class_behaviour_errors.c
@@ -0,0 +1,63 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdio.h>
6
7#include "Eo.h"
8#include "eo_suite.h"
9#include "eo_error_msgs.h"
10#include "eo_test_class_simple.h"
11
12static struct log_ctx ctx;
13
14const Eo_Class *klass;
15
16static void _destructor_unref(Eo *obj, void *class_data EINA_UNUSED)
17{
18 eo_do_super(obj, klass, eo_destructor());
19
20 /* this triggers an eo stack overflow if not correctly protected */
21 eo_unref(obj);
22}
23
24START_TEST(eo_destructor_unref)
25{
26 eo_init();
27 eina_log_print_cb_set(eo_test_print_cb, &ctx);
28
29 static Eo_Op_Description op_descs [] = {
30 EO_OP_FUNC_OVERRIDE(eo_destructor, _destructor_unref),
31 EO_OP_SENTINEL
32 };
33
34 static Eo_Class_Description class_desc = {
35 EO_VERSION,
36 "Simple",
37 EO_CLASS_TYPE_REGULAR,
38 EO_CLASS_DESCRIPTION_OPS(op_descs),
39 NULL,
40 0,
41 NULL,
42 NULL
43 };
44
45 klass = eo_class_new(&class_desc, SIMPLE_CLASS, NULL);
46 fail_unless(klass);
47
48 Eo *obj = eo_add(klass, NULL);
49 fail_unless(obj);
50
51 TEST_EO_ERROR("_eo_unref", "Object %p deletion already triggered. You wrongly call eo_unref() within a destructor.");
52 eo_unref(obj);
53
54 eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
55
56 eo_shutdown();
57}
58END_TEST
59
60void eo_test_class_behaviour_errors(TCase *tc)
61{
62 tcase_add_test(tc, eo_destructor_unref);
63}