From 5863af232b8fc57de210702afe659a7383bb8840 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 9 Feb 2019 14:01:58 +0100 Subject: Fixed another batch of memory leaks. --- plugins/arm/v7/fetch.c | 3 + plugins/itanium/component.c | 13 ++- plugins/pychrysalide/access.c | 22 ++++- plugins/pychrysalide/access.h | 3 + plugins/pychrysalide/analysis/project.c | 3 + plugins/pychrysalide/helpers.c | 4 + plugins/pychrysalide/plugin.c | 37 ++++++--- plugins/pychrysalide/pychrysa.c | 24 +++++- src/analysis/db/collection.c | 14 ++++ src/analysis/project.c | 3 + src/analysis/routine.c | 6 +- src/gleak.c | 137 +++++++++++++++++++++++++++++++- src/gleak.h | 2 + src/main.c | 4 + src/plugins/plugin-def.h | 20 +++-- 15 files changed, 264 insertions(+), 31 deletions(-) diff --git a/plugins/arm/v7/fetch.c b/plugins/arm/v7/fetch.c index 0aa0c6c..6252990 100644 --- a/plugins/arm/v7/fetch.c +++ b/plugins/arm/v7/fetch.c @@ -498,6 +498,9 @@ void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *inst { g_db_comment_add_static_text(comment, "\n"); g_db_comment_add_dynamic_text(comment, desc); + + g_object_unref(G_OBJECT(comment)); + } else diff --git a/plugins/itanium/component.c b/plugins/itanium/component.c index 5ebfeb9..7510b42 100644 --- a/plugins/itanium/component.c +++ b/plugins/itanium/component.c @@ -1408,8 +1408,17 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) result = itd_translate_component_to_type(comp->binary.right); - if (result != NULL && ns != NULL) - itd_prepend_namespace_to_type(result, ns); + if (result != NULL) + { + if (ns != NULL) + itd_prepend_namespace_to_type(result, ns); + } + + else + { + if (ns != NULL) + g_object_unref(G_OBJECT(ns)); + } } diff --git a/plugins/pychrysalide/access.c b/plugins/pychrysalide/access.c index bfaf160..4efa9c7 100644 --- a/plugins/pychrysalide/access.c +++ b/plugins/pychrysalide/access.c @@ -95,8 +95,6 @@ void register_access_to_python_module(const char *path, PyObject *mod) access.path = path; access.mod = mod; - Py_INCREF(mod); - _pychrysalide_modules = qinsert(_pychrysalide_modules, &_pychrysalide_count, sizeof(module_access), (__compar_fn_t)compare_python_module_accesses, &access); @@ -135,3 +133,23 @@ PyObject *get_access_to_python_module(const char *path) return result; } + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Supprime tous les accès rapide aux modules Python. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void clear_all_accesses_to_python_modules(void) +{ + if (_pychrysalide_modules != NULL) + free(_pychrysalide_modules); + +} diff --git a/plugins/pychrysalide/access.h b/plugins/pychrysalide/access.h index 492664d..9a842e4 100644 --- a/plugins/pychrysalide/access.h +++ b/plugins/pychrysalide/access.h @@ -35,6 +35,9 @@ void register_access_to_python_module(const char *, PyObject *); /* Fournit la référence à un module Python défini. */ PyObject *get_access_to_python_module(const char *path); +/* Supprime tous les accès rapide aux modules Python. */ +void clear_all_accesses_to_python_modules(void); + #endif /* _PLUGINS_PYCHRYSALIDE_ACCESS_H */ diff --git a/plugins/pychrysalide/analysis/project.c b/plugins/pychrysalide/analysis/project.c index 9046bf3..98610d5 100644 --- a/plugins/pychrysalide/analysis/project.c +++ b/plugins/pychrysalide/analysis/project.c @@ -308,6 +308,9 @@ static PyObject *py_study_project_get_contents(PyObject *self, void *closure) } + if (contents != NULL) + free(contents); + return result; } diff --git a/plugins/pychrysalide/helpers.c b/plugins/pychrysalide/helpers.c index f744475..48b805c 100644 --- a/plugins/pychrysalide/helpers.c +++ b/plugins/pychrysalide/helpers.c @@ -434,6 +434,8 @@ bool register_python_module_methods(PyObject *module, PyMethodDef *defs) if (result) { + Py_INCREF(item); + ret = PyDict_SetItemString(features_dict, iter->ml_name, item); result = (ret == 0); assert(result); @@ -483,6 +485,8 @@ static bool include_python_type_into_features(PyObject *dict, PyTypeObject *type result = (item != NULL); assert(result); + Py_INCREF(item); + ret = PyDict_SetItemString(features_dict, name, item); result = (ret == 0); assert(result); diff --git a/plugins/pychrysalide/plugin.c b/plugins/pychrysalide/plugin.c index 51da910..9352924 100644 --- a/plugins/pychrysalide/plugin.c +++ b/plugins/pychrysalide/plugin.c @@ -94,9 +94,6 @@ struct _GPythonPlugin { GPluginModule parent; /* Instance parente */ - PyObject *module; /* Script Python chargé */ - PyObject *instance; /* Instance Python du greffon */ - }; @@ -551,6 +548,8 @@ static void py_plugin_module_handle_binary_content_wrapper(const GPluginModule * Py_XDECREF(value); Py_DECREF(args); + Py_DECREF(pyobj); + PyGILState_Release(gstate); } @@ -597,6 +596,8 @@ static void py_plugin_module_handle_loaded_content_wrapper(const GPluginModule * Py_XDECREF(value); Py_DECREF(args); + Py_DECREF(pyobj); + PyGILState_Release(gstate); } @@ -643,6 +644,8 @@ static bool py_plugin_module_handle_binary_format_analysis_wrapper(const GPlugin Py_XDECREF(value); Py_DECREF(args); + Py_DECREF(pyobj); + PyGILState_Release(gstate); return true; @@ -691,6 +694,8 @@ static bool py_plugin_module_preload_binary_format_wrapper(const GPluginModule * Py_XDECREF(value); Py_DECREF(args); + Py_DECREF(pyobj); + PyGILState_Release(gstate); return true; @@ -735,6 +740,8 @@ static void py_plugin_module_attach_debug_format_wrapper(const GPluginModule *pl Py_XDECREF(value); Py_DECREF(args); + Py_DECREF(pyobj); + PyGILState_Release(gstate); } @@ -781,6 +788,8 @@ static void py_plugin_module_process_disassembly_event_wrapper(const GPluginModu Py_XDECREF(value); Py_DECREF(args); + Py_DECREF(pyobj); + PyGILState_Release(gstate); } @@ -903,9 +912,6 @@ static void g_python_plugin_dispose(GPythonPlugin *plugin) if (tstate != NULL) PyEval_RestoreThread(tstate); - Py_XDECREF(plugin->instance); - plugin->instance = NULL; - if (tstate != NULL) PyEval_SaveThread(); @@ -930,15 +936,20 @@ static void g_python_plugin_finalize(GPythonPlugin *plugin) { plugin_interface *final; /* Interface finale conservée */ - Py_XDECREF(plugin->module); - final = (plugin_interface *)G_PLUGIN_MODULE(plugin)->interface; if (final != NULL) { + free(final->name); + free(final->desc); + free(final->version); + assert(final->required_count == 1); free(final->required); + if (final->actions != NULL) + free(final->actions); + free(final); } @@ -1025,10 +1036,14 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename) G_PLUGIN_MODULE(result)->filename = strdup(filename); - result->module = module; - result->instance = instance; + /** + * L'instance Python et l'objet GLib résultante sont un même PyGObject. + * + * Donc pas besoin de toucher au comptage des références ici, la libération + * se réalisera à la fin, quand l'objet GLib sera libéré. + */ - Py_INCREF(instance); + Py_DECREF(module); return G_PLUGIN_MODULE(result); diff --git a/plugins/pychrysalide/pychrysa.c b/plugins/pychrysalide/pychrysa.c index 4cb18d9..3e14add 100644 --- a/plugins/pychrysalide/pychrysa.c +++ b/plugins/pychrysalide/pychrysa.c @@ -306,13 +306,22 @@ static bool set_version_for_gtk_namespace(const char *version) static void PyExit_pychrysalide(void) { + assert(_standalone); + extern void set_current_project(void *project); set_current_project(NULL); #ifdef TRACK_GOBJECT_LEAKS - if (_standalone) - dump_remaining_gtypes(); + remember_gtypes_for_leaks(); +#endif + + exit_all_plugins(); + + unload_all_basic_components(); + +#ifdef TRACK_GOBJECT_LEAKS + dump_remaining_gtypes(); #endif } @@ -500,7 +509,12 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) load_remaning_plugins(); - g_object_unref(G_OBJECT(self)); + /** + * On laisse fuir ici la référence sur self afin d'avoir + * l'assurance que le greffon se déchargera toujours en dernier. + * + * La fuite mémoire est au final évitée dans PyExit_pychrysalide(). + */ } @@ -657,6 +671,8 @@ static void load_python_plugins(GPluginModule *plugin) } + free(paths); + } @@ -737,6 +753,8 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) G_MODULE_EXPORT void chrysalide_plugin_exit(GPluginModule *plugin) { + clear_all_accesses_to_python_modules(); + Py_XDECREF(_chrysalide_module); } diff --git a/src/analysis/db/collection.c b/src/analysis/db/collection.c index 9c28c4a..0a617f3 100644 --- a/src/analysis/db/collection.c +++ b/src/analysis/db/collection.c @@ -149,6 +149,18 @@ static void g_db_collection_init(GDbCollection *collec) static void g_db_collection_dispose(GDbCollection *collec) { + if (collec->items != NULL) + { + g_list_free_full(collec->items, g_object_unref); + collec->items = NULL; + } + + if (collec->sorted != NULL) + { + g_list_free_full(collec->sorted, g_object_unref); + collec->sorted = NULL; + } + G_OBJECT_CLASS(g_db_collection_parent_class)->dispose(G_OBJECT(collec)); } @@ -1130,6 +1142,8 @@ bool g_db_collection_load_all_items(GDbCollection *collec, sqlite3 *db) result = g_db_item_load(new, values, count); result &= g_db_collection_add_item(G_DB_COLLECTION(collec), new); + g_object_unref(G_OBJECT(new)); + } /* Sortie propre */ diff --git a/src/analysis/project.c b/src/analysis/project.c index 6156fbc..57ebcc6 100644 --- a/src/analysis/project.c +++ b/src/analysis/project.c @@ -1345,6 +1345,9 @@ static void on_new_content_resolved(GContentResolver *resolver, wgroup_id_t wid, } + if (handler->filter != NULL) + handler->filter(NULL, handler->data); + } else diff --git a/src/analysis/routine.c b/src/analysis/routine.c index 8b49456..d206e5e 100644 --- a/src/analysis/routine.c +++ b/src/analysis/routine.c @@ -539,12 +539,8 @@ GDataType *g_binary_routine_get_return_type(const GBinRoutine *routine) void g_binary_routine_add_arg(GBinRoutine *routine, GBinVariable *var) { - routine->args_count++; + routine->args = realloc(routine->args, ++routine->args_count * sizeof(GBinVariable *)); - routine->args = (GBinVariable **)realloc(routine->args, - routine->args_count * sizeof(GBinVariable *)); - - g_object_ref(G_OBJECT(var)); routine->args[routine->args_count - 1] = var; } diff --git a/src/gleak.c b/src/gleak.c index 3212d9f..4423cbb 100644 --- a/src/gleak.c +++ b/src/gleak.c @@ -24,10 +24,12 @@ #include "gleak.h" +#include #include #include #include #include +#include #include @@ -39,12 +41,122 @@ #define DUMP_CLOSE_MSG "\n----------------------------------------------\n\n" +/* Description de type utilisé */ +typedef struct _tracked_gtype_t +{ + GType type; /* Type GLib représenté */ + char *name; /* Désignation humaine */ + +} tracked_gtype_t; + +/* Conservation des types même sans les greffons associés */ +static tracked_gtype_t *__tracking = NULL; +static size_t __count = 0; + + +/* Effectue une comparaison entre deux mémorisations de GTypes. */ +static int compare_gtypes_for_leaks(const tracked_gtype_t *, const tracked_gtype_t *); + +/* Constitue une base de données de nom de tous les GTypes. */ +static void _remember_gtypes_for_leaks(GType); /* Parcourt l'arborescence des types à la recherche de fuites. */ static void track_gtype_for_leak(GType, bool *); + +/****************************************************************************** +* * +* Paramètres : a = première description à comparer. * +* b = seconde description à comparer. * +* * +* Description : Effectue une comparaison entre deux mémorisations de GTypes. * +* * +* Retour : Bilan de l'opération (-1, 0 ou 1). * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int compare_gtypes_for_leaks(const tracked_gtype_t *a, const tracked_gtype_t *b) +{ + int result; /* Bilan à retourner */ + + if (a->type < b->type) + result = -1; + + else if (a->type > b->type) + result = 1; + + else + result = 0; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : root = racine des types d'instance à parcourir. * +* * +* Description : Constitue une base de données de nom de tous les GTypes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void _remember_gtypes_for_leaks(GType root) +{ + GType *children; /* Liste de tous les sous-types*/ + guint count; /* Taille de cette liste */ + tracked_gtype_t *new; /* Nouvelle feuille à mémoriser*/ + GType *iter; /* Boucle de parcours */ + + children = g_type_children(root, &count); + + if (count == 0) + { + __tracking = realloc(__tracking, ++__count * sizeof(tracked_gtype_t)); + + new = &__tracking[__count - 1]; + + new->type = root; + new->name = strdup(g_type_name(root)); + + } + + else + for (iter = children; *iter != 0; iter++) + _remember_gtypes_for_leaks(*iter); + + g_free(children); + +} + + +/****************************************************************************** +* * +* Paramètres : root = racine des types d'instance à parcourir. * +* * +* Description : Constitue une base de données de nom de tous les GTypes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void remember_gtypes_for_leaks(void) +{ + _remember_gtypes_for_leaks(G_TYPE_OBJECT); + +} + + /****************************************************************************** * * * Paramètres : root = racine des types d'instance à retrouver. * @@ -62,8 +174,9 @@ static void track_gtype_for_leak(GType root, bool *first) { GType *children; /* Liste de tous les sous-types*/ guint count; /* Taille de cette liste */ - GType *iter; /* Boucle de parcours */ int remaining; /* Nombre d'instances restantes*/ + const tracked_gtype_t *tracked; /* Infos de type mémorisées */ + GType *iter; /* Boucle de parcours */ children = g_type_children(root, &count); @@ -79,7 +192,12 @@ static void track_gtype_for_leak(GType root, bool *first) *first = false; } - fprintf(stderr, "%s: %d\n", g_type_name(root), remaining); + tracked = bsearch((tracked_gtype_t []) { { .type = root } }, __tracking, + __count, sizeof(tracked_gtype_t), (__compar_fn_t)compare_gtypes_for_leaks); + + assert(tracked != NULL); + + fprintf(stderr, "%s: %d\n", tracked->name, remaining); } @@ -110,6 +228,7 @@ void dump_remaining_gtypes(void) { char *debug; /* Conditions d'environnement */ bool first; /* Première fois ? */ + size_t i; /* Boucle de parcours */ debug = get_env_var("GOBJECT_DEBUG"); @@ -125,6 +244,8 @@ void dump_remaining_gtypes(void) { first = true; + qsort(__tracking, __count, sizeof(tracked_gtype_t), (__compar_fn_t)compare_gtypes_for_leaks); + track_gtype_for_leak(G_TYPE_OBJECT, &first); if (!first) @@ -134,4 +255,16 @@ void dump_remaining_gtypes(void) free(debug); + for (i = 0; i < __count; i++) + free(__tracking[i].name); + + if (__tracking != NULL) + { + free(__tracking); + + __tracking = NULL; + __count = 0; + + } + } diff --git a/src/gleak.h b/src/gleak.h index 233fabb..f80e167 100644 --- a/src/gleak.h +++ b/src/gleak.h @@ -25,6 +25,8 @@ #define _GLEAK_H +/* Constitue une base de données de nom de tous les GTypes. */ +void remember_gtypes_for_leaks(void); /* Affiche la liste des instances courantes restantes par type. */ void dump_remaining_gtypes(void); diff --git a/src/main.c b/src/main.c index ef0335a..e5a964e 100644 --- a/src/main.c +++ b/src/main.c @@ -404,6 +404,10 @@ int main(int argc, char **argv) exit_complete_gui: +#ifdef TRACK_GOBJECT_LEAKS + remember_gtypes_for_leaks(); +#endif + exit_all_plugins(); if (!batch_mode) diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h index 6d4253e..3717035 100644 --- a/src/plugins/plugin-def.h +++ b/src/plugins/plugin-def.h @@ -223,14 +223,22 @@ typedef struct _plugin_interface uint64_t magic; /* Vérification a minima */ plugin_abi_version_t abi_version; /* Version du protocole utilisé*/ - const char *gtp_name; /* Désignation du GType associé*/ - const char *name; /* Désignation humaine courte */ - const char *desc; /* Description plus loquace */ - const char *version; /* Version du greffon */ + /** + * Les champs suivants ne sont généralement pas alloués dynamiquement, + * car issus des données des greffons natifs. + * + * Dans le cas des autres types d'extensions (par exemple ceux en Python), + * les éléments sont construits à la volée, donc à libérer après usage. + */ + + char *gtp_name; /* Désignation du GType associé*/ + char *name; /* Désignation humaine courte */ + char *desc; /* Description plus loquace */ + char *version; /* Version du greffon */ bool container; /* Mise en place de greffons ? */ - const char **required; /* Pré-chargements requis */ + char **required; /* Pré-chargements requis */ size_t required_count; /* Quantité de ces dépendances */ plugin_action_t *actions; /* Liste des actions gérées */ @@ -251,7 +259,7 @@ typedef struct _plugin_interface #define AL(...) BUILD_PG_LIST(.actions, ((plugin_action_t []){ __VA_ARGS__ })) -#define RL(...) BUILD_PG_LIST(.required, ((const char *[]){ __VA_ARGS__ })) +#define RL(...) BUILD_PG_LIST(.required, ((char *[]){ __VA_ARGS__ })) #define NO_REQ EMPTY_PG_LIST(.required) -- cgit v0.11.2-87-g4458