diff options
Diffstat (limited to 'src/analysis/scan')
58 files changed, 1897 insertions, 1818 deletions
diff --git a/src/analysis/scan/Makefile.am b/src/analysis/scan/Makefile.am index bcec986..d4d7aa4 100644 --- a/src/analysis/scan/Makefile.am +++ b/src/analysis/scan/Makefile.am @@ -24,8 +24,6 @@ libanalysisscan_la_SOURCES = \ core.h core.c \ expr-int.h \ expr.h expr.c \ - func-int.h \ - func.h func.c \ item-int.h \ item.h item.c \ match-int.h \ @@ -45,7 +43,7 @@ libanalysisscan_la_SOURCES = \ libanalysisscan_la_LIBADD = \ exprs/libanalysisscanexprs.la \ - funcs/libanalysisscanfuncs.la \ + items/libanalysisscanitems.la \ matches/libanalysisscanmatches.la \ patterns/libanalysisscanpatterns.la @@ -64,4 +62,4 @@ CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h EXTRA_DIST = tokens.h -SUBDIRS = exprs funcs matches patterns +SUBDIRS = exprs items matches patterns diff --git a/src/analysis/scan/conds/Makefile.am b/src/analysis/scan/conds/Makefile.am deleted file mode 100644 index 402deac..0000000 --- a/src/analysis/scan/conds/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ - -noinst_LTLIBRARIES = libanalysisscanconds.la - - -libanalysisscanconds_la_SOURCES = \ - binop-int.h \ - binop.h binop.c \ - counter-int.h \ - counter.h counter.c - -libanalysisscanconds_la_CFLAGS = $(LIBGOBJ_CFLAGS) - - -devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) - -dev_HEADERS = $(libanalysisscanconds_la_SOURCES:%c=) diff --git a/src/analysis/scan/conds/binop-int.h b/src/analysis/scan/conds/binop-int.h deleted file mode 100644 index 0fc5940..0000000 --- a/src/analysis/scan/conds/binop-int.h +++ /dev/null @@ -1,54 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * binop-int.h - prototypes internes pour les opérations booléennes impliquant deux opérandes - * - * Copyright (C) 2022 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * Chrysalide is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Chrysalide is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _ANALYSIS_SCAN_CONDS_BINOP_INT_H -#define _ANALYSIS_SCAN_CONDS_BINOP_INT_H - - -#include "binop.h" - - -#include "../cond-int.h" - - - -/* Opération booléenne impliquant deux opérandes (instance) */ -struct _GBinaryOperation -{ - GMatchCondition parent; /* A laisser en premier */ - - GMatchCondition *conds[2]; /* Opérandes à manipuler */ - BinOpType type; /* Type de manipulation */ - -}; - -/* Opération booléenne impliquant deux opérandes (classe) */ -struct _GBinaryOperationClass -{ - GMatchConditionClass parent; /* A laisser en premier */ - -}; - - - -#endif /* _ANALYSIS_SCAN_CONDS_BINOP_INT_H */ diff --git a/src/analysis/scan/conds/binop.c b/src/analysis/scan/conds/binop.c deleted file mode 100644 index 01e99d9..0000000 --- a/src/analysis/scan/conds/binop.c +++ /dev/null @@ -1,265 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * binop.c - opérations booléennes impliquant deux opérandes - * - * Copyright (C) 2022 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * Chrysalide is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Chrysalide is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "binop.h" - - -#include "binop-int.h" - - - -/* --------------------- INSTANCIATION D'UNE FORME DE CONDITION --------------------- */ - - -/* Initialise la classe des opérations booléennes. */ -static void g_binary_operation_class_init(GBinaryOperationClass *); - -/* Initialise une instance d'opération booléenne. */ -static void g_binary_operation_init(GBinaryOperation *); - -/* Supprime toutes les références externes. */ -static void g_binary_operation_dispose(GBinaryOperation *); - -/* Procède à la libération totale de la mémoire. */ -static void g_binary_operation_finalize(GBinaryOperation *); - - - -/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ - - -/* Indique le statut d'une condition de validation. */ -static bool g_binary_operation_resolve(const GBinaryOperation *); - -/* Lance l'analyse de contenu binaire selon un motif donné. */ -static void g_binary_operation_analyze(const GBinaryOperation *, const bin_t *, phys_t, phys_t, bool); - - - -/* ---------------------------------------------------------------------------------- */ -/* INSTANCIATION D'UNE FORME DE CONDITION */ -/* ---------------------------------------------------------------------------------- */ - - -/* Indique le type défini pour une opération booléenne de validation. */ -G_DEFINE_TYPE(GBinaryOperation, g_binary_operation, G_TYPE_MATCH_CONDITION); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des opérations booléennes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_binary_operation_class_init(GBinaryOperationClass *klass) -{ - GObjectClass *object; /* Autre version de la classe */ - GMatchConditionClass *cond; /* Classe parente directe */ - - object = G_OBJECT_CLASS(klass); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_binary_operation_dispose; - object->finalize = (GObjectFinalizeFunc)g_binary_operation_finalize; - - cond = G_MATCH_CONDITION_CLASS(klass); - - cond->resolve = (resolve_cond_fc)g_binary_operation_resolve; - cond->analyze = (analyze_cond_fc)g_binary_operation_analyze; - -} - - -/****************************************************************************** -* * -* Paramètres : op = instance à initialiser. * -* * -* Description : Initialise une instance d'opération booléenne. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_binary_operation_init(GBinaryOperation *op) -{ - op->conds[0] = NULL; - op->conds[1] = NULL; - - op->type = BOT_AND; - -} - - -/****************************************************************************** -* * -* Paramètres : op = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_binary_operation_dispose(GBinaryOperation *op) -{ - g_clear_object(&op->conds[0]); - g_clear_object(&op->conds[1]); - - G_OBJECT_CLASS(g_binary_operation_parent_class)->dispose(G_OBJECT(op)); - -} - - -/****************************************************************************** -* * -* Paramètres : op = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_binary_operation_finalize(GBinaryOperation *op) -{ - G_OBJECT_CLASS(g_binary_operation_parent_class)->finalize(G_OBJECT(op)); - -} - - -/****************************************************************************** -* * -* Paramètres : op1 = premier opérande à intégrer. * -* op2 = second opérande à intégrer. * -* type = type d'opération à prendre en compte. * -* * -* Description : Met en place une représentation d'opération booléenne. * -* * -* Retour : Condition mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBinaryOperation *g_binary_operation_new(GMatchCondition *op1, GMatchCondition *op2, BinOpType type) -{ - GBinaryOperation *result; /* Structure à retourner */ - - result = g_object_new(G_TYPE_BINARY_OPERATION, NULL); - - result->conds[0] = op1; - g_object_ref(G_OBJECT(op1)); - - result->conds[1] = op2; - g_object_ref(G_OBJECT(op2)); - - result->type = type; - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : op = condition à consulter. * -* * -* Description : Indique le statut d'une condition de validation. * -* * -* Retour : Validation de la condition considérée. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_binary_operation_resolve(const GBinaryOperation *op) -{ - bool result; /* Bilan à retourner */ - - result = g_match_condition_resolve(op->conds[0]); - - switch (op->type) - { - case BOT_AND: - default: - if (result) - result = g_match_condition_resolve(op->conds[1]); - break; - - case BOT_OR: - if (!result) - result = g_match_condition_resolve(op->conds[1]); - break; - - case BOT_XOR: - result ^= g_match_condition_resolve(op->conds[1]); - break; - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : op = condition à considérer. * -* data = données binaires brutes à considérer. * -* size = quantité de ces données. * -* pos = position du point d'étude courant. * -* full = force une recherche pleine et entière. * -* * -* Description : Lance l'analyse de contenu binaire selon un motif donné. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_binary_operation_analyze(const GBinaryOperation *op, const bin_t *data, phys_t size, phys_t pos, bool full) -{ - g_match_condition_analyze(op->conds[0], data, size, pos, full); - - if (full || !g_binary_operation_resolve(op)) - g_match_condition_analyze(op->conds[1], data, size, pos, full); - -} diff --git a/src/analysis/scan/conds/binop.h b/src/analysis/scan/conds/binop.h deleted file mode 100644 index 55cb515..0000000 --- a/src/analysis/scan/conds/binop.h +++ /dev/null @@ -1,68 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * binop.h - prototypes pour les opérations booléennes impliquant deux opérandes - * - * Copyright (C) 2022 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * Chrysalide is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Chrysalide is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _ANALYSIS_SCAN_CONDS_BINOP_H -#define _ANALYSIS_SCAN_CONDS_BINOP_H - - -#include <glib-object.h> - - -#include "../cond.h" - - - -#define G_TYPE_BINARY_OPERATION g_binary_operation_get_type() -#define G_BINARY_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BINARY_OPERATION, GBinaryOperation)) -#define G_IS_BINARY_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BINARY_OPERATION)) -#define G_BINARY_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BINARY_OPERATION, GBinaryOperationClass)) -#define G_IS_BINARY_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BINARY_OPERATION)) -#define G_BINARY_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BINARY_OPERATION, GBinaryOperationClass)) - - -/* Opération booléenne impliquant deux opérandes (instance) */ -typedef struct _GBinaryOperation GBinaryOperation; - -/* Opération booléenne impliquant deux opérandes (classe) */ -typedef struct _GBinaryOperationClass GBinaryOperationClass; - - -/* Types d'opérations booléennes disponibles */ -typedef enum _BinOpType -{ - BOT_AND, - BOT_OR, - BOT_XOR, - -} BinOpType; - - -/* Indique le type défini pour une opération booléenne de validation. */ -GType g_binary_operation_get_type(void); - -/* Met en place une représentation d'opération booléenne. */ -GBinaryOperation *g_binary_operation_new(GMatchCondition *, GMatchCondition *, BinOpType); - - - -#endif /* _ANALYSIS_SCAN_CONDS_BINOP_H */ diff --git a/src/analysis/scan/conds/counter-int.h b/src/analysis/scan/conds/counter-int.h deleted file mode 100644 index a706fca..0000000 --- a/src/analysis/scan/conds/counter-int.h +++ /dev/null @@ -1,53 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * counter-int.h - prototypes internes pour le décompte de correspondances identifiées dans du contenu binaire - * - * Copyright (C) 2022 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * Chrysalide is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Chrysalide is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _ANALYSIS_SCAN_CONDS_COUNTER_INT_H -#define _ANALYSIS_SCAN_CONDS_COUNTER_INT_H - - -#include "counter.h" - - -#include "../cond-int.h" - - - -/* Décompte des identifications de motifs (instance) */ -struct _GMatchCounter -{ - GMatchCondition parent; /* A laisser en premier */ - - GSearchPattern *pattern; /* Motif associé */ - -}; - -/* Décompte des identifications de motifs (classe) */ -struct _GMatchCounterClass -{ - GMatchConditionClass parent; /* A laisser en premier */ - -}; - - - -#endif /* _ANALYSIS_SCAN_CONDS_COUNTER_INT_H */ diff --git a/src/analysis/scan/conds/counter.c b/src/analysis/scan/conds/counter.c deleted file mode 100644 index 7cf36b8..0000000 --- a/src/analysis/scan/conds/counter.c +++ /dev/null @@ -1,232 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * counter.c - décompte de correspondances identifiées dans du contenu binaire - * - * Copyright (C) 2022 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * Chrysalide is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Chrysalide is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "counter.h" - - -#include "counter-int.h" - - - -/* --------------------- INSTANCIATION D'UNE FORME DE CONDITION --------------------- */ - - -/* Initialise la classe des opérations booléennes. */ -static void g_match_counter_class_init(GMatchCounterClass *); - -/* Initialise une instance d'opération booléenne. */ -static void g_match_counter_init(GMatchCounter *); - -/* Supprime toutes les références externes. */ -static void g_match_counter_dispose(GMatchCounter *); - -/* Procède à la libération totale de la mémoire. */ -static void g_match_counter_finalize(GMatchCounter *); - - - -/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ - - -/* Indique le statut d'une condition de validation. */ -static unsigned long long g_match_counter_resolve_as_number(const GMatchCounter *); - -/* Lance l'analyse de contenu binaire selon un motif donné. */ -static void g_match_counter_analyze(const GMatchCounter *, const bin_t *, phys_t, phys_t, bool); - - - -/* ---------------------------------------------------------------------------------- */ -/* INSTANCIATION D'UNE FORME DE CONDITION */ -/* ---------------------------------------------------------------------------------- */ - - -/* Indique le type défini pour un décompte de résultats lors d'une recherche de motifs. */ -G_DEFINE_TYPE(GMatchCounter, g_match_counter, G_TYPE_MATCH_CONDITION); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des opérations booléennes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_match_counter_class_init(GMatchCounterClass *klass) -{ - GObjectClass *object; /* Autre version de la classe */ - GMatchConditionClass *cond; /* Classe parente directe */ - - object = G_OBJECT_CLASS(klass); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_match_counter_dispose; - object->finalize = (GObjectFinalizeFunc)g_match_counter_finalize; - - cond = G_MATCH_CONDITION_CLASS(klass); - - cond->resolve_as_num = (resolve_cond_as_number_fc)g_match_counter_resolve_as_number; - cond->analyze = (analyze_cond_fc)g_match_counter_analyze; - -} - - -/****************************************************************************** -* * -* Paramètres : op = instance à initialiser. * -* * -* Description : Initialise une instance d'opération booléenne. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_match_counter_init(GMatchCounter *counter) -{ - counter->pattern = NULL; - -} - - -/****************************************************************************** -* * -* Paramètres : op = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_match_counter_dispose(GMatchCounter *counter) -{ - g_clear_object(&counter->pattern); - - G_OBJECT_CLASS(g_match_counter_parent_class)->dispose(G_OBJECT(counter)); - -} - - -/****************************************************************************** -* * -* Paramètres : op = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_match_counter_finalize(GMatchCounter *counter) -{ - G_OBJECT_CLASS(g_match_counter_parent_class)->finalize(G_OBJECT(counter)); - -} - - -/****************************************************************************** -* * -* Paramètres : pattern = motif à impliquer. * -* * -* Description : Met en place un décompte de correspondances obtenues. * -* * -* Retour : Condition mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GMatchCounter *g_match_counter_new(GSearchPattern *pattern) -{ - GMatchCounter *result; /* Structure à retourner */ - - result = g_object_new(G_TYPE_MATCH_COUNTER, NULL); - - result->pattern = pattern; - g_object_ref(G_OBJECT(pattern)); - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : op = condition à consulter. * -* * -* Description : Indique le statut d'une condition de validation. * -* * -* Retour : Forme numérique de la condition considérée pour validation. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static unsigned long long g_match_counter_resolve_as_number(const GMatchCounter *counter) -{ - unsigned long long result; /* Valeur à retourner */ - - result = g_search_pattern_count_matchs(counter->pattern); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : counter = condition à considérer. * -* data = données binaires brutes à considérer. * -* size = quantité de ces données. * -* pos = position du point d'étude courant. * -* full = force une recherche pleine et entière. * -* * -* Description : Lance l'analyse de contenu binaire selon un motif donné. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_match_counter_analyze(const GMatchCounter *counter, const bin_t *data, phys_t size, phys_t pos, bool full) -{ - //g_search_pattern_analyze(counter->pattern, data, size, pos); - -} diff --git a/src/analysis/scan/conds/counter.h b/src/analysis/scan/conds/counter.h deleted file mode 100644 index 033ac99..0000000 --- a/src/analysis/scan/conds/counter.h +++ /dev/null @@ -1,58 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * counter.h - prototypes pour le décompte de correspondances identifiées dans du contenu binaire - * - * Copyright (C) 2022 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * Chrysalide is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Chrysalide is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _ANALYSIS_SCAN_CONDS_COUNTER_H -#define _ANALYSIS_SCAN_CONDS_COUNTER_H - - -#include <glib-object.h> - - -#include "../pattern.h" - - - -#define G_TYPE_MATCH_COUNTER g_match_counter_get_type() -#define G_MATCH_COUNTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_MATCH_COUNTER, GMatchCounter)) -#define G_IS_MATCH_COUNTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_MATCH_COUNTER)) -#define G_MATCH_COUNTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_MATCH_COUNTER, GMatchCounterClass)) -#define G_IS_MATCH_COUNTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_MATCH_COUNTER)) -#define G_MATCH_COUNTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_MATCH_COUNTER, GMatchCounterClass)) - - -/* Décompte des identifications de motifs (instance) */ -typedef struct _GMatchCounter GMatchCounter; - -/* Décompte des identifications de motifs (classe) */ -typedef struct _GMatchCounterClass GMatchCounterClass; - - -/* Indique le type défini pour un décompte de résultats lors d'une recherche de motifs. */ -GType g_match_counter_get_type(void); - -/* Met en place une représentation d'opération booléenne. */ -GMatchCounter *g_match_counter_new(GSearchPattern *); - - - -#endif /* _ANALYSIS_SCAN_CONDS_COUNTER_H */ diff --git a/src/analysis/scan/context.c b/src/analysis/scan/context.c index aec654a..c19b76c 100644 --- a/src/analysis/scan/context.c +++ b/src/analysis/scan/context.c @@ -499,7 +499,7 @@ bool g_scan_context_has_match_for_rule(GScanContext *context, const char *name) cond = NULL; - for (i = 0; context->cond_count; i++) + for (i = 0; i < context->cond_count; i++) if (strcmp(name, context->conditions[i].name) == 0) { cond = &context->conditions[i]; @@ -513,16 +513,14 @@ bool g_scan_context_has_match_for_rule(GScanContext *context, const char *name) if (!cond->final_reduced) { - new = g_scan_expression_reduce(cond->expr, context, false); + cond->final_reduced = g_scan_expression_reduce(cond->expr, context, NULL, &new); - if (new != NULL) + if (cond->final_reduced && new != NULL) { g_object_unref(G_OBJECT(cond->expr)); cond->expr = new; } - cond->final_reduced = true; - } /* Tentative de récupération d'un bilan final */ diff --git a/src/analysis/scan/core.c b/src/analysis/scan/core.c index 3b6c2c9..aef9abd 100644 --- a/src/analysis/scan/core.c +++ b/src/analysis/scan/core.c @@ -24,8 +24,8 @@ #include "core.h" -#include "funcs/datasize.h" -#include "funcs/uint.h" +#include "items/datasize.h" +#include "items/uint.h" @@ -47,20 +47,21 @@ bool populate_main_scan_namespace(GScanNamespace *space) result = true; -#define REGISTER_FUNC(s, f, n) \ +#define REGISTER_FUNC(s, f) \ ({ \ bool __result; \ - __result = g_scan_namespace_register(s, G_REGISTERED_ITEM(f), n); \ + __result = g_scan_namespace_register_item(s, G_REGISTERED_ITEM(f)); \ + g_object_unref(G_OBJECT(f)); \ __result; \ }) - if (result) result = REGISTER_FUNC(space, g_datasize_function_new(), "datasize"); - if (result) result = REGISTER_FUNC(space, g_datasize_function_new(), "filesize"); /* Alias */ + if (result) result = REGISTER_FUNC(space, g_datasize_function_new()); + //if (result) result = REGISTER_FUNC(space, g_datasize_function_new(), "filesize"); /* Alias */ - if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_8_BITS_UNSIGNED), "uint8"); - if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_16_BITS_UNSIGNED), "uint16"); - if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_32_BITS_UNSIGNED), "uint32"); - if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_64_BITS_UNSIGNED), "uint64"); + if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_8_BITS_UNSIGNED)); + if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_16_BITS_UNSIGNED)); + if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_32_BITS_UNSIGNED)); + if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_64_BITS_UNSIGNED)); return result; diff --git a/src/analysis/scan/expr-int.h b/src/analysis/scan/expr-int.h index 4323693..dbfea6e 100644 --- a/src/analysis/scan/expr-int.h +++ b/src/analysis/scan/expr-int.h @@ -44,8 +44,11 @@ typedef bool (* check_expr_validity_fc) (const GScanExpression *); /* Reproduit une expression en place dans une nouvelle instance. */ typedef GScanExpression * (* dup_expr_fc) (const GScanExpression *); +/* Reproduit une expression en place dans une nouvelle instance. */ +typedef void (* copy_expr_fc) (GScanExpression *, const GScanExpression *); + /* Réduit une expression à une forme plus simple. */ -typedef GScanExpression * (* reduce_expr_fc) (GScanExpression *, GScanContext *, bool); +typedef bool (* reduce_expr_fc) (GScanExpression *, GScanContext *, GScanScope *, GScanExpression **); /* Expression d'évaluation généraliste (instance) */ @@ -64,6 +67,7 @@ struct _GScanExpressionClass compare_expr_rich_fc cmp_rich; /* Comparaison de façon précise*/ check_expr_validity_fc check; /* Validation de la cohérence */ + copy_expr_fc copy; /* Reproduction d'expression */ dup_expr_fc dup; /* Reproduction d'expression */ reduce_expr_fc reduce; /* Simplification d'expression */ diff --git a/src/analysis/scan/expr.c b/src/analysis/scan/expr.c index 0b81e01..52d2c42 100644 --- a/src/analysis/scan/expr.c +++ b/src/analysis/scan/expr.c @@ -24,6 +24,9 @@ #include "expr.h" +#include <assert.h> + + #include "expr-int.h" @@ -46,6 +49,10 @@ static void g_scan_expression_dispose(GScanExpression *); /* Procède à la libération totale de la mémoire. */ static void g_scan_expression_finalize(GScanExpression *); +/* Reproduit une expression en place dans une nouvelle instance. */ +static void g_scan_expression_copy(GScanExpression *, const GScanExpression *); + + /* ----------------------- INTERFACE OFFRANT DES COMPARAISONS ----------------------- */ @@ -86,6 +93,8 @@ static void g_scan_expression_class_init(GScanExpressionClass *klass) object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_expression_dispose; object->finalize = (GObjectFinalizeFunc)g_scan_expression_finalize; + klass->copy = g_scan_expression_copy; + } @@ -241,6 +250,26 @@ bool g_scan_expression_check_validity(const GScanExpression *expr) /****************************************************************************** * * +* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] * +* src = expression source à copier. * +* * +* Description : Reproduit une expression en place dans une nouvelle instance.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_expression_copy(GScanExpression *dest, const GScanExpression *src) +{ + dest->value_type = src->value_type; + +} + + +/****************************************************************************** +* * * Paramètres : expr = expression à copier. * * * * Description : Reproduit une expression en place dans une nouvelle instance.* @@ -254,11 +283,16 @@ bool g_scan_expression_check_validity(const GScanExpression *expr) GScanExpression *g_scan_expression_duplicate(const GScanExpression *expr) { GScanExpression *result; /* Instance copiée à retourner */ + GType type; /* Type d'objet à copier */ GScanExpressionClass *class; /* Classe à activer */ + type = G_TYPE_FROM_INSTANCE(expr); + + result = g_object_new(type, NULL); + class = G_SCAN_EXPRESSION_GET_CLASS(expr); - result = class->dup(expr); + class->copy(result, expr); return result; @@ -269,24 +303,32 @@ GScanExpression *g_scan_expression_duplicate(const GScanExpression *expr) * * * Paramètres : expr = expression à consulter. * * ctx = contexte de suivi de l'analyse courante. * -* final = indique une ultime conversion dans le cycle en cours.* +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la réduction opérée. [OUT] * * * * Description : Réduit une expression à une forme plus simple. * * * -* Retour : Réduction correspondante, expression déjà réduite, ou NULL. * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * * Remarques : - * * * ******************************************************************************/ -GScanExpression *g_scan_expression_reduce(GScanExpression *expr, GScanContext *ctx, bool final) +bool g_scan_expression_reduce(GScanExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - GScanExpression *result; /* Instance à renvoyer */ + bool result; /* Bilan à retourner */ GScanExpressionClass *class; /* Classe à activer */ + *out = NULL; + class = G_SCAN_EXPRESSION_GET_CLASS(expr); - result = class->reduce(expr, ctx, final); + result = class->reduce(expr, ctx, scope, out); + +#ifndef NDEBUG + if (*out != NULL) + assert(result); +#endif return result; diff --git a/src/analysis/scan/expr.h b/src/analysis/scan/expr.h index 98e7f7d..d596222 100644 --- a/src/analysis/scan/expr.h +++ b/src/analysis/scan/expr.h @@ -30,6 +30,7 @@ #include "context.h" +#include "scope.h" @@ -77,7 +78,7 @@ bool g_scan_expression_check_validity(const GScanExpression *); GScanExpression *g_scan_expression_duplicate(const GScanExpression *); /* Réduit une expression à une forme plus simple. */ -GScanExpression *g_scan_expression_reduce(GScanExpression *, GScanContext *, bool); +bool g_scan_expression_reduce(GScanExpression *, GScanContext *, GScanScope *, GScanExpression **); diff --git a/src/analysis/scan/exprs/Makefile.am b/src/analysis/scan/exprs/Makefile.am index f164864..efe25fc 100644 --- a/src/analysis/scan/exprs/Makefile.am +++ b/src/analysis/scan/exprs/Makefile.am @@ -3,6 +3,8 @@ noinst_LTLIBRARIES = libanalysisscanexprs.la libanalysisscanexprs_la_SOURCES = \ + access-int.h \ + access.h access.c \ arithmop-int.h \ arithmop.h arithmop.c \ boolop-int.h \ @@ -13,8 +15,8 @@ libanalysisscanexprs_la_SOURCES = \ literal.h literal.c \ relop-int.h \ relop.h relop.c \ - str-int.h \ - str.h str.c + strop-int.h \ + strop.h strop.c libanalysisscanexprs_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) diff --git a/src/analysis/scan/exprs/access-int.h b/src/analysis/scan/exprs/access-int.h new file mode 100644 index 0000000..2212b48 --- /dev/null +++ b/src/analysis/scan/exprs/access-int.h @@ -0,0 +1,69 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * access-int.h - prototypes internes pour l'accès à un élément d'expression sous-jacent + * + * Copyright (C) 2023 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_EXPRS_ACCESS_INT_H +#define _ANALYSIS_SCAN_EXPRS_ACCESS_INT_H + + +#include "access.h" + + +#include "../expr-int.h" + + + +/* Accès à un élément d'expression sous-jacent (instance) */ +struct _GNamedAccess +{ + GScanExpression parent; /* A laisser en premier */ + + union + { + GRegisteredItem *base; /* Base de recherche */ + GRegisteredItem *resolved; /* Elément ciblé au final */ + GObject *any; /* Accès indistinct */ + }; + + char *target; /* Cible dans l'espace */ + + struct _GNamedAccess *next; /* Evnetuel prochain élément */ + +}; + +/* Accès à un élément d'expression sous-jacent (classe) */ +struct _GNamedAccessClass +{ + GScanExpressionClass parent; /* A laisser en premier */ + +}; + + +/* Met en place une expression d'accès. */ +bool g_named_access_create(GNamedAccess *, const sized_string_t *); + +/* Réduit une expression à une forme plus simple. */ +bool _g_named_access_reduce(GNamedAccess *, GScanContext *, GScanScope *, GScanExpression **); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_ACCESS_INT_H */ diff --git a/src/analysis/scan/exprs/access.c b/src/analysis/scan/exprs/access.c new file mode 100644 index 0000000..ad66f60 --- /dev/null +++ b/src/analysis/scan/exprs/access.c @@ -0,0 +1,471 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * access.c - accès à un élément d'expression sous-jacent + * + * Copyright (C) 2023 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "access.h" + + +#include <assert.h> +#include <malloc.h> +#include <string.h> + + +#include "access-int.h" +#include "../../../core/global.h" + + + +/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */ + + +/* Initialise la classe des appels de fonction avec arguments. */ +static void g_named_access_class_init(GNamedAccessClass *); + +/* Initialise une instance d'appel de fonction avec arguments. */ +static void g_named_access_init(GNamedAccess *); + +/* Supprime toutes les références externes. */ +static void g_named_access_dispose(GNamedAccess *); + +/* Procède à la libération totale de la mémoire. */ +static void g_named_access_finalize(GNamedAccess *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Reproduit une expression en place dans une nouvelle instance. */ +static void g_named_access_copy(GNamedAccess *, const GNamedAccess *); + +/* Réduit une expression à une forme plus simple. */ +static bool g_named_access_reduce(GNamedAccess *, GScanContext *, GScanScope *, GScanExpression **); + + + +/* ---------------------------------------------------------------------------------- */ +/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un appel de fonction enregistrée. */ +G_DEFINE_TYPE(GNamedAccess, g_named_access, G_TYPE_SCAN_EXPRESSION); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des appels de fonction avec arguments. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_named_access_class_init(GNamedAccessClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanExpressionClass *expr; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_named_access_dispose; + object->finalize = (GObjectFinalizeFunc)g_named_access_finalize; + + expr = G_SCAN_EXPRESSION_CLASS(klass); + + expr->cmp_rich = (compare_expr_rich_fc)NULL; + expr->copy = (copy_expr_fc)g_named_access_copy; + expr->reduce = (reduce_expr_fc)g_named_access_reduce; + +} + + +/****************************************************************************** +* * +* Paramètres : access = instance à initialiser. * +* * +* Description : Initialise une instance d'appel de fonction avec arguments. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_named_access_init(GNamedAccess *access) +{ + access->any = NULL; + access->target = NULL; + + access->next = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : access = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_named_access_dispose(GNamedAccess *access) +{ + g_clear_object(&access->any); + + g_clear_object(&access->next); + + G_OBJECT_CLASS(g_named_access_parent_class)->dispose(G_OBJECT(access)); + +} + + +/****************************************************************************** +* * +* Paramètres : access = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_named_access_finalize(GNamedAccess *access) +{ + if (access->target != NULL) + free(access->target); + + G_OBJECT_CLASS(g_named_access_parent_class)->finalize(G_OBJECT(access)); + +} + + +/****************************************************************************** +* * +* Paramètres : target = désignation de l'objet d'appel à identifier. * +* * +* Description : Organise un accès à un élément d'expression sous-jacent. * +* * +* Retour : Fonction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_named_access_new(const sized_string_t *target) +{ + GScanExpression *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_NAMED_ACCESS, NULL); + + if (!g_named_access_create(G_NAMED_ACCESS(result), target)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : access = instance à initialiser pleinement. * +* target = désignation de l'objet d'appel à identifier. * +* * +* Description : Met en place une expression d'accès. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_named_access_create(GNamedAccess *access, const sized_string_t *target) +{ + bool result; /* Bilan à retourner */ + + result = g_scan_expression_create(G_SCAN_EXPRESSION(access), EVT_PENDING); + if (!result) goto exit; + + access->target = strndup(target->data, target->len); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : access = expression d'appel à actualiser. * +* base = zone de recherche pour la résolution à venir. * +* * +* Description : Définit une base de recherche pour la cible d'accès. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_named_access_set_base(GNamedAccess *access, GRegisteredItem *base) +{ + g_clear_object(&access->base); + + access->base = base; + g_object_ref(G_OBJECT(base)); + +} + + +/****************************************************************************** +* * +* Paramètres : access = expression d'appel à compléter. * +* next = expression d'appel suivante dans la chaîne. * +* * +* Description : Complète la chaine d'accès à des expressions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_named_access_attach_next(GNamedAccess *access, GNamedAccess *next) +{ + if (access->next != NULL) + g_named_access_attach_next(access->next, next); + + else + { + access->next = next; + g_object_ref(G_OBJECT(next)); + } + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] * +* src = expression source à copier. * +* * +* Description : Reproduit une expression en place dans une nouvelle instance.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_named_access_copy(GNamedAccess *dest, const GNamedAccess *src) +{ + GScanExpressionClass *class; /* Classe parente à solliciter */ + + class = G_SCAN_EXPRESSION_CLASS(g_named_access_parent_class); + + class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src)); + + if (src->any != NULL) + { + dest->any = src->any; + g_object_ref(src->any); + } + + if (src->target != NULL) + dest->target = strdup(src->target); + + if (src->next != NULL) + dest->next = G_NAMED_ACCESS(g_scan_expression_duplicate(G_SCAN_EXPRESSION(src->next))); + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression à consulter. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la réduction opérée. [OUT] * +* * +* Description : Réduit une expression à une forme plus simple. * +* * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool _g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +{ + bool result; /* Bilan à retourner */ + GRegisteredItem *base; /* Base de recherche courante */ + GRegisteredItem *resolved; /* Cible concrète obtenue */ + GNamedAccess *new; /* Copie mise en place */ + + result = true; + + if (expr->target != NULL) + { + if (expr->base != NULL) + { + base = expr->base; + g_object_ref(G_OBJECT(base)); + } + else + base = G_REGISTERED_ITEM(get_rost_root_namespace()); + + result = g_registered_item_resolve(base, expr->target, ctx, scope, &resolved); + + g_object_unref(G_OBJECT(base)); + + if (result && resolved != NULL) + { + new = G_NAMED_ACCESS(g_scan_expression_duplicate(G_SCAN_EXPRESSION(expr))); + + g_clear_object(&new->base); + + free(new->target); + new->target = NULL; + + new->resolved = resolved; + + *out = G_SCAN_EXPRESSION(new); + + } + + } + + /** + * Si plus aucune indication n'est diponible pour avancer dans les réductions, + * c'est que l'opération est déjà conclue. + */ + else + { + assert(expr->resolved != NULL); + + *out = G_SCAN_EXPRESSION(expr); + g_object_ref(G_OBJECT(*out)); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression à consulter. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la réduction opérée. [OUT] * +* * +* Description : Réduit une expression à une forme plus simple. * +* * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +{ + bool result; /* Bilan à retourner */ + GNamedAccess *new; /* Eventuel étage suivant */ + GScanExpression *final; /* Expression d'évaluation */ + GScanExpression *new_next; /* Nouvelle version du suivant */ + + result = _g_named_access_reduce(expr, ctx, scope, out); + + if (result && *out != NULL) + { + assert(G_IS_NAMED_ACCESS(*out)); + + new = G_NAMED_ACCESS(*out); + *out = NULL; + + assert(new->target == NULL); + assert(G_IS_NAMED_ACCESS(new)); + assert(G_IS_REGISTERED_ITEM(new->resolved)); + + /** + * Si l'élément résolu se trouve en fin de chaîne, alors cet élément + * est sollicité pour obtenir une expression d'évaluation classique. + * Le produit de cette réduction finale bénéficie d'une promotion et + * représente à lui seul la réduction produite pour la chaîne. + */ + if (new->next == NULL) + { + result = g_registered_item_reduce(new->resolved, ctx, scope, &final); + + if (result && final != NULL) + { + g_clear_object(out); + *out = final; + } + + } + + /** + * Sinon, l'élément résolu constitue une base pour l'étage suivant de + * la chaîne de résolution. + */ + else + { + new_next = g_scan_expression_duplicate(G_SCAN_EXPRESSION(new->next)); + assert(G_IS_NAMED_ACCESS(new_next)); + + g_named_access_set_base(G_NAMED_ACCESS(new_next), new->resolved); + + g_clear_object(out); + + result = g_scan_expression_reduce(new_next, ctx, scope, out); + + if (result && *out == NULL) + *out = new_next; + + } + + g_object_unref(G_OBJECT(new)); + + } + + return result; + +} diff --git a/src/analysis/scan/exprs/access.h b/src/analysis/scan/exprs/access.h new file mode 100644 index 0000000..a04adc7 --- /dev/null +++ b/src/analysis/scan/exprs/access.h @@ -0,0 +1,63 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * access.h - prototypes pour l'accès à un élément d'expression sous-jacent + * + * Copyright (C) 2023 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_EXPRS_ACCESS_H +#define _ANALYSIS_SCAN_EXPRS_ACCESS_H + + +#include "../expr.h" +#include "../item.h" +#include "../../../common/szstr.h" + + + +#define G_TYPE_NAMED_ACCESS g_named_access_get_type() +#define G_NAMED_ACCESS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_NAMED_ACCESS, GNamedAccess)) +#define G_IS_NAMED_ACCESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_NAMED_ACCESS)) +#define G_NAMED_ACCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_NAMED_ACCESS, GNamedAccessClass)) +#define G_IS_NAMED_ACCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_NAMED_ACCESS)) +#define G_NAMED_ACCESS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_NAMED_ACCESS, GNamedAccessClass)) + + +/* Accès à un élément d'expression sous-jacent (instance) */ +typedef struct _GNamedAccess GNamedAccess; + +/* Accès à un élément d'expression sous-jacent (classe) */ +typedef struct _GNamedAccessClass GNamedAccessClass; + + +/* Indique le type défini pour un appel de fonction enregistrée. */ +GType g_named_access_get_type(void); + +/* Organise un accès à un élément d'expression sous-jacent. */ +GScanExpression *g_named_access_new(const sized_string_t *); + +/* Définit une base de recherche pour la cible d'accès. */ +void g_named_access_set_base(GNamedAccess *, GRegisteredItem *); + +/* Complète la chaine d'accès à des expressions. */ +void g_named_access_attach_next(GNamedAccess *, GNamedAccess *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_ACCESS_H */ diff --git a/src/analysis/scan/exprs/arithmop-int.h b/src/analysis/scan/exprs/arithmop-int.h index 75f1dbb..031de84 100644 --- a/src/analysis/scan/exprs/arithmop-int.h +++ b/src/analysis/scan/exprs/arithmop-int.h @@ -39,8 +39,8 @@ struct _GArithmOperation ArithmeticExpressionOperator operator; /* Type d'opération menée */ - GScanExpression *first; /* Expression impactée #1 */ - GScanExpression *second; /* Expression impactée #2 */ + GScanExpression *left; /* Expression impactée #1 */ + GScanExpression *right; /* Expression impactée #2 */ }; diff --git a/src/analysis/scan/exprs/arithmop.c b/src/analysis/scan/exprs/arithmop.c index f57e260..5f9e3f1 100644 --- a/src/analysis/scan/exprs/arithmop.c +++ b/src/analysis/scan/exprs/arithmop.c @@ -52,11 +52,11 @@ static void g_arithmetic_operation_finalize(GArithmOperation *); /* Réalise une comparaison entre objets selon un critère précis. */ static bool g_arithmetic_operation_compare_rich(const GArithmOperation *, const GArithmOperation *, RichCmpOperation, bool *); -/* Initialise une instance d'opération de relation. */ -static GScanExpression *g_arithmetic_operation_duplicate(const GArithmOperation *); +/* Reproduit une expression en place dans une nouvelle instance. */ +static void g_arithmetic_operation_copy(GArithmOperation *, const GArithmOperation *); /* Réduit une expression à une forme plus simple. */ -GScanExpression *g_arithmetic_operation_reduce(GArithmOperation *, GScanContext *, bool); +static bool g_arithmetic_operation_reduce(GArithmOperation *, GScanContext *, GScanScope *, GScanExpression **); @@ -94,7 +94,7 @@ static void g_arithmetic_operation_class_init(GArithmOperationClass *klass) expr = G_SCAN_EXPRESSION_CLASS(klass); expr->cmp_rich = (compare_expr_rich_fc)g_arithmetic_operation_compare_rich; - expr->dup = (dup_expr_fc)g_arithmetic_operation_duplicate; + expr->copy = (copy_expr_fc)g_arithmetic_operation_copy; expr->reduce = (reduce_expr_fc)g_arithmetic_operation_reduce; } @@ -114,8 +114,8 @@ static void g_arithmetic_operation_class_init(GArithmOperationClass *klass) static void g_arithmetic_operation_init(GArithmOperation *op) { - op->first = NULL; - op->second = NULL; + op->left = NULL; + op->right = NULL; } @@ -134,8 +134,8 @@ static void g_arithmetic_operation_init(GArithmOperation *op) static void g_arithmetic_operation_dispose(GArithmOperation *op) { - g_clear_object(&op->first); - g_clear_object(&op->second); + g_clear_object(&op->left); + g_clear_object(&op->right); G_OBJECT_CLASS(g_arithmetic_operation_parent_class)->dispose(G_OBJECT(op)); @@ -164,8 +164,8 @@ static void g_arithmetic_operation_finalize(GArithmOperation *op) /****************************************************************************** * * * Paramètres : operator = type d'opération arithmétique à représenter. * -* first = premier opérande concerné. * -* second = éventuel second opérande impliqué ou NULL. * +* left = premier opérande concerné. * +* right = éventuel second opérande impliqué ou NULL. * * * * Description : Organise une opération arithmétique entre expressions. * * * @@ -175,13 +175,13 @@ static void g_arithmetic_operation_finalize(GArithmOperation *op) * * ******************************************************************************/ -GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operator, GScanExpression *first, GScanExpression *second) +GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right) { GScanExpression *result; /* Structure à retourner */ result = g_object_new(G_TYPE_ARITHMETIC_OPERATION, NULL); - if (!g_arithmetic_operation_create(G_ARITHMETIC_OPERATION(result), operator, first, second)) + if (!g_arithmetic_operation_create(G_ARITHMETIC_OPERATION(result), operator, left, right)) g_clear_object(&result); return result; @@ -193,8 +193,8 @@ GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operato * * * Paramètres : op = instance à initialiser pleinement. * * operator = type d'opération booléenne à représenter. * -* first = premier opérande concerné. * -* second = éventuel second opérande impliqué ou NULL. * +* left = premier opérande concerné. * +* right = éventuel second opérande impliqué ou NULL. * * * * Description : Met en place une opération arithmétique entre expressions. * * * @@ -204,19 +204,19 @@ GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operato * * ******************************************************************************/ -bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOperator operator, GScanExpression *first, GScanExpression *second) +bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right) { bool result; /* Bilan à retourner */ ExprValueType vtype; /* Type de valeur portée */ result = false; - vtype = g_scan_expression_get_value_type(first); + vtype = g_scan_expression_get_value_type(left); if (vtype != EVT_INTEGER && vtype != EVT_PENDING) goto exit; - vtype = g_scan_expression_get_value_type(second); + vtype = g_scan_expression_get_value_type(right); if (vtype != EVT_INTEGER && vtype != EVT_PENDING) goto exit; @@ -226,11 +226,11 @@ bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOpe op->operator = operator; - op->first = first; - g_object_ref(G_OBJECT(op->first)); + op->left = left; + g_object_ref(G_OBJECT(op->left)); - op->second = second; - g_object_ref(G_OBJECT(op->second)); + op->right = right; + g_object_ref(G_OBJECT(op->right)); result = true; @@ -265,9 +265,9 @@ bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOpe static bool g_arithmetic_operation_compare_rich(const GArithmOperation *item, const GArithmOperation *other, RichCmpOperation op, bool *status) { bool result; /* Etat à retourner */ - bool equal; /* Bilan intermédiaire */ - result = true; // TODO : cmp parent()->type + result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_ARITHMETIC_OPERATION); + if (!result) goto done; if (item->operator != other->operator) { @@ -275,18 +275,16 @@ static bool g_arithmetic_operation_compare_rich(const GArithmOperation *item, co goto done; } - equal = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status); + result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status); + if (!result || STATUS_NOT_EQUAL(*status, op)) goto done; - if (!equal) - { - result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first), - G_COMPARABLE_ITEM(other->first), - op, status); - goto done; - } + result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->left), + G_COMPARABLE_ITEM(other->left), + op, status); + if (!result || STATUS_NOT_EQUAL(*status, op)) goto done; - result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second), - G_COMPARABLE_ITEM(other->second), + result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->right), + G_COMPARABLE_ITEM(other->right), op, status); done: @@ -298,23 +296,29 @@ static bool g_arithmetic_operation_compare_rich(const GArithmOperation *item, co /****************************************************************************** * * -* Paramètres : expr = expression à copier. * +* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] * +* src = expression source à copier. * * * * Description : Reproduit une expression en place dans une nouvelle instance.* * * -* Retour : Nouvelle instance d'expression. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static GScanExpression *g_arithmetic_operation_duplicate(const GArithmOperation *expr) +static void g_arithmetic_operation_copy(GArithmOperation *dest, const GArithmOperation *src) { - GScanExpression *result; /* Instance copiée à retourner */ + GScanExpressionClass *class; /* Classe parente à solliciter */ - result = g_arithmetic_operation_new(expr->operator, expr->first, expr->second); + class = G_SCAN_EXPRESSION_CLASS(g_arithmetic_operation_parent_class); - return result; + class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src)); + + dest->operator = src->operator; + + dest->left = g_scan_expression_duplicate(src->left); + dest->right = g_scan_expression_duplicate(src->right); } @@ -323,92 +327,110 @@ static GScanExpression *g_arithmetic_operation_duplicate(const GArithmOperation * * * Paramètres : expr = expression à consulter. * * ctx = contexte de suivi de l'analyse courante. * -* final = impose une conversion finale de dernier tour. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la réduction opérée. [OUT] * * * * Description : Réduit une expression à une forme plus simple. * * * -* Retour : Réduction correspondante, expression déjà réduite, ou NULL. * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * * Remarques : - * * * ******************************************************************************/ -GScanExpression *g_arithmetic_operation_reduce(GArithmOperation *expr, GScanContext *ctx, bool final) +static bool g_arithmetic_operation_reduce(GArithmOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - GScanExpression *result; /* Instance à renvoyer */ - GScanExpression *new; /* Nouvelle expression obtenue */ + bool result; /* Bilan à retourner */ + GScanExpression *new_left; /* Expression réduite (gauche) */ + GScanExpression *new_right; /* Expression réduite (droite) */ + GLiteralExpression *op_left; /* Opérande gauche final */ + GLiteralExpression *op_right; /* Opérande droite final */ unsigned long long val_1; /* Première valeur à traiter */ - unsigned long long val_2; /* Second valeur à traiter */ - bool valid; /* Validité de ce bilan obtenu */ + unsigned long long val_2; /* Seconde valeur à traiter */ unsigned long long reduced; /* Valeur réduite finale */ - result = NULL; - /* Réduction des éléments considérés */ - new = g_scan_expression_reduce(expr->first, ctx, final); - - if (new != NULL) - { - g_object_unref(G_OBJECT(expr->first)); - expr->first = new; - } + new_left = NULL; + new_right = NULL; - if (expr->second != NULL) - { - new = g_scan_expression_reduce(expr->second, ctx, final); + result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left); + if (!result) goto exit; - if (new != NULL) - { - g_object_unref(G_OBJECT(expr->second)); - expr->second = new; - } - - } + result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right); + if (!result) goto exit; /* Construction d'une réduction locale ? */ - if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second)) + if (G_IS_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right)) { - valid = g_literal_expression_get_integer_value(G_LITERAL_EXPRESSION(expr->first), &val_1); + op_left = G_LITERAL_EXPRESSION(new_left); + op_right = G_LITERAL_EXPRESSION(new_right); - if (valid) - valid = g_literal_expression_get_integer_value(G_LITERAL_EXPRESSION(expr->second), &val_2); + result = g_literal_expression_get_integer_value(op_left, &val_1); + if (!result) goto exit; - if (valid) - switch (expr->operator) - { - case AEO_PLUS: - reduced = val_1 + val_2; - break; + result = g_literal_expression_get_integer_value(op_right, &val_2); + if (!result) goto exit; - case AEO_MINUS: - reduced = val_1 - val_2; - break; + switch (expr->operator) + { + case AEO_PLUS: + reduced = val_1 + val_2; + break; + + case AEO_MINUS: + reduced = val_1 - val_2; + break; + + case AEO_MUL: + reduced = val_1 * val_2; + break; + + case AEO_DIV: + result = (val_2 != 0); + if (result) + reduced = val_1 / val_2; + break; + + case AEO_MOD: + result = (val_2 != 0); + if (result) + reduced = val_1 % val_2; + break; - case AEO_MUL: - reduced = val_1 * val_2; - break; + } - case AEO_DIV: - valid = (val_2 != 0); - if (valid) - reduced = val_1 / val_2; - break; + if (result) + *out = g_literal_expression_new(EVT_INTEGER, &reduced); - case AEO_MOD: - valid = (val_2 != 0); - if (valid) - reduced = val_1 % val_2; - break; + } - } + /* Mise à jour de la progression ? */ - if (valid) - result = g_literal_expression_new(EVT_INTEGER, &reduced); + else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right)) + { + if (new_left == NULL) + { + new_left = expr->left; + g_object_ref(G_OBJECT(new_left)); + } + + if (new_right == NULL) + { + new_right = expr->right; + g_object_ref(G_OBJECT(new_right)); + } + + *out = g_arithmetic_operation_new(expr->operator, new_left, new_right); } + exit: + + g_clear_object(&new_left); + g_clear_object(&new_right); + return result; } diff --git a/src/analysis/scan/exprs/boolop.c b/src/analysis/scan/exprs/boolop.c index 2902fdd..f6a80dd 100644 --- a/src/analysis/scan/exprs/boolop.c +++ b/src/analysis/scan/exprs/boolop.c @@ -56,10 +56,10 @@ static void g_boolean_operation_finalize(GBoolOperation *); static bool g_boolean_operation_compare_rich(const GBoolOperation *, const GBoolOperation *, RichCmpOperation, bool *); /* Reproduit une expression en place dans une nouvelle instance. */ -static GScanExpression *g_boolean_operation_duplicate(const GBoolOperation *); +static void g_boolean_operation_copy(GBoolOperation *, const GBoolOperation *); /* Réduit une expression à une forme plus simple. */ -GScanExpression *g_boolean_operation_reduce(GBoolOperation *, GScanContext *, bool); +static bool g_boolean_operation_reduce(GBoolOperation *, GScanContext *, GScanScope *, GScanExpression **); @@ -97,7 +97,7 @@ static void g_boolean_operation_class_init(GBoolOperationClass *klass) expr = G_SCAN_EXPRESSION_CLASS(klass); expr->cmp_rich = (compare_expr_rich_fc)g_boolean_operation_compare_rich; - expr->dup = (dup_expr_fc)g_boolean_operation_duplicate; + expr->copy = (copy_expr_fc)g_boolean_operation_copy; expr->reduce = (reduce_expr_fc)g_boolean_operation_reduce; } @@ -278,9 +278,9 @@ bool g_boolean_operation_create(GBoolOperation *op, BooleanOperationType type, G static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const GBoolOperation *other, RichCmpOperation op, bool *status) { bool result; /* Etat à retourner */ - bool equal; /* Bilan intermédiaire */ - result = true; + result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_BOOLEAN_OPERATION); + if (!result) goto done; if (item->type != other->type) { @@ -288,15 +288,13 @@ static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const G goto done; } - equal = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status); + result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status); + if (!result || STATUS_NOT_EQUAL(*status, op)) goto done; - if (!equal) - { - *status = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first), - G_COMPARABLE_ITEM(other->first), - op, status); - goto done; - } + result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first), + G_COMPARABLE_ITEM(other->first), + op, status); + if (!result || STATUS_NOT_EQUAL(*status, op)) goto done; if (item->second == NULL) { @@ -321,9 +319,9 @@ static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const G } else - *status = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second), - G_COMPARABLE_ITEM(other->second), - op, status); + result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second), + G_COMPARABLE_ITEM(other->second), + op, status); done: @@ -334,23 +332,31 @@ static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const G /****************************************************************************** * * -* Paramètres : expr = expression à copier. * +* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] * +* src = expression source à copier. * * * * Description : Reproduit une expression en place dans une nouvelle instance.* * * -* Retour : Nouvelle instance d'expression. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static GScanExpression *g_boolean_operation_duplicate(const GBoolOperation *expr) +static void g_boolean_operation_copy(GBoolOperation *dest, const GBoolOperation *src) { - GScanExpression *result; /* Instance copiée à retourner */ + GScanExpressionClass *class; /* Classe parente à solliciter */ - result = g_boolean_operation_new(expr->type, expr->first, expr->second); + class = G_SCAN_EXPRESSION_CLASS(g_boolean_operation_parent_class); - return result; + class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src)); + + dest->type = src->type; + + dest->first = g_scan_expression_duplicate(src->first); + + if (src->second != NULL) + dest->second = g_scan_expression_duplicate(src->second); } @@ -359,92 +365,115 @@ static GScanExpression *g_boolean_operation_duplicate(const GBoolOperation *expr * * * Paramètres : expr = expression à consulter. * * ctx = contexte de suivi de l'analyse courante. * -* final = impose une conversion finale de dernier tour. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la réduction opérée. [OUT] * * * * Description : Réduit une expression à une forme plus simple. * * * -* Retour : Réduction correspondante, expression déjà réduite, ou NULL. * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * * Remarques : - * * * ******************************************************************************/ -GScanExpression *g_boolean_operation_reduce(GBoolOperation *expr, GScanContext *ctx, bool final) +static bool g_boolean_operation_reduce(GBoolOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - GScanExpression *result; /* Instance à renvoyer */ - GScanExpression *new; /* Nouvelle expression obtenue */ + bool result; /* Bilan à retourner */ + GScanExpression *new_first; /* Expression réduite (gauche) */ + GScanExpression *new_second; /* Expression réduite (droite) */ bool values[2]; /* Valeurs des éléments portés */ bool valid[2]; /* Validité de ces valeurs */ - result = NULL; - /* Réduction des éléments considérés */ - new = g_scan_expression_reduce(expr->first, ctx, final); + new_first = NULL; + new_second = NULL; + + result = g_scan_expression_reduce(expr->first, ctx, scope, &new_first); + if (!result) goto exit; - if (new != NULL) + if (expr->second == NULL) + new_second = NULL; + else { - g_object_unref(G_OBJECT(expr->first)); - expr->first = new; + result = g_scan_expression_reduce(expr->second, ctx, scope, &new_second); + if (!result) goto exit; } - if (expr->second != NULL) - { - new = g_scan_expression_reduce(expr->second, ctx, final); + /* Construction d'une réduction locale ? */ - if (new != NULL) - { - g_object_unref(G_OBJECT(expr->second)); - expr->second = new; - } + valid[0] = G_IS_LITERAL_EXPRESSION(new_first); - } + if (valid[0]) + valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(new_first), &values[0]); - /* Construction d'une réduction locale ? */ + valid[1] = G_IS_LITERAL_EXPRESSION(new_second); + + if (valid[1]) + valid[1] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(new_second), &values[1]); switch (expr->type) { case BOT_AND: - if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second)) - { - valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->first), &values[0]); - valid[1] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->second), &values[1]); + if (valid[0] && valid[1]) + *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] && values[1] }); - if (valid[0] && valid[1]) - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] && values[1] }); + else if (valid[0] && !values[0]) + *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false }); - else - /* Etre malin si 0 && x => bilan (si ctx->quick) */ - ; + else if (valid[1] && !values[1]) + *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false }); - } break; case BOT_OR: - if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second)) - { - valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->first), &values[0]); - valid[1] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->second), &values[1]); + if (valid[0] && valid[1]) + *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] || values[1] }); - if (valid[0] && valid[1]) - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] || values[1] }); + else if (valid[0] && values[0]) + *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { true }); + + else if (valid[1] && values[1]) + *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { true }); - } break; case BOT_NOT: - if (G_IS_LITERAL_EXPRESSION(expr->first)) - { - valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->first), &values[0]); + if (valid[0]) + *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { !values[0] }); + break; - if (valid[0]) - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { !values[1] }); + } + + /* Mise à jour de la progression ? */ + + if (*out == NULL) + { + if ((new_first != NULL && new_first != expr->first) || (new_second != NULL && new_second != expr->second)) + { + if (new_first == NULL) + { + new_first = expr->first; + g_object_ref(G_OBJECT(new_first)); + } + if (new_second == NULL) + { + new_second = expr->second; + g_object_ref(G_OBJECT(new_second)); } - break; + + *out = g_boolean_operation_new(expr->type, new_first, new_second); + + } } + exit: + + g_clear_object(&new_first); + g_clear_object(&new_second); + return result; } diff --git a/src/analysis/scan/exprs/call-int.h b/src/analysis/scan/exprs/call-int.h index d68977f..631a25b 100644 --- a/src/analysis/scan/exprs/call-int.h +++ b/src/analysis/scan/exprs/call-int.h @@ -28,35 +28,30 @@ #include "call.h" -#include "../expr-int.h" +#include "access-int.h" /* Exécution d'une fonction auxiliaire d'analyse (instance) */ struct _GPendingCall { - GScanExpression parent; /* A laisser en premier */ - - GRegisteredItem *base; /* Base de recherche */ - char *target; /* Cible dans l'espace */ + GNamedAccess parent; /* A laisser en premier */ GScanExpression **args; /* Arguments d'appel fournis */ size_t count; /* Quantité de ces arguments */ - struct _GPendingCall *next; /* Evnetuel prochain élément */ - }; /* Exécution d'une fonction auxiliaire d'analyse (classe) */ struct _GPendingCallClass { - GScanExpressionClass parent; /* A laisser en premier */ + GNamedAccessClass parent; /* A laisser en premier */ }; /* Met en place une expression d'appel. */ -bool g_pending_call_create(GPendingCall *, const char *, size_t, GScanExpression **, size_t); +bool g_pending_call_create(GPendingCall *, const sized_string_t *, GScanExpression **, size_t); diff --git a/src/analysis/scan/exprs/call.c b/src/analysis/scan/exprs/call.c index 76f5fc3..dde627c 100644 --- a/src/analysis/scan/exprs/call.c +++ b/src/analysis/scan/exprs/call.c @@ -24,6 +24,7 @@ #include "call.h" +#include <assert.h> #include <malloc.h> #include <string.h> @@ -48,19 +49,16 @@ static void g_pending_call_dispose(GPendingCall *); /* Procède à la libération totale de la mémoire. */ static void g_pending_call_finalize(GPendingCall *); -/* Définit une base de recherche pour la cible d'appel. */ -static void g_pending_call_set_base(GPendingCall *, GRegisteredItem *); - /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ /* Reproduit une expression en place dans une nouvelle instance. */ -static GScanExpression *g_pending_call_duplicate(const GPendingCall *); +static void g_pending_call_copy(GPendingCall *, const GPendingCall *); /* Réduit une expression à une forme plus simple. */ -GScanExpression *g_pending_call_reduce(GPendingCall *, GScanContext *, bool); +static bool g_pending_call_reduce(GPendingCall *, GScanContext *, GScanScope *, GScanExpression **); @@ -70,7 +68,7 @@ GScanExpression *g_pending_call_reduce(GPendingCall *, GScanContext *, bool); /* Indique le type défini pour un appel de fonction enregistrée. */ -G_DEFINE_TYPE(GPendingCall, g_pending_call, G_TYPE_SCAN_EXPRESSION); +G_DEFINE_TYPE(GPendingCall, g_pending_call, G_TYPE_NAMED_ACCESS); /****************************************************************************** @@ -98,7 +96,7 @@ static void g_pending_call_class_init(GPendingCallClass *klass) expr = G_SCAN_EXPRESSION_CLASS(klass); expr->cmp_rich = (compare_expr_rich_fc)NULL; - expr->dup = (dup_expr_fc)g_pending_call_duplicate; + expr->copy = (copy_expr_fc)g_pending_call_copy; expr->reduce = (reduce_expr_fc)g_pending_call_reduce; } @@ -118,14 +116,9 @@ static void g_pending_call_class_init(GPendingCallClass *klass) static void g_pending_call_init(GPendingCall *call) { - call->base = NULL; - call->target = NULL; - call->args = NULL; call->count = 0; - call->next = NULL; - } @@ -145,13 +138,9 @@ static void g_pending_call_dispose(GPendingCall *call) { size_t i; /* Boucle de parcours */ - g_clear_object(&call->base); - for (i = 0; i < call->count; i++) g_clear_object(&call->args[i]); - g_clear_object(&call->next); - G_OBJECT_CLASS(g_pending_call_parent_class)->dispose(G_OBJECT(call)); } @@ -171,9 +160,6 @@ static void g_pending_call_dispose(GPendingCall *call) static void g_pending_call_finalize(GPendingCall *call) { - if (call->target != NULL) - free(call->target); - if (call->args != NULL) free(call->args); @@ -185,7 +171,6 @@ static void g_pending_call_finalize(GPendingCall *call) /****************************************************************************** * * * Paramètres : target = désignation de l'objet d'appel à identifier. * -* len = taille de cette désignation. * * args = éventuelle liste d'arguments à actionner. * * count = quantité de ces arguments. * * * @@ -197,13 +182,13 @@ static void g_pending_call_finalize(GPendingCall *call) * * ******************************************************************************/ -GScanExpression *g_pending_call_new(const char *target, size_t len, GScanExpression **args, size_t count) +GScanExpression *g_pending_call_new(const sized_string_t *target, GScanExpression **args, size_t count) { GScanExpression *result; /* Structure à retourner */ result = g_object_new(G_TYPE_PENDING_CALL, NULL); - if (!g_pending_call_create(G_PENDING_CALL(result), target, len, args, count)) + if (!g_pending_call_create(G_PENDING_CALL(result), target, args, count)) g_clear_object(&result); return result; @@ -215,7 +200,6 @@ GScanExpression *g_pending_call_new(const char *target, size_t len, GScanExpress * * * Paramètres : call = instance à initialiser pleinement. * * target = désignation de l'objet d'appel à identifier. * -* len = taille de cette désignation. * * args = éventuelle liste d'arguments à actionner. * * count = quantité de ces arguments. * * * @@ -227,16 +211,14 @@ GScanExpression *g_pending_call_new(const char *target, size_t len, GScanExpress * * ******************************************************************************/ -bool g_pending_call_create(GPendingCall *call, const char *target, size_t len, GScanExpression **args, size_t count) +bool g_pending_call_create(GPendingCall *call, const sized_string_t *target, GScanExpression **args, size_t count) { bool result; /* Bilan à retourner */ size_t i; /* Boucle de parcours */ - result = g_scan_expression_create(G_SCAN_EXPRESSION(call), EVT_PENDING); + result = g_named_access_create(G_NAMED_ACCESS(call), target); if (!result) goto exit; - call->target = strndup(target, len); - call->args = malloc(count * sizeof(GScanExpression *)); call->count = count; @@ -253,48 +235,6 @@ bool g_pending_call_create(GPendingCall *call, const char *target, size_t len, G } -/****************************************************************************** -* * -* Paramètres : call = expression d'appel à actualiser. * -* base = zone de recherche pour la résolution à venir. * -* * -* Description : Définit une base de recherche pour la cible d'appel. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_pending_call_set_base(GPendingCall *call, GRegisteredItem *base) -{ - call->base = base; - g_object_ref(G_OBJECT(base)); - -} - - -/****************************************************************************** -* * -* Paramètres : call = expression d'appel à compléter. * -* next = expression d'appel suivante dans la chaîne. * -* * -* Description : Complète la chaine d'expressions d'appel. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_pending_call_attach_next(GPendingCall *call, GPendingCall *next) -{ - call->next = next; - g_object_ref(G_OBJECT(next)); - -} - - /* ---------------------------------------------------------------------------------- */ /* IMPLEMENTATION DES FONCTIONS DE CLASSE */ @@ -303,23 +243,31 @@ void g_pending_call_attach_next(GPendingCall *call, GPendingCall *next) /****************************************************************************** * * -* Paramètres : expr = expression à copier. * +* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] * +* src = expression source à copier. * * * * Description : Reproduit une expression en place dans une nouvelle instance.* * * -* Retour : Nouvelle instance d'expression. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static GScanExpression *g_pending_call_duplicate(const GPendingCall *expr) +static void g_pending_call_copy(GPendingCall *dest, const GPendingCall *src) { - GScanExpression *result; /* Instance copiée à retourner */ + GScanExpressionClass *class; /* Classe parente à solliciter */ + size_t i; /* Boucle de parcours */ - result = g_pending_call_new(expr->target, strlen(expr->target), expr->args, expr->count); + class = G_SCAN_EXPRESSION_CLASS(g_pending_call_parent_class); - return result; + class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src)); + + dest->args = malloc(src->count * sizeof(GScanExpression *)); + dest->count = src->count; + + for (i = 0; i < src->count; i++) + dest->args[i] = g_scan_expression_duplicate(src->args[i]); } @@ -328,99 +276,100 @@ static GScanExpression *g_pending_call_duplicate(const GPendingCall *expr) * * * Paramètres : expr = expression à consulter. * * ctx = contexte de suivi de l'analyse courante. * -* final = indique une ultime conversion dans le cycle en cours.* +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la réduction opérée. [OUT] * * * * Description : Réduit une expression à une forme plus simple. * * * -* Retour : Réduction correspondante, expression déjà réduite, ou NULL. * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * * Remarques : - * * * ******************************************************************************/ -GScanExpression *g_pending_call_reduce(GPendingCall *expr, GScanContext *ctx, bool final) +static bool g_pending_call_reduce(GPendingCall *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - GScanExpression *result; /* Instance à renvoyer */ + bool result; /* Bilan à retourner */ + GNamedAccess *new; /* Eventuel étage suivant */ + GPendingCall *new_call; /* Version en appel */ size_t i; /* Boucle de parcours */ - GScanExpression *new; /* Nouvelle expression obtenue */ - bool last; /* Détection de fin de chaîne */ - GRegisteredItem *base; /* Base de recherche courante */ - GRegisteredItem *rebase; /* Nouvelle base résolue */ + GScanExpression *arg; /* Argument réduit à échanger */ + GObject *final; /* Expression ou élément ? */ GScanExpression *new_next; /* Nouvelle version du suivant */ - for (i = 0; i < expr->count; i++) + result = _g_named_access_reduce(G_NAMED_ACCESS(expr), ctx, scope, out); + + if (result && *out != NULL) { - new = g_scan_expression_reduce(expr->args[i], ctx, final); + assert(G_IS_NAMED_ACCESS(*out)); - if (new != NULL) - { - g_object_unref(G_OBJECT(expr->args[i])); - expr->args[i] = new; - } + new = G_NAMED_ACCESS(*out); + *out = NULL; - } + assert(new->target == NULL); + assert(G_IS_PENDING_CALL(new)); + assert(G_IS_REGISTERED_ITEM(new->resolved)); - last = (expr->next == NULL); + new_call = G_PENDING_CALL(new); - if (!last) - new_next = g_scan_expression_duplicate(G_SCAN_EXPRESSION(expr->next)); - else - new_next = NULL; - - if (expr->target != NULL) - { - if (expr->base != NULL) + for (i = 0; i < new_call->count; i++) { - base = expr->base; - g_object_ref(G_OBJECT(base)); - } - else - base = G_REGISTERED_ITEM(get_rost_root_namespace()); + result = g_scan_expression_reduce(new_call->args[i], ctx, scope, &arg); + if (!result) goto exit; - rebase = g_registered_item_resolve(base, expr->target, ctx, - last ? NULL : expr->args, last ? 0 : expr->count, - last, final); + if (arg != NULL) + { + g_object_unref(G_OBJECT(new_call->args[i])); + new_call->args[i] = arg; + } - g_object_unref(G_OBJECT(base)); - if (rebase == NULL) - { - result = NULL; - goto done; } - if (last) - { - g_pending_call_set_base(expr, rebase); + result = g_registered_item_run_call(new->resolved, + new_call->args, + new_call->count, + ctx, scope, &final); - free(expr->target); - expr->target = NULL; + if (result && final != NULL) + { + /** + * Si le produit de l'appel à la fonction est une expression d'évaluation + * classique, alors ce produit constitue la réduction finale de la chaîne. + * + * Ce cas de figure ne se rencontre normalement qu'en bout de chaîne. + */ + if (!G_IS_REGISTERED_ITEM(final)) + { + assert(new->next == NULL); + *out = G_SCAN_EXPRESSION(final); + } + else + { + assert(new->next != NULL); + + new_next = g_scan_expression_duplicate(G_SCAN_EXPRESSION(new->next)); + assert(G_IS_NAMED_ACCESS(new_next)); + + g_named_access_set_base(G_NAMED_ACCESS(new_next), G_REGISTERED_ITEM(final)); + + result = g_scan_expression_reduce(new_next, ctx, scope, out); + + if (result && *out == NULL) + *out = new_next; + else + g_object_unref(G_OBJECT(new_next)); + + } } - else - g_pending_call_set_base(G_PENDING_CALL(new_next), rebase); - - } - if (last) - result = g_registered_item_reduce(expr->base, ctx, expr->args, expr->count, final); + exit: - else - { - result = g_scan_expression_reduce(new_next, ctx, final); - - if (result == NULL) - { - g_object_ref(G_OBJECT(new_next)); - result = new_next; - } + g_object_unref(G_OBJECT(new)); } - done: - - g_clear_object(&new_next); - return result; } diff --git a/src/analysis/scan/exprs/call.h b/src/analysis/scan/exprs/call.h index b69ca85..c344036 100644 --- a/src/analysis/scan/exprs/call.h +++ b/src/analysis/scan/exprs/call.h @@ -26,7 +26,7 @@ #include "../expr.h" -#include "../item.h" +#include "../../../common/szstr.h" @@ -49,10 +49,7 @@ typedef struct _GPendingCallClass GPendingCallClass; GType g_pending_call_get_type(void); /* Organise un appel de fonction avec ses arguments. */ -GScanExpression *g_pending_call_new(const char *, size_t, GScanExpression **, size_t); - -/* Complète la chaine d'expressions d'appel. */ -void g_pending_call_attach_next(GPendingCall *, GPendingCall *); +GScanExpression *g_pending_call_new(const sized_string_t *, GScanExpression **, size_t); diff --git a/src/analysis/scan/exprs/literal-int.h b/src/analysis/scan/exprs/literal-int.h index d803d30..875b3de 100644 --- a/src/analysis/scan/exprs/literal-int.h +++ b/src/analysis/scan/exprs/literal-int.h @@ -46,7 +46,7 @@ struct _GLiteralExpression { bool boolean; /* Valeur booléenne */ unsigned long long integer; /* Valeur entière 64 bits */ - char *string; /* Chaîne de caractères */ + sized_string_t string; /* Chaîne de caractères */ struct { char *regex; /* Formulation d'origine */ diff --git a/src/analysis/scan/exprs/literal.c b/src/analysis/scan/exprs/literal.c index f40747d..119b871 100644 --- a/src/analysis/scan/exprs/literal.c +++ b/src/analysis/scan/exprs/literal.c @@ -57,10 +57,10 @@ static void g_literal_expression_finalize(GLiteralExpression *); static bool g_literal_expression_compare_rich(const GLiteralExpression *, const GLiteralExpression *, RichCmpOperation, bool *); /* Reproduit une expression en place dans une nouvelle instance. */ -static GScanExpression *g_literal_expression_duplicate(const GLiteralExpression *); +static void g_literal_expression_copy(GLiteralExpression *, const GLiteralExpression *); /* Réduit une expression à une forme plus simple. */ -GScanExpression *g_literal_expression_reduce(GLiteralExpression *, GScanContext *, bool); +static bool g_literal_expression_reduce(GLiteralExpression *, GScanContext *, GScanScope *, GScanExpression **); @@ -98,7 +98,7 @@ static void g_literal_expression_class_init(GLiteralExpressionClass *klass) expr = G_SCAN_EXPRESSION_CLASS(klass); expr->cmp_rich = (compare_expr_rich_fc)g_literal_expression_compare_rich; - expr->dup = (dup_expr_fc)g_literal_expression_duplicate; + expr->copy = (copy_expr_fc)g_literal_expression_copy; expr->reduce = (reduce_expr_fc)g_literal_expression_reduce; } @@ -215,7 +215,8 @@ bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype, va_list ap; /* Liste d'arguements */ const bool *boolean; /* Valeur booléenne */ const unsigned long long *integer; /* Valeur entière 64 bits */ - const char *string; /* Chaîne de caractères */ + const sized_string_t *string; /* Chaîne de caractères */ + const char *raw; /* Chaîne de caractères brute */ size_t len; /* Taille de la chaîne */ int cflags; /* Détails de compilation */ unsigned int i; /* Boucle de parcours */ @@ -241,15 +242,15 @@ bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype, break; case EVT_STRING: - string = va_arg(ap, const char *); - expr->value.string = strdup(string); + string = va_arg(ap, const sized_string_t *); + szstrdup(&expr->value.string, string); break; case EVT_REG_EXPR: - string = va_arg(ap, const char *); - len = strlen(string); + raw = va_arg(ap, const char *); + len = strlen(raw); - result = (len > 2 && string[0] == '/'); + result = (len > 2 && raw[0] == '/'); cflags = REG_EXTENDED | REG_NOSUB; @@ -257,38 +258,38 @@ bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype, { result = (len > 2); - if (string[len - 1] == 'i') + if (raw[len - 1] == 'i') { cflags |= REG_ICASE; len -= 1; } - else if (string[len - 1] == 's') + else if (raw[len - 1] == 's') { cflags |= REG_NEWLINE; len -= 1; } - else if (string[len - 1] == '/') + else if (raw[len - 1] == '/') break; } if (result) - result = (string[len - 1] == '/'); + result = (raw[len - 1] == '/'); if (result) { assert(len > 2); - tmp = strndup(&string[1], len - 2); + tmp = strndup(&raw[1], len - 2); ret = regcomp(&expr->value.preg, tmp, cflags); free(tmp); result = (ret == 0); if (result) - expr->value.regex = strdup(string); + expr->value.regex = strdup(raw); } @@ -378,14 +379,14 @@ bool g_literal_expression_get_integer_value(const GLiteralExpression *item, unsi * * ******************************************************************************/ -bool g_literal_expression_get_string_value(const GLiteralExpression *item, const char **value) +bool g_literal_expression_get_string_value(const GLiteralExpression *item, const sized_string_t **value) { bool result; /* Etat à retourner */ result = (item->value_type == EVT_STRING); if (result) - *value = item->value.string; + *value = &item->value.string; return result; @@ -445,10 +446,12 @@ static bool g_literal_expression_compare_rich(const GLiteralExpression *item, co bool result; /* Etat à retourner */ int cmp; /* Bilan intermédiaire */ + result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_LITERAL_EXPRESSION); + if (!result) goto done; + if (item->value_type != other->value_type) { *status = compare_rich_integer_values(item->value_type, other->value_type, op); - result = true; goto done; } @@ -480,7 +483,7 @@ static bool g_literal_expression_compare_rich(const GLiteralExpression *item, co break; case EVT_STRING: - cmp = strcmp(item->value.string, other->value.string); + cmp = szstrcmp(&item->value.string, &other->value.string); *status = compare_rich_integer_values(cmp, 0, op); result = true; break; @@ -506,51 +509,51 @@ static bool g_literal_expression_compare_rich(const GLiteralExpression *item, co /****************************************************************************** * * -* Paramètres : expr = expression à copier. * +* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] * +* src = expression source à copier. * * * * Description : Reproduit une expression en place dans une nouvelle instance.* * * -* Retour : Nouvelle instance d'expression. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static GScanExpression *g_literal_expression_duplicate(const GLiteralExpression *expr) +static void g_literal_expression_copy(GLiteralExpression *dest, const GLiteralExpression *src) { - GScanExpression *result; /* Instance copiée à retourner */ - const void *ptr; /* Pointeur vers des données */ + GScanExpressionClass *class; /* Classe parente à solliciter */ + + class = G_SCAN_EXPRESSION_CLASS(g_literal_expression_parent_class); + + class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src)); - switch (expr->value_type) + dest->value_type = src->value_type; + + switch (src->value_type) { case EVT_BOOLEAN: - ptr = &expr->value.boolean; + dest->value.boolean = src->value.boolean; break; case EVT_INTEGER: - ptr = &expr->value.integer; + dest->value.integer = src->value.integer; break; case EVT_STRING: - ptr = &expr->value.string; + szstrdup(&dest->value.string, &src->value.string); break; case EVT_REG_EXPR: - ptr = &expr->value.regex; + /*ptr = &expr->value.regex*//* FIXME */; break; default: - ptr = NULL; + assert(false); break; } - assert(ptr != NULL); - - result = g_literal_expression_new(expr->value_type, ptr); - - return result; - } @@ -558,47 +561,25 @@ static GScanExpression *g_literal_expression_duplicate(const GLiteralExpression * * * Paramètres : expr = expression à consulter. * * ctx = contexte de suivi de l'analyse courante. * -* force = impose une conversion en booléen si possible. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la réduction opérée. [OUT] * * * * Description : Réduit une expression à une forme plus simple. * * * -* Retour : Réduction correspondante, expression déjà réduite, ou NULL. * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * * Remarques : - * * * ******************************************************************************/ -GScanExpression *g_literal_expression_reduce(GLiteralExpression *expr, GScanContext *ctx, bool force) +static bool g_literal_expression_reduce(GLiteralExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - GScanExpression *result; /* Instance à renvoyer */ - - if (!force) - result = NULL; - - else - switch (expr->value_type) - { - case EVT_BOOLEAN: - result = NULL; - break; - - case EVT_INTEGER: - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { expr->value.integer > 0 }); - break; - - case EVT_STRING: - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { strlen(expr->value.string) > 0 }); - break; - - case EVT_REG_EXPR: - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { strlen(expr->value.regex) > 0 }); - break; + bool result; /* Bilan à retourner */ - default: - result = NULL; - break; + result = true; - } + *out = G_SCAN_EXPRESSION(expr); + g_object_ref(G_OBJECT(expr)); return result; diff --git a/src/analysis/scan/exprs/literal.h b/src/analysis/scan/exprs/literal.h index ac5724f..7120c07 100644 --- a/src/analysis/scan/exprs/literal.h +++ b/src/analysis/scan/exprs/literal.h @@ -29,6 +29,7 @@ #include "../expr.h" +#include "../../../common/szstr.h" @@ -60,7 +61,7 @@ bool g_literal_expression_get_boolean_value(const GLiteralExpression *, bool *); bool g_literal_expression_get_integer_value(const GLiteralExpression *, unsigned long long *); /* Indique la valeur portée par une expression de chaîne. */ -bool g_literal_expression_get_string_value(const GLiteralExpression *, const char **); +bool g_literal_expression_get_string_value(const GLiteralExpression *, const sized_string_t **); /* Indique la valeur portée par une expression rationnelle. */ bool g_literal_expression_get_regex_value(const GLiteralExpression *, const regex_t **); diff --git a/src/analysis/scan/exprs/relop-int.h b/src/analysis/scan/exprs/relop-int.h index 273b543..3adbcf0 100644 --- a/src/analysis/scan/exprs/relop-int.h +++ b/src/analysis/scan/exprs/relop-int.h @@ -39,8 +39,8 @@ struct _GRelOperation RichCmpOperation rel_type; /* Type de relation étudiée */ - GScanExpression *first; /* Expression impactée #1 */ - GScanExpression *second; /* Expression impactée #2 */ + GScanExpression *left; /* Expression impactée #1 */ + GScanExpression *right; /* Expression impactée #2 */ }; diff --git a/src/analysis/scan/exprs/relop.c b/src/analysis/scan/exprs/relop.c index 94ce77d..7dc6864 100644 --- a/src/analysis/scan/exprs/relop.c +++ b/src/analysis/scan/exprs/relop.c @@ -52,11 +52,11 @@ static void g_relational_operation_finalize(GRelOperation *); /* Réalise une comparaison entre objets selon un critère précis. */ static bool g_relational_operation_compare_rich(const GRelOperation *, const GRelOperation *, RichCmpOperation, bool *); -/* Initialise une instance d'opération de relation. */ -static GScanExpression *g_relational_operation_duplicate(const GRelOperation *); +/* Reproduit une expression en place dans une nouvelle instance. */ +static void g_relational_operation_copy(GRelOperation *, const GRelOperation *); /* Réduit une expression à une forme plus simple. */ -GScanExpression *g_relational_operation_reduce(GRelOperation *, GScanContext *, bool); +static bool g_relational_operation_reduce(GRelOperation *, GScanContext *, GScanScope *, GScanExpression **); @@ -94,7 +94,7 @@ static void g_relational_operation_class_init(GRelOperationClass *klass) expr = G_SCAN_EXPRESSION_CLASS(klass); expr->cmp_rich = (compare_expr_rich_fc)g_relational_operation_compare_rich; - expr->dup = (dup_expr_fc)g_relational_operation_duplicate; + expr->copy = (copy_expr_fc)g_relational_operation_copy; expr->reduce = (reduce_expr_fc)g_relational_operation_reduce; } @@ -114,8 +114,8 @@ static void g_relational_operation_class_init(GRelOperationClass *klass) static void g_relational_operation_init(GRelOperation *op) { - op->first = NULL; - op->second = NULL; + op->left = NULL; + op->right = NULL; } @@ -134,8 +134,8 @@ static void g_relational_operation_init(GRelOperation *op) static void g_relational_operation_dispose(GRelOperation *op) { - g_clear_object(&op->first); - g_clear_object(&op->second); + g_clear_object(&op->left); + g_clear_object(&op->right); G_OBJECT_CLASS(g_relational_operation_parent_class)->dispose(G_OBJECT(op)); @@ -163,9 +163,9 @@ static void g_relational_operation_finalize(GRelOperation *op) /****************************************************************************** * * -* Paramètres : type = type d'opération booléenne à représenter. * -* first = premier opérande concerné. * -* second = éventuel second opérande impliqué ou NULL. * +* Paramètres : type = type d'opération booléenne à représenter. * +* left = premier opérande concerné. * +* right = éventuel second opérande impliqué ou NULL. * * * * Description : Organise une opération relationnelle entre expressions. * * * @@ -175,13 +175,13 @@ static void g_relational_operation_finalize(GRelOperation *op) * * ******************************************************************************/ -GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpression *first, GScanExpression *second) +GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpression *left, GScanExpression *right) { GScanExpression *result; /* Structure à retourner */ result = g_object_new(G_TYPE_RELATIONAL_OPERATION, NULL); - if (!g_relational_operation_create(G_RELATIONAL_OPERATION(result), type, first, second)) + if (!g_relational_operation_create(G_RELATIONAL_OPERATION(result), type, left, right)) g_clear_object(&result); return result; @@ -191,10 +191,10 @@ GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpressi /****************************************************************************** * * -* Paramètres : op = instance à initialiser pleinement. * -* type = type d'opération booléenne à représenter. * -* first = premier opérande concerné. * -* second = éventuel second opérande impliqué ou NULL. * +* Paramètres : op = instance à initialiser pleinement. * +* type = type d'opération booléenne à représenter. * +* left = premier opérande concerné. * +* right = éventuel second opérande impliqué ou NULL. * * * * Description : Met en place une opération relationnelle entre expressions. * * * @@ -204,13 +204,13 @@ GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpressi * * ******************************************************************************/ -bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GScanExpression *first, GScanExpression *second) +bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GScanExpression *left, GScanExpression *right) { bool result; /* Bilan à retourner */ result = false; - if (g_scan_expression_get_value_type(first) != g_scan_expression_get_value_type(first)) + if (g_scan_expression_get_value_type(left) != g_scan_expression_get_value_type(left)) goto exit; if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_BOOLEAN)) @@ -218,11 +218,11 @@ bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GSc op->rel_type = type; - op->first = first; - g_object_ref(G_OBJECT(op->first)); + op->left = left; + g_object_ref(G_OBJECT(op->left)); - op->second = second; - g_object_ref(G_OBJECT(op->second)); + op->right = right; + g_object_ref(G_OBJECT(op->right)); result = true; @@ -257,28 +257,26 @@ bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GSc static bool g_relational_operation_compare_rich(const GRelOperation *item, const GRelOperation *other, RichCmpOperation op, bool *status) { bool result; /* Etat à retourner */ - bool equal; /* Bilan intermédiaire */ - result = true; // TODO : cmp parent()->type + result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_RELATIONAL_OPERATION); + if (!result) goto done; if (item->rel_type != other->rel_type) { - result = compare_rich_integer_values(item->rel_type, other->rel_type, op); + *status = compare_rich_integer_values(item->rel_type, other->rel_type, op); goto done; } - equal = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status); + result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status); + if (!result || STATUS_NOT_EQUAL(*status, op)) goto done; - if (!equal) - { - result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first), - G_COMPARABLE_ITEM(other->first), - op, status); - goto done; - } + result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->left), + G_COMPARABLE_ITEM(other->left), + op, status); + if (!result || STATUS_NOT_EQUAL(*status, op)) goto done; - result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second), - G_COMPARABLE_ITEM(other->second), + result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->right), + G_COMPARABLE_ITEM(other->right), op, status); done: @@ -290,23 +288,29 @@ static bool g_relational_operation_compare_rich(const GRelOperation *item, const /****************************************************************************** * * -* Paramètres : expr = expression à copier. * +* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] * +* src = expression source à copier. * * * * Description : Reproduit une expression en place dans une nouvelle instance.* * * -* Retour : Nouvelle instance d'expression. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static GScanExpression *g_relational_operation_duplicate(const GRelOperation *expr) +static void g_relational_operation_copy(GRelOperation *dest, const GRelOperation *src) { - GScanExpression *result; /* Instance copiée à retourner */ + GScanExpressionClass *class; /* Classe parente à solliciter */ - result = g_relational_operation_new(expr->rel_type, expr->first, expr->second); + class = G_SCAN_EXPRESSION_CLASS(g_relational_operation_parent_class); - return result; + class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src)); + + dest->rel_type = src->rel_type; + + dest->left = g_scan_expression_duplicate(src->left); + dest->right = g_scan_expression_duplicate(src->right); } @@ -315,60 +319,74 @@ static GScanExpression *g_relational_operation_duplicate(const GRelOperation *ex * * * Paramètres : expr = expression à consulter. * * ctx = contexte de suivi de l'analyse courante. * -* final = impose une conversion finale de dernier tour. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la réduction opérée. [OUT] * * * * Description : Réduit une expression à une forme plus simple. * * * -* Retour : Réduction correspondante, expression déjà réduite, ou NULL. * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * * Remarques : - * * * ******************************************************************************/ -GScanExpression *g_relational_operation_reduce(GRelOperation *expr, GScanContext *ctx, bool final) +static bool g_relational_operation_reduce(GRelOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - GScanExpression *result; /* Instance à renvoyer */ - GScanExpression *new; /* Nouvelle expression obtenue */ + bool result; /* Bilan à retourner */ + GScanExpression *new_left; /* Expression réduite (gauche) */ + GScanExpression *new_right; /* Expression réduite (droite) */ bool status; /* Bilan d'une comparaison */ bool valid; /* Validité de ce bilan obtenu */ - result = NULL; - /* Réduction des éléments considérés */ - new = g_scan_expression_reduce(expr->first, ctx, final); + new_left = NULL; + new_right = NULL; - if (new != NULL) - { - g_object_unref(G_OBJECT(expr->first)); - expr->first = new; - } + result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left); + if (!result) goto exit; + + result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right); + if (!result) goto exit; + + /* Construction d'une réduction locale ? */ - if (expr->second != NULL) + if (G_IS_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right)) { - new = g_scan_expression_reduce(expr->second, ctx, final); + valid = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(new_left), + G_COMPARABLE_ITEM(new_right), + expr->rel_type, &status); - if (new != NULL) - { - g_object_unref(G_OBJECT(expr->second)); - expr->second = new; - } + if (valid) + *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { status }); } - /* Construction d'une réduction locale ? */ + /* Mise à jour de la progression ? */ - if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second)) + else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right)) { - valid = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(expr->first), - G_COMPARABLE_ITEM(expr->second), - expr->rel_type, &status); + if (new_left == NULL) + { + new_left = expr->left; + g_object_ref(G_OBJECT(new_left)); + } - if (valid) - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { status }); + if (new_right == NULL) + { + new_right = expr->right; + g_object_ref(G_OBJECT(new_right)); + } + + *out = g_relational_operation_new(expr->rel_type, new_left, new_right); } + exit: + + g_clear_object(&new_left); + g_clear_object(&new_right); + return result; } diff --git a/src/analysis/scan/exprs/str-int.h b/src/analysis/scan/exprs/strop-int.h index 9bed5cf..234ae8f 100644 --- a/src/analysis/scan/exprs/str-int.h +++ b/src/analysis/scan/exprs/strop-int.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * str-int.h - prototypes internes pour la gestion des opérations booléennes + * strop-int.h - prototypes internes pour la gestion des opérations booléennes * * Copyright (C) 2022 Cyrille Bagard * @@ -21,14 +21,15 @@ */ -#ifndef _ANALYSIS_SCAN_EXPRS_STR_INT_H -#define _ANALYSIS_SCAN_EXPRS_STR_INT_H +#ifndef _ANALYSIS_SCAN_EXPRS_STROP_INT_H +#define _ANALYSIS_SCAN_EXPRS_STROP_INT_H -#include "str.h" +#include "strop.h" #include "../expr-int.h" +#include "../../../common/extstr.h" @@ -40,8 +41,8 @@ struct _GStringOperation StringOperationType type; /* Type d'opération menée */ bool case_sensitive; /* Respect de la casse ? */ - GScanExpression *first; /* Expression impactée #1 */ - GScanExpression *second; /* Expression impactée #2 */ + GScanExpression *left; /* Expression impactée #1 */ + GScanExpression *right; /* Expression impactée #2 */ }; @@ -58,4 +59,4 @@ bool g_string_operation_create(GStringOperation *, StringOperationType, GScanExp -#endif /* _ANALYSIS_SCAN_EXPRS_STR_INT_H */ +#endif /* _ANALYSIS_SCAN_EXPRS_STROP_INT_H */ diff --git a/src/analysis/scan/exprs/str.c b/src/analysis/scan/exprs/strop.c index 675b2f6..145e8da 100644 --- a/src/analysis/scan/exprs/str.c +++ b/src/analysis/scan/exprs/strop.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * str.c - gestion des opérations booléennes + * strop.c - gestion des opérations booléennes * * Copyright (C) 2022 Cyrille Bagard * @@ -21,7 +21,7 @@ */ -#include "str.h" +#include "strop.h" #include <assert.h> @@ -29,7 +29,7 @@ #include <strings.h> -#include "str-int.h" +#include "strop-int.h" #include "literal.h" @@ -55,10 +55,10 @@ static void g_string_operation_finalize(GStringOperation *); /* Reproduit une expression en place dans une nouvelle instance. */ -static GScanExpression *g_string_operation_duplicate(const GStringOperation *); +static void g_string_operation_copy(GStringOperation *, const GStringOperation *); /* Réduit une expression à une forme plus simple. */ -GScanExpression *g_string_operation_reduce(GStringOperation *, GScanContext *, bool); +static bool g_string_operation_reduce(GStringOperation *, GScanContext *, GScanScope *, GScanExpression **); @@ -96,7 +96,7 @@ static void g_string_operation_class_init(GStringOperationClass *klass) expr = G_SCAN_EXPRESSION_CLASS(klass); expr->cmp_rich = (compare_expr_rich_fc)NULL; - expr->dup = (dup_expr_fc)g_string_operation_duplicate; + expr->copy = (copy_expr_fc)g_string_operation_copy; expr->reduce = (reduce_expr_fc)g_string_operation_reduce; } @@ -116,8 +116,8 @@ static void g_string_operation_class_init(GStringOperationClass *klass) static void g_string_operation_init(GStringOperation *op) { - op->first = NULL; - op->second = NULL; + op->left = NULL; + op->right = NULL; } @@ -136,8 +136,8 @@ static void g_string_operation_init(GStringOperation *op) static void g_string_operation_dispose(GStringOperation *op) { - g_clear_object(&op->first); - g_clear_object(&op->second); + g_clear_object(&op->left); + g_clear_object(&op->right); G_OBJECT_CLASS(g_string_operation_parent_class)->dispose(G_OBJECT(op)); @@ -196,9 +196,9 @@ GScanExpression *g_string_operation_new(StringOperationType type, GScanExpressio * * * Paramètres : op = instance à initialiser pleinement. * * type = type d'opération booléenne à représenter. * -* first = premier opérande concerné. * -* second = éventuel second opérande impliqué ou NULL. * -* sensitive = détermine la prise en compte de la casse. * +* left = premier opérande concerné. * +* right = éventuel second opérande impliqué ou NULL. * +* sensitive = détermine la prise en compte de la casse. * * * * Description : Met en place une expression d'opération traite une chaîne. * * * @@ -208,19 +208,19 @@ GScanExpression *g_string_operation_new(StringOperationType type, GScanExpressio * * ******************************************************************************/ -bool g_string_operation_create(GStringOperation *op, StringOperationType type, GScanExpression *first, GScanExpression *second, bool sensitive) +bool g_string_operation_create(GStringOperation *op, StringOperationType type, GScanExpression *left, GScanExpression *right, bool sensitive) { bool result; /* Bilan à retourner */ ExprValueType vtype; /* Type de valeur portée */ result = false; - vtype = g_scan_expression_get_value_type(first); + vtype = g_scan_expression_get_value_type(left); if (vtype != EVT_STRING && vtype != EVT_PENDING) goto exit; - vtype = g_scan_expression_get_value_type(second); + vtype = g_scan_expression_get_value_type(right); if (vtype != EVT_STRING && vtype != EVT_REG_EXPR && vtype != EVT_PENDING) goto exit; @@ -245,11 +245,11 @@ bool g_string_operation_create(GStringOperation *op, StringOperationType type, G } - op->first = first; - g_object_ref(G_OBJECT(op->first)); + op->left = left; + g_object_ref(G_OBJECT(op->left)); - op->second = second; - g_object_ref(G_OBJECT(op->second)); + op->right = right; + g_object_ref(G_OBJECT(op->right)); result = true; @@ -268,170 +268,202 @@ bool g_string_operation_create(GStringOperation *op, StringOperationType type, G /****************************************************************************** * * -* Paramètres : op = expression à copier. * +* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] * +* src = expression source à copier. * * * * Description : Reproduit une expression en place dans une nouvelle instance.* * * -* Retour : Nouvelle instance d'expression. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static GScanExpression *g_string_operation_duplicate(const GStringOperation *op) +static void g_string_operation_copy(GStringOperation *dest, const GStringOperation *src) { - GScanExpression *result; /* Instance copiée à retourner */ + GScanExpressionClass *class; /* Classe parente à solliciter */ - result = g_string_operation_new(op->type, op->first, op->second, op->case_sensitive); + class = G_SCAN_EXPRESSION_CLASS(g_string_operation_parent_class); - return result; + class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src)); + + dest->type = src->type; + dest->case_sensitive = src->case_sensitive; + + dest->left = g_scan_expression_duplicate(src->left); + dest->right = g_scan_expression_duplicate(src->right); } /****************************************************************************** * * -* Paramètres : op = expression à consulter. * +* Paramètres : expr = expression à consulter. * * ctx = contexte de suivi de l'analyse courante. * -* final = impose une conversion finale de dernier tour. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la réduction opérée. [OUT] * * * * Description : Réduit une expression à une forme plus simple. * * * -* Retour : Réduction correspondante, expression déjà réduite, ou NULL. * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * * Remarques : - * * * ******************************************************************************/ -GScanExpression *g_string_operation_reduce(GStringOperation *op, GScanContext *ctx, bool final) +static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - GScanExpression *result; /* Instance à renvoyer */ - GScanExpression *new; /* Nouvelle expression obtenue */ - const char *strings[2]; /* Chaînes en jeu */ - bool status; /* Bilan intermédiaire */ - char *found; /* Eventuelle portion trouvée */ - size_t len[2]; /* Tailles max. de comparaison */ - int ret; /* Bilan de comparaison */ + bool result; /* Bilan à retourner */ + GScanExpression *new_left; /* Expression réduite (gauche) */ + GScanExpression *new_right; /* Expression réduite (droite) */ + GLiteralExpression *op_left; /* Opérande gauche final */ + GLiteralExpression *op_right; /* Opérande droite final */ + const sized_string_t *strings[2]; /* Chaînes en jeu */ + const void *found; /* Présence d'une bribe ? */ + bool status; /* Bilan de comparaison #1 */ + size_t offset; /* Point de départ d'analyse */ const regex_t *preg; /* Expression rationnelle */ - - result = NULL; + int ret; /* Bilan de comparaison #2 */ /* Réduction des éléments considérés */ - new = g_scan_expression_reduce(op->first, ctx, final); + new_left = NULL; + new_right = NULL; - if (new != NULL) - { - g_object_unref(G_OBJECT(op->first)); - op->first = new; - } + result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left); + if (!result) goto exit; - new = g_scan_expression_reduce(op->second, ctx, final); - - if (new != NULL) - { - g_object_unref(G_OBJECT(op->second)); - op->second = new; - } + result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right); + if (!result) goto exit; /* Construction d'une réduction locale ? */ - if (!G_IS_LITERAL_EXPRESSION(op->first)) - goto exit; + if (G_IS_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right)) + { + op_left = G_LITERAL_EXPRESSION(new_left); + op_right = G_LITERAL_EXPRESSION(new_right); - if (!G_IS_LITERAL_EXPRESSION(op->second)) - goto exit; + result = g_literal_expression_get_string_value(op_left, &strings[0]); + if (!result) goto exit; - status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->first), &strings[0]); - if (!status) goto exit; + switch (expr->type) + { + case SOT_CONTAINS: - switch (op->type) - { - case SOT_CONTAINS: + result = g_literal_expression_get_string_value(op_right, &strings[1]); + if (!result) goto exit; - status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->second), &strings[1]); - if (!status) goto exit; + if (expr->case_sensitive) + found = memmem(strings[0]->data, strings[0]->len, strings[1]->data, strings[1]->len); - if (op->case_sensitive) - found = strstr(strings[0], strings[1]); - else - found = strcasestr(strings[0], strings[1]); + else + found = memcasemem(strings[0]->data, strings[0]->len, strings[1]->data, strings[1]->len); - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { found != NULL }); - break; + result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { found != NULL }); + break; - case SOT_STARTSWITH: + case SOT_STARTSWITH: - status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->second), &strings[1]); - if (!status) goto exit; + result = g_literal_expression_get_string_value(op_right, &strings[1]); + if (!result) goto exit; - len[1] = strlen(strings[1]); + if (strings[0]->len < strings[1]->len) + status = false; - if (op->case_sensitive) - ret = strncmp(strings[0], strings[1], len[1]); - else - ret = strncasecmp(strings[0], strings[1], len[1]); + else + { + if (expr->case_sensitive) + ret = memcmp(strings[0]->data, strings[1]->data, strings[1]->len); + else + ret = memcasecmp(strings[0]->data, strings[1]->data, strings[1]->len); - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret == 0 }); - break; + status = (ret == 0); - case SOT_ENDSWITH: + } - len[0] = strlen(strings[0]); + result = g_literal_expression_new(EVT_BOOLEAN, &status); + break; - status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->second), &strings[1]); - if (!status) goto exit; + case SOT_ENDSWITH: - len[1] = strlen(strings[1]); + result = g_literal_expression_get_string_value(op_right, &strings[1]); + if (!result) goto exit; - if (len[0] < len[1]) - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false }); + if (strings[0]->len < strings[1]->len) + status = false; - else - { - if (op->case_sensitive) - ret = strncmp(strings[0] + (len[0] - len[1]), strings[1], len[1]); else - ret = strncasecmp(strings[0] + (len[0] - len[1]), strings[1], len[1]); + { + offset = strings[0]->len - strings[1]->len; - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret == 0 }); + if (expr->case_sensitive) + ret = memcmp(strings[0]->data + offset, strings[1]->data, strings[1]->len); + else + ret = memcasecmp(strings[0]->data + offset, strings[1]->data, strings[1]->len); - } - break; + status = (ret == 0); - case SOT_MATCHES: + } - status = g_literal_expression_get_regex_value(G_LITERAL_EXPRESSION(op->second), &preg); - if (!status) goto exit; + result = g_literal_expression_new(EVT_BOOLEAN, &status); + break; - ret = regexec(preg, strings[0], 0, NULL, 0); + case SOT_MATCHES: - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret != REG_NOMATCH }); - break; + result = g_literal_expression_get_regex_value(op_right, &preg); + if (!result) goto exit; - case SOT_IEQUALS: + ret = regexec(preg, strings[0]->data, 0, NULL, 0); - len[0] = strlen(strings[0]); + *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret != REG_NOMATCH }); + break; - status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->second), &strings[1]); - if (!status) goto exit; + case SOT_IEQUALS: - len[1] = strlen(strings[1]); + result = g_literal_expression_get_string_value(op_right, &strings[1]); + if (!result) goto exit; - if (len[0] != len[1]) - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false }); + if (strings[0]->len != strings[1]->len) + status = false; - else - { - ret = strcasecmp(strings[0], strings[1]); - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret == 0 }); - } - break; + else + { + ret = memcasecmp(strings[0]->data, strings[1]->data, strings[1]->len); + status = (ret == 0); + } + + result = g_literal_expression_new(EVT_BOOLEAN, &status); + break; + + } + + } + + /* Mise à jour de la progression ? */ + + else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right)) + { + if (new_left == NULL) + { + new_left = expr->left; + g_object_ref(G_OBJECT(new_left)); + } + + if (new_right == NULL) + { + new_right = expr->right; + g_object_ref(G_OBJECT(new_right)); + } + + *out = g_string_operation_new(expr->type, new_left, new_right, expr->case_sensitive); } exit: + g_clear_object(&new_left); + g_clear_object(&new_right); + return result; } diff --git a/src/analysis/scan/exprs/str.h b/src/analysis/scan/exprs/strop.h index 195f941..c7c0813 100644 --- a/src/analysis/scan/exprs/str.h +++ b/src/analysis/scan/exprs/strop.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * str.h - prototypes pour la gestion des opérations booléennes + * strop.h - prototypes pour la gestion des opérations booléennes * * Copyright (C) 2022 Cyrille Bagard * @@ -21,8 +21,8 @@ */ -#ifndef _ANALYSIS_SCAN_EXPRS_STR_H -#define _ANALYSIS_SCAN_EXPRS_STR_H +#ifndef _ANALYSIS_SCAN_EXPRS_STROP_H +#define _ANALYSIS_SCAN_EXPRS_STROP_H #include "../expr.h" @@ -64,4 +64,4 @@ GScanExpression *g_string_operation_new(StringOperationType, GScanExpression *, -#endif /* _ANALYSIS_SCAN_EXPRS_STR_H */ +#endif /* _ANALYSIS_SCAN_EXPRS_STROP_H */ diff --git a/src/analysis/scan/func-int.h b/src/analysis/scan/func-int.h deleted file mode 100644 index 6591ba4..0000000 --- a/src/analysis/scan/func-int.h +++ /dev/null @@ -1,51 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * func-int.h - prototypes internes pour la définition d'une fonction ciblant une propriété pendant un scan - * - * Copyright (C) 2022 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * Chrysalide is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Chrysalide is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _ANALYSIS_SCAN_FUNC_INT_H -#define _ANALYSIS_SCAN_FUNC_INT_H - - -#include "func.h" - - -#include "item-int.h" - - - -/* Fonction apportant un support d'analyse pendant un scan (instance) */ -struct _GScanFunction -{ - GRegisteredItem parent; /* A laisser en premier */ - -}; - -/* Fonction apportant un support d'analyse pendant un scan (classe) */ -struct _GScanFunctionClass -{ - GRegisteredItemClass parent; /* A laisser en premier */ - -}; - - - -#endif /* _ANALYSIS_SCAN_FUNC_INT_H */ diff --git a/src/analysis/scan/func.c b/src/analysis/scan/func.c deleted file mode 100644 index b839d1d..0000000 --- a/src/analysis/scan/func.c +++ /dev/null @@ -1,126 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * func.c - définition d'une fonction ciblant une propriété pendant un scan - * - * Copyright (C) 2022 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * Chrysalide is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Chrysalide is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "func.h" - - -#include "func-int.h" - - - -/* Initialise la classe des fonctions de support pour scan. */ -static void g_scan_function_class_init(GScanFunctionClass *); - -/* Initialise une instance de fonction de support pour scan. */ -static void g_scan_function_init(GScanFunction *); - -/* Supprime toutes les références externes. */ -static void g_scan_function_dispose(GScanFunction *); - -/* Procède à la libération totale de la mémoire. */ -static void g_scan_function_finalize(GScanFunction *); - - - -/* Indique le type défini pour une définition de fonction de scan. */ -G_DEFINE_TYPE(GScanFunction, g_scan_function, G_TYPE_REGISTERED_ITEM); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des fonctions de support pour scan. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_scan_function_class_init(GScanFunctionClass *klass) -{ - GObjectClass *object; /* Autre version de la classe */ - - object = G_OBJECT_CLASS(klass); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_function_dispose; - object->finalize = (GObjectFinalizeFunc)g_scan_function_finalize; - -} - - -/****************************************************************************** -* * -* Paramètres : func = instance à initialiser. * -* * -* Description : Initialise une instance de fonction de support pour scan. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_scan_function_init(GScanFunction *func) -{ - -} - - -/****************************************************************************** -* * -* Paramètres : func = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_scan_function_dispose(GScanFunction *func) -{ - G_OBJECT_CLASS(g_scan_function_parent_class)->dispose(G_OBJECT(func)); - -} - - -/****************************************************************************** -* * -* Paramètres : func = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_scan_function_finalize(GScanFunction *func) -{ - G_OBJECT_CLASS(g_scan_function_parent_class)->finalize(G_OBJECT(func)); - -} diff --git a/src/analysis/scan/func.h b/src/analysis/scan/func.h deleted file mode 100644 index bfc823a..0000000 --- a/src/analysis/scan/func.h +++ /dev/null @@ -1,52 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * func.h - prototypes pour la définition d'une fonction ciblant une propriété pendant un scan - * - * Copyright (C) 2022 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * Chrysalide is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Chrysalide is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _ANALYSIS_SCAN_FUNC_H -#define _ANALYSIS_SCAN_FUNC_H - - -#include <glib-object.h> - - - -#define G_TYPE_SCAN_FUNCTION g_scan_function_get_type() -#define G_SCAN_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_FUNCTION, GScanFunction)) -#define G_IS_SCAN_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_FUNCTION)) -#define G_SCAN_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_FUNCTION, GScanFunctionClass)) -#define G_IS_SCAN_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_FUNCTION)) -#define G_SCAN_FUNCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_FUNCTION, GScanFunctionClass)) - - -/* Fonction apportant un support d'analyse pendant un scan (instance) */ -typedef struct _GScanFunction GScanFunction; - -/* Fonction apportant un support d'analyse pendant un scan (classe) */ -typedef struct _GScanFunctionClass GScanFunctionClass; - - -/* Indique le type défini pour une définition de fonction de scan. */ -GType g_scan_function_get_type(void); - - - -#endif /* _ANALYSIS_SCAN_FUNC_H */ diff --git a/src/analysis/scan/funcs/Makefile.am b/src/analysis/scan/funcs/Makefile.am deleted file mode 100644 index be370ba..0000000 --- a/src/analysis/scan/funcs/Makefile.am +++ /dev/null @@ -1,15 +0,0 @@ - -noinst_LTLIBRARIES = libanalysisscanfuncs.la - - -libanalysisscanfuncs_la_SOURCES = \ - datasize.h datasize.c \ - uint-int.h \ - uint.h uint.c - -libanalysisscanfuncs_la_CFLAGS = $(LIBGOBJ_CFLAGS) - - -devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) - -dev_HEADERS = $(libanalysisscanfuncs_la_SOURCES:%c=) diff --git a/src/analysis/scan/grammar.y b/src/analysis/scan/grammar.y index ab64ad8..525c5d1 100644 --- a/src/analysis/scan/grammar.y +++ b/src/analysis/scan/grammar.y @@ -17,12 +17,12 @@ static int yyerror(GContentScanner *, yyscan_t, GScanRule **, void/*GBytesPatter typedef void *yyscan_t; #include "scanner.h" -#include "conds/counter.h" +#include "exprs/access.h" #include "exprs/arithmop.h" #include "exprs/boolop.h" #include "exprs/call.h" #include "exprs/literal.h" -#include "exprs/str.h" +#include "exprs/strop.h" #include "exprs/relop.h" #include "patterns/tokens/plain.h" @@ -46,14 +46,16 @@ typedef void *yyscan_t; %union { - //char *string; /* Chaîne de caractères #1 */ - const char *cstring; /* Chaîne de caractères #2 */ + unsigned long long unsigned_integer; /* Valeur entière #1 */ + signed long long signed_integer; /* Valeur entière #2 */ + double floating_number; /* Valeur à virgule flottante */ + sized_string_t sized_cstring; /* Chaîne de caractères */ + char byte; /* Octet unique */ + + + unsigned long long integer; /* Valeur entière */ - struct { - const char *cstring; /* Chaîne de caractères #3 */ - size_t len; /* Taille correspondante */ - } sized_cstring; GScanRule *rule; /* Nouvelle règle à intégrer */ void/*GBytesPattern*/ *pattern; /* Nouveau motif à considérer */ @@ -97,8 +99,6 @@ YY_DECL; %token BRACE_IN BRACE_OUT ASSIGN COLON -%token RAW_BLOCK - %token PLAIN_STRING %token MASKED_STRING @@ -147,8 +147,7 @@ YY_DECL; %token THEM "them" -%type <cstring> RULE_NAME -%type <cstring> RAW_BLOCK +%type <sized_cstring> RULE_NAME %type <sized_cstring> IDENTIFIER @@ -156,7 +155,7 @@ YY_DECL; %type <integer> INTEGER -%type <cstring> STRING +%type <sized_cstring> STRING %type <rule> rule @@ -165,7 +164,7 @@ YY_DECL; %type <expr> cexpression %type <expr> literal -%type <expr> callable +%type <expr> item_chain %type <args_list> call_args %type <expr> bool_expr %type <expr> rel_expr @@ -214,7 +213,7 @@ rules : /* empty */ rule : RAW_RULE RULE_NAME { - *built_rule = g_scan_rule_new($2); + *built_rule = g_scan_rule_new($2.data); $<rule>$ = *built_rule; } BRACE_IN strings condition BRACE_OUT @@ -238,8 +237,8 @@ string_decls : string_decl string_decl : IDENTIFIER ASSIGN PLAIN_STRING { GSearchPattern *__pat; - __pat = g_plain_bytes_new((uint8_t *)$3.cstring, $3.len); - g_search_pattern_set_name(__pat, $1.cstring, $1.len); + __pat = g_plain_bytes_new((uint8_t *)$3.data, $3.len); + g_search_pattern_set_name(__pat, $1.data, $1.len); g_scan_rule_add_local_variable(*built_rule, __pat); g_object_unref(G_OBJECT(__pat)); @@ -300,7 +299,7 @@ cexpression : IDENTIFIER */ } | literal { $$ = $1; } - | callable { $$ = $1; } + | item_chain { $$ = $1; } | bool_expr { $$ = $1; } | rel_expr { $$ = $1; } | str_expr { $$ = $1; } @@ -315,42 +314,42 @@ literal : "true" { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ true }) | INTEGER KB { $$ = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ $1 * 1024 }); } | INTEGER MB { $$ = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ $1 * 1048576 }); } | INTEGER GB { $$ = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ $1 * 1073741824 }); } - | STRING { $$ = g_literal_expression_new(EVT_STRING, $1); } + | STRING { $$ = g_literal_expression_new(EVT_STRING, &$1); } ; -callable : NAME { $$ = g_pending_call_new($1.cstring, $1.len, NULL, 0); } - | NAME "(" ")" { $$ = g_pending_call_new($1.cstring, $1.len, NULL, 0); } +item_chain : NAME { $$ = g_named_access_new(&$1); } + | NAME "(" ")" { $$ = g_pending_call_new(&$1, NULL, 0); } | NAME "(" call_args ")" { size_t __i; - $$ = g_pending_call_new($1.cstring, $1.len, $3.args, $3.count); + $$ = g_pending_call_new(&$1, $3.args, $3.count); for (__i = 0; __i < $3.count; __i++) g_object_unref(G_OBJECT($3.args[__i])); free($3.args); } - | callable "." NAME + | item_chain "." NAME { GScanExpression *__next; - __next = g_pending_call_new($3.cstring, $3.len, NULL, 0); - g_pending_call_attach_next(G_PENDING_CALL($1), G_PENDING_CALL(__next)); + __next = g_named_access_new(&$3); + g_named_access_attach_next(G_NAMED_ACCESS($1), G_NAMED_ACCESS(__next)); $$ = $1; } - | callable "." NAME "(" ")" + | item_chain "." NAME "(" ")" { GScanExpression *__next; - __next = g_pending_call_new($3.cstring, $3.len, NULL, 0); - g_pending_call_attach_next(G_PENDING_CALL($1), G_PENDING_CALL(__next)); + __next = g_pending_call_new(&$3, NULL, 0); + g_named_access_attach_next(G_NAMED_ACCESS($1), G_NAMED_ACCESS(__next)); $$ = $1; } - | callable "." NAME "(" call_args ")" + | item_chain "." NAME "(" call_args ")" { GScanExpression *__next; size_t __i; - __next = g_pending_call_new($3.cstring, $3.len, $5.args, $5.count); + __next = g_pending_call_new(&$3, $5.args, $5.count); for (__i = 0; __i < $5.count; __i++) g_object_unref(G_OBJECT($5.args[__i])); free($5.args); - g_pending_call_attach_next(G_PENDING_CALL($1), G_PENDING_CALL(__next)); + g_named_access_attach_next(G_NAMED_ACCESS($1), G_NAMED_ACCESS(__next)); $$ = $1; } ; diff --git a/src/analysis/scan/item-int.h b/src/analysis/scan/item-int.h index d1151f2..0ec4e46 100644 --- a/src/analysis/scan/item-int.h +++ b/src/analysis/scan/item-int.h @@ -32,11 +32,17 @@ -/* Lance une résolution d'élément à appeler. */ -typedef GRegisteredItem * (* resolve_registered_item_fc) (GRegisteredItem *, const char *, GScanContext *, GScanExpression **, size_t, bool, bool); +/* Indique le nom associé à une expression d'évaluation. */ +typedef char * (* get_registered_item_name_fc) (const GRegisteredItem *); + +/* Lance une résolution d'élément à solliciter. */ +typedef bool (* resolve_registered_item_fc) (GRegisteredItem *, const char *, GScanContext *, GScanScope *, GRegisteredItem **); /* Réduit une expression à une forme plus simple. */ -typedef GScanExpression * (* reduce_registered_item_fc) (GRegisteredItem *, GScanContext *, GScanExpression **, size_t, bool); +typedef bool (* reduce_registered_item_fc) (GRegisteredItem *, GScanContext *, GScanScope *, GScanExpression **); + +/* Effectue un appel à une fonction enregistrée. */ +typedef bool (* run_registered_item_call_fc) (GRegisteredItem *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); /* Expression d'évaluation généraliste (instance) */ @@ -51,8 +57,10 @@ struct _GRegisteredItemClass { GObjectClass parent; /* A laisser en premier */ + get_registered_item_name_fc get_name; /* Obtention du nom associé */ resolve_registered_item_fc resolve; /* Opération de résolution */ reduce_registered_item_fc reduce; /* Opération de réduction */ + run_registered_item_call_fc run_call; /* Appel à une fonction connue */ }; diff --git a/src/analysis/scan/item.c b/src/analysis/scan/item.c index c0b1532..d819f59 100644 --- a/src/analysis/scan/item.c +++ b/src/analysis/scan/item.c @@ -24,6 +24,9 @@ #include "item.h" +#include <assert.h> + + #include "item-int.h" @@ -136,33 +139,67 @@ static void g_registered_item_finalize(GRegisteredItem *item) /****************************************************************************** * * +* Paramètres : item = élément d'appel à consulter. * +* * +* Description : Indique le nom associé à une expression d'évaluation. * +* * +* Retour : Désignation humaine de l'expression d'évaluation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *g_registered_item_get_name(const GRegisteredItem *item) +{ + char *result; /* Désignation à retourner */ + GRegisteredItemClass *class; /* Classe à activer */ + + class = G_REGISTERED_ITEM_GET_CLASS(item); + + result = class->get_name(item); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : item = élément d'appel à consulter. * * target = désignation de l'objet d'appel à identifier. * * ctx = contexte de suivi de l'analyse courante. * -* args = liste d'éventuels arguments fournis. * -* count = taille de cette liste. * -* last = l'élément est-il le dernier d'une chaîne d'appels ? * -* final = indique une ultime conversion dans le cycle en cours.* +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la résolution opérée. [OUT]* * * -* Description : Lance une résolution d'élément à appeler. * +* Description : Lance une résolution d'élément à solliciter. * * * -* Retour : Nouvel élément d'appel identifié ou NULL. * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * * Remarques : - * * * ******************************************************************************/ -GRegisteredItem *g_registered_item_resolve(GRegisteredItem *item, const char *target, GScanContext *ctx, GScanExpression **args, size_t count, bool last, bool final) +bool g_registered_item_resolve(GRegisteredItem *item, const char *target, GScanContext *ctx, GScanScope *scope, GRegisteredItem **out) { - GRegisteredItem *result; /* Instance à renvoyer */ + bool result; /* Bilan à retourner */ GRegisteredItemClass *class; /* Classe à activer */ + *out = NULL; + class = G_REGISTERED_ITEM_GET_CLASS(item); if (class->resolve == NULL) - result = NULL; + result = false; else - result = class->resolve(item, target, ctx, args, count, last, final); + { + result = class->resolve(item, target, ctx, scope, out); + +#ifndef NDEBUG + if (*out != NULL) + assert(result); +#endif + + } return result; @@ -171,28 +208,84 @@ GRegisteredItem *g_registered_item_resolve(GRegisteredItem *item, const char *ta /****************************************************************************** * * -* Paramètres : item = élément d'appel à consulter. * -* ctx = contexte de suivi de l'analyse courante. * -* args = liste d'éventuels arguments fournis. * -* count = taille de cette liste. * -* final = indique une ultime conversion dans le cycle en cours.* +* Paramètres : item = élément d'appel à consulter. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la réduction opérée. [OUT] * * * * Description : Réduit une expression à une forme plus simple. * * * -* Retour : Réduction correspondante, expression déjà réduite, ou NULL. * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * * Remarques : - * * * ******************************************************************************/ -GScanExpression *g_registered_item_reduce(GRegisteredItem *item, GScanContext *ctx, GScanExpression **args, size_t count, bool final) +bool g_registered_item_reduce(GRegisteredItem *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - GScanExpression *result; /* Instance à renvoyer */ + bool result; /* Bilan à retourner */ GRegisteredItemClass *class; /* Classe à activer */ + *out = NULL; + class = G_REGISTERED_ITEM_GET_CLASS(item); - result = class->reduce(item, ctx, args, count, final); + if (class->reduce == NULL) + result = false; + else + { + result = class->reduce(item, ctx, scope, out); + +#ifndef NDEBUG + if (*out != NULL) + assert(result); +#endif + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * +* args = liste d'éventuels arguments fournis. * +* count = taille de cette liste. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la résolution opérée. [OUT] * +* * +* Description : Effectue un appel à une fonction enregistrée. * +* * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_registered_item_run_call(GRegisteredItem *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out) +{ + bool result; /* Bilan à retourner */ + GRegisteredItemClass *class; /* Classe à activer */ + + *out = NULL; + + class = G_REGISTERED_ITEM_GET_CLASS(item); + + if (class->run_call == NULL) + result = false; + else + { + result = class->run_call(item, args, count, ctx, scope, out); + +#ifndef NDEBUG + if (*out != NULL) + assert(result); +#endif + + } return result; diff --git a/src/analysis/scan/item.h b/src/analysis/scan/item.h index e3e02e6..fee1e2c 100644 --- a/src/analysis/scan/item.h +++ b/src/analysis/scan/item.h @@ -52,11 +52,17 @@ typedef struct _GRegisteredItemClass GRegisteredItemClass; /* Indique le type défini pour un élément appelable et enregistré. */ GType g_registered_item_get_type(void); -/* Lance une résolution d'élément à appeler. */ -GRegisteredItem *g_registered_item_resolve(GRegisteredItem *, const char *, GScanContext *, GScanExpression **, size_t, bool, bool); +/* Indique le nom associé à une expression d'évaluation. */ +char *g_registered_item_get_name(const GRegisteredItem *); + +/* Lance une résolution d'élément à solliciter. */ +bool g_registered_item_resolve(GRegisteredItem *, const char *, GScanContext *, GScanScope *, GRegisteredItem **); /* Réduit une expression à une forme plus simple. */ -GScanExpression *g_registered_item_reduce(GRegisteredItem *, GScanContext *, GScanExpression **, size_t, bool); +bool g_registered_item_reduce(GRegisteredItem *, GScanContext *, GScanScope *, GScanExpression **); + +/* Effectue un appel à une fonction enregistrée. */ +bool g_registered_item_run_call(GRegisteredItem *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); diff --git a/src/analysis/scan/items/Makefile.am b/src/analysis/scan/items/Makefile.am new file mode 100644 index 0000000..3a6bb62 --- /dev/null +++ b/src/analysis/scan/items/Makefile.am @@ -0,0 +1,15 @@ + +noinst_LTLIBRARIES = libanalysisscanitems.la + + +libanalysisscanitems_la_SOURCES = \ + datasize.h datasize.c \ + uint-int.h \ + uint.h uint.c + +libanalysisscanitems_la_CFLAGS = $(LIBGOBJ_CFLAGS) + + +devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) + +dev_HEADERS = $(libanalysisscanitems_la_SOURCES:%c=) diff --git a/src/analysis/scan/funcs/datasize.c b/src/analysis/scan/items/datasize.c index 7e63095..618d0c3 100644 --- a/src/analysis/scan/funcs/datasize.c +++ b/src/analysis/scan/items/datasize.c @@ -24,7 +24,7 @@ #include "datasize.h" -#include "../func-int.h" +#include "../item-int.h" #include "../exprs/literal.h" @@ -49,8 +49,14 @@ static void g_datasize_function_finalize(GDatasizeFunction *); /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ +/* Indique le nom associé à une expression d'évaluation. */ +static char *g_datasize_function_get_name(const GDatasizeFunction *); + +/* Réduit une expression à une forme plus simple. */ +static bool g_datasize_function_reduce(GDatasizeFunction *, GScanContext *, GScanScope *, GScanExpression **); + /* Réduit une expression à une forme plus simple. */ -static GScanExpression *g_datasize_function_reduce(GDatasizeFunction *, GScanContext *, GScanExpression **, size_t, bool); +static bool g_datasize_function_run_call(GDatasizeFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); @@ -60,7 +66,7 @@ static GScanExpression *g_datasize_function_reduce(GDatasizeFunction *, GScanCon /* Indique le type défini pour une mesure de quantité de données scannées. */ -G_DEFINE_TYPE(GDatasizeFunction, g_datasize_function, G_TYPE_SCAN_FUNCTION); +G_DEFINE_TYPE(GDatasizeFunction, g_datasize_function, G_TYPE_REGISTERED_ITEM); /****************************************************************************** @@ -87,7 +93,9 @@ static void g_datasize_function_class_init(GDatasizeFunctionClass *klass) registered = G_REGISTERED_ITEM_CLASS(klass); + registered->get_name = (get_registered_item_name_fc)g_datasize_function_get_name; registered->reduce = (reduce_registered_item_fc)g_datasize_function_reduce; + registered->run_call = (run_registered_item_call_fc)g_datasize_function_run_call; } @@ -160,9 +168,9 @@ static void g_datasize_function_finalize(GDatasizeFunction *func) * * ******************************************************************************/ -GScanFunction *g_datasize_function_new(void) +GDatasizeFunction *g_datasize_function_new(void) { - GScanFunction *result; /* Structure à retourner */ + GDatasizeFunction *result; /* Structure à retourner */ result = g_object_new(G_TYPE_DATASIZE_FUNCTION, NULL); @@ -179,36 +187,86 @@ GScanFunction *g_datasize_function_new(void) /****************************************************************************** * * -* Paramètres : func = élément d'appel à consulter. * -* target = désignation de l'objet d'appel à identifier. * -* ctx = contexte de suivi de l'analyse courante. * -* args = liste d'éventuels arguments fournis. * -* count = taille de cette liste. * -* last = l'élément est-il le dernier d'une chaîne d'appels ? * -* final = indique une ultime conversion dans le cycle en cours.* +* Paramètres : item = élément d'appel à consulter. * +* * +* Description : Indique le nom associé à une expression d'évaluation. * +* * +* Retour : Désignation humaine de l'expression d'évaluation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_datasize_function_get_name(const GDatasizeFunction *item) +{ + char *result; /* Désignation à retourner */ + + result = strdup("datasize"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la réduction opérée. [OUT] * * * * Description : Réduit une expression à une forme plus simple. * * * -* Retour : Réduction correspondante, expression déjà réduite, ou NULL. * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * * Remarques : - * * * ******************************************************************************/ -static GScanExpression *g_datasize_function_reduce(GDatasizeFunction *func, GScanContext *ctx, GScanExpression **args, size_t count, bool final) +static bool g_datasize_function_reduce(GDatasizeFunction *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - GScanExpression *result; /* Instance à renvoyer */ + bool result; /* Bilan à retourner */ GBinContent *content; /* Contenu à manipuler */ phys_t size; /* Quantité de données liées */ + result = true; + content = g_scan_context_get_content(ctx); size = g_binary_content_compute_size(content); - result = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ size }); + *out = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ size }); g_object_unref(G_OBJECT(content)); return result; } + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * +* args = liste d'éventuels arguments fournis. * +* count = taille de cette liste. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la résolution opérée. [OUT] * +* * +* Description : Réduit une expression à une forme plus simple. * +* * +* Retour : Réduction correspondante, expression déjà réduite, ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_datasize_function_run_call(GDatasizeFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out) +{ + bool result; /* Bilan à retourner */ + + result = g_datasize_function_reduce(item, ctx, scope, (GScanExpression **)out); + + return result; + +} diff --git a/src/analysis/scan/funcs/datasize.h b/src/analysis/scan/items/datasize.h index bdd813d..bd8e185 100644 --- a/src/analysis/scan/funcs/datasize.h +++ b/src/analysis/scan/items/datasize.h @@ -21,11 +21,14 @@ */ -#ifndef _ANALYSIS_SCAN_FUNCS_DATASIZE_H -#define _ANALYSIS_SCAN_FUNCS_DATASIZE_H +#ifndef _ANALYSIS_SCAN_ITEMS_DATASIZE_H +#define _ANALYSIS_SCAN_ITEMS_DATASIZE_H -#include "../func.h" +#include <glib-object.h> + + +#include "../item.h" @@ -38,18 +41,18 @@ /* Mesure de la quantité de données scannées (instance) */ -typedef GScanFunction GDatasizeFunction; +typedef GRegisteredItem GDatasizeFunction; /* Mesure de la quantité de données scannées (classe) */ -typedef GScanFunctionClass GDatasizeFunctionClass; +typedef GRegisteredItemClass GDatasizeFunctionClass; /* Indique le type défini pour une mesure de quantité de données scannées. */ GType g_datasize_function_get_type(void); /* Constitue une fonction de récupération de taille de données. */ -GScanFunction *g_datasize_function_new(void); +GDatasizeFunction *g_datasize_function_new(void); -#endif /* _ANALYSIS_SCAN_FUNCS_DATASIZE_H */ +#endif /* _ANALYSIS_SCAN_ITEMS_DATASIZE_H */ diff --git a/src/analysis/scan/funcs/uint-int.h b/src/analysis/scan/items/uint-int.h index 0817805..1fa83c5 100644 --- a/src/analysis/scan/funcs/uint-int.h +++ b/src/analysis/scan/items/uint-int.h @@ -21,21 +21,21 @@ */ -#ifndef _ANALYSIS_SCAN_FUNCS_UINT_INT_H -#define _ANALYSIS_SCAN_FUNCS_UINT_INT_H +#ifndef _ANALYSIS_SCAN_ITEMS_UINT_INT_H +#define _ANALYSIS_SCAN_ITEMS_UINT_INT_H #include "uint.h" -#include "../func-int.h" +#include "../item-int.h" /* Fonction conduisant à la lecture d'un mot (instance) */ struct _GUintFunction { - GScanFunction parent; /* A laisser en premier */ + GRegisteredItem parent; /* A laisser en premier */ MemoryDataSize size; /* Taille du mot à lire */ SourceEndian endian; /* Boutisme à respecter */ @@ -45,10 +45,14 @@ struct _GUintFunction /* Fonction conduisant à la lecture d'un mot (classe) */ struct _GUintFunctionClass { - GScanFunctionClass parent; /* A laisser en premier */ + GRegisteredItemClass parent; /* A laisser en premier */ }; +/* Met en place un nouvelle fonction de lecture d'entiers. */ +bool g_uint_function_create(GUintFunction *, MemoryDataSize); -#endif /* _ANALYSIS_SCAN_FUNCS_UINT_INT_H */ + + +#endif /* _ANALYSIS_SCAN_ITEMS_UINT_INT_H */ diff --git a/src/analysis/scan/funcs/uint.c b/src/analysis/scan/items/uint.c index 6421f52..4fea494 100644 --- a/src/analysis/scan/funcs/uint.c +++ b/src/analysis/scan/items/uint.c @@ -24,6 +24,9 @@ #include "uint.h" +#include <assert.h> + + #include "uint-int.h" #include "../exprs/literal.h" @@ -49,8 +52,11 @@ static void g_uint_function_finalize(GUintFunction *); /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ +/* Indique le nom associé à une expression d'évaluation. */ +static char *g_uint_function_get_name(const GUintFunction *); + /* Réduit une expression à une forme plus simple. */ -static GScanExpression *g_uint_function_reduce(GUintFunction *, GScanContext *, GScanExpression **, size_t, bool); +static bool g_uint_function_run_call(GUintFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); @@ -60,7 +66,7 @@ static GScanExpression *g_uint_function_reduce(GUintFunction *, GScanContext *, /* Indique le type défini pour une lecture de mot à partir de données binaires. */ -G_DEFINE_TYPE(GUintFunction, g_uint_function, G_TYPE_SCAN_FUNCTION); +G_DEFINE_TYPE(GUintFunction, g_uint_function, G_TYPE_REGISTERED_ITEM); /****************************************************************************** @@ -87,7 +93,8 @@ static void g_uint_function_class_init(GUintFunctionClass *klass) registered = G_REGISTERED_ITEM_CLASS(klass); - registered->reduce = (reduce_registered_item_fc)g_uint_function_reduce; + registered->get_name = (get_registered_item_name_fc)g_uint_function_get_name; + registered->run_call = (run_registered_item_call_fc)g_uint_function_run_call; } @@ -162,13 +169,40 @@ static void g_uint_function_finalize(GUintFunction *func) * * ******************************************************************************/ -GScanFunction *g_uint_function_new(MemoryDataSize size) +GUintFunction *g_uint_function_new(MemoryDataSize size) { - GScanFunction *result; /* Structure à retourner */ + GUintFunction *result; /* Structure à retourner */ result = g_object_new(G_TYPE_UINT_FUNCTION, NULL); - G_UINT_FUNCTION(result)->size = size; + if (!g_uint_function_create(result, size)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : func = encadrement d'un parcours de correspondances. * +* size = taille du mot à venir lire dans les données. * +* * +* Description : Met en place un nouvelle fonction de lecture d'entiers. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_uint_function_create(GUintFunction *func, MemoryDataSize size) +{ + bool result; /* Bilan à retourner */ + + result = true; + + func->size = size; return result; @@ -183,13 +217,58 @@ GScanFunction *g_uint_function_new(MemoryDataSize size) /****************************************************************************** * * -* Paramètres : func = élément d'appel à consulter. * -* target = désignation de l'objet d'appel à identifier. * -* ctx = contexte de suivi de l'analyse courante. * -* args = liste d'éventuels arguments fournis. * -* count = taille de cette liste. * -* last = l'élément est-il le dernier d'une chaîne d'appels ? * -* final = indique une ultime conversion dans le cycle en cours.* +* Paramètres : item = élément d'appel à consulter. * +* * +* Description : Indique le nom associé à une expression d'évaluation. * +* * +* Retour : Désignation humaine de l'expression d'évaluation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_uint_function_get_name(const GUintFunction *item) +{ + char *result; /* Désignation à retourner */ + + switch (item->size) + { + case MDS_8_BITS_UNSIGNED: + result = strdup("uint8"); + break; + + case MDS_16_BITS_UNSIGNED: + result = strdup("uint16"); + break; + + case MDS_32_BITS_UNSIGNED: + result = strdup("uint32"); + break; + + case MDS_64_BITS_UNSIGNED: + result = strdup("uint64"); + break; + + default: + assert(false); + result = NULL; + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * +* args = liste d'éventuels arguments fournis. * +* count = taille de cette liste. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la résolution opérée. [OUT] * * * * Description : Réduit une expression à une forme plus simple. * * * @@ -199,11 +278,10 @@ GScanFunction *g_uint_function_new(MemoryDataSize size) * * ******************************************************************************/ -static GScanExpression *g_uint_function_reduce(GUintFunction *func, GScanContext *ctx, GScanExpression **args, size_t count, bool final) +static bool g_uint_function_run_call(GUintFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out) { - GScanExpression *result; /* Instance à renvoyer */ + bool result; /* Bilan à retourner */ unsigned long long offset; /* Position du mot ciblé */ - bool status; /* Bilan d'une opération */ GBinContent *content; /* Contenu à manipuler */ vmpa2t pos; /* Tête de lecture */ uint8_t val_8; /* Valeur entière sur 8 bits */ @@ -211,54 +289,51 @@ static GScanExpression *g_uint_function_reduce(GUintFunction *func, GScanContext uint32_t val_32; /* Valeur entière sur 32 bits */ uint64_t val_64; /* Valeur entière sur 64 bits */ - result = NULL; - - if (count == 1 && G_IS_LITERAL_EXPRESSION(args[0])) - { - status = g_literal_expression_get_integer_value(G_LITERAL_EXPRESSION(args[0]), &offset); - if (!status) goto exit; - - content = g_scan_context_get_content(ctx); - - g_binary_content_compute_start_pos(content, &pos); - advance_vmpa(&pos, offset); + result = (count == 1 && G_IS_LITERAL_EXPRESSION(args[0])); + if (!result) goto exit; - switch (func->size) - { - case MDS_8_BITS_UNSIGNED: - status = g_binary_content_read_u8(content, &pos, &val_8); - if (status) - result = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_8 }); - break; + result = g_literal_expression_get_integer_value(G_LITERAL_EXPRESSION(args[0]), &offset); + if (!result) goto exit; - case MDS_16_BITS_UNSIGNED: - status = g_binary_content_read_u16(content, &pos, func->endian, &val_16); - if (status) - result = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_16 }); - break; + content = g_scan_context_get_content(ctx); - case MDS_32_BITS_UNSIGNED: - status = g_binary_content_read_u32(content, &pos, func->endian, &val_32); - if (status) - result = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_32 }); - break; + g_binary_content_compute_start_pos(content, &pos); + advance_vmpa(&pos, offset); - - case MDS_64_BITS_UNSIGNED: - status = g_binary_content_read_u64(content, &pos, func->endian, &val_64); - if (status) - result = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_64 }); - break; - - default: - break; - - } - - g_object_unref(G_OBJECT(content)); + switch (item->size) + { + case MDS_8_BITS_UNSIGNED: + result = g_binary_content_read_u8(content, &pos, &val_8); + if (result) + *out = G_OBJECT(g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_8 })); + break; + + case MDS_16_BITS_UNSIGNED: + result = g_binary_content_read_u16(content, &pos, item->endian, &val_16); + if (result) + *out = G_OBJECT(g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_16 })); + break; + + case MDS_32_BITS_UNSIGNED: + result = g_binary_content_read_u32(content, &pos, item->endian, &val_32); + if (result) + *out = G_OBJECT(g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_32 })); + break; + + + case MDS_64_BITS_UNSIGNED: + result = g_binary_content_read_u64(content, &pos, item->endian, &val_64); + if (result) + *out = G_OBJECT(g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_64 })); + break; + + default: + break; } + g_object_unref(G_OBJECT(content)); + exit: return result; diff --git a/src/analysis/scan/funcs/uint.h b/src/analysis/scan/items/uint.h index fe6cb52..60f2975 100644 --- a/src/analysis/scan/funcs/uint.h +++ b/src/analysis/scan/items/uint.h @@ -21,11 +21,13 @@ */ -#ifndef _ANALYSIS_SCAN_FUNCS_UINT_H -#define _ANALYSIS_SCAN_FUNCS_UINT_H +#ifndef _ANALYSIS_SCAN_ITEMS_UINT_H +#define _ANALYSIS_SCAN_ITEMS_UINT_H + + +#include <glib-object.h> -#include "../func.h" #include "../../../arch/archbase.h" @@ -49,8 +51,8 @@ typedef struct _GUintFunctionClass GUintFunctionClass; GType g_uint_function_get_type(void); /* Constitue une fonction de lecture de valeur entière. */ -GScanFunction *g_uint_function_new(MemoryDataSize); +GUintFunction *g_uint_function_new(MemoryDataSize); -#endif /* _ANALYSIS_SCAN_FUNCS_UINT_H */ +#endif /* _ANALYSIS_SCAN_ITEMS_UINT_H */ diff --git a/src/analysis/scan/patterns/backend-int.h b/src/analysis/scan/patterns/backend-int.h index 698ba5f..b2587df 100644 --- a/src/analysis/scan/patterns/backend-int.h +++ b/src/analysis/scan/patterns/backend-int.h @@ -39,7 +39,7 @@ typedef patid_t (* enroll_plain_into_backend_fc) (GEngineBackend *, GScanContext typedef void (* warm_up_backend_fc) (GEngineBackend *); /* Parcours un contenu binaire à la recherche de motifs. */ -typedef void (* run_backend_scan_fc) (const GEngineBackend *, GScanContext *, GBinContent *); +typedef void (* run_backend_scan_fc) (const GEngineBackend *, GScanContext *); /* Imprime quelques faits quant aux éléments mis en place. */ typedef void (* output_backend_stats_fc) (const GEngineBackend *); diff --git a/src/analysis/scan/patterns/backend.c b/src/analysis/scan/patterns/backend.c index 800d0aa..0ecc7fe 100644 --- a/src/analysis/scan/patterns/backend.c +++ b/src/analysis/scan/patterns/backend.c @@ -209,7 +209,6 @@ void g_engine_backend_warm_up(GEngineBackend *backend) * * * Paramètres : backend = moteur de recherche à manipuler. * * context = lieu d'enregistrement des résultats. * -* content = données binaires à analyser. * * * * Description : Parcours un contenu binaire à la recherche de motifs. * * * @@ -219,13 +218,13 @@ void g_engine_backend_warm_up(GEngineBackend *backend) * * ******************************************************************************/ -void g_engine_backend_run_scan(const GEngineBackend *backend, GScanContext *context, GBinContent *content) +void g_engine_backend_run_scan(const GEngineBackend *backend, GScanContext *context) { GEngineBackendClass *class; /* Classe à activer */ class = G_ENGINE_BACKEND_GET_CLASS(backend); - class->run_scan(backend, context, content); + class->run_scan(backend, context); } diff --git a/src/analysis/scan/patterns/backend.h b/src/analysis/scan/patterns/backend.h index 700366e..8f6b929 100644 --- a/src/analysis/scan/patterns/backend.h +++ b/src/analysis/scan/patterns/backend.h @@ -63,7 +63,7 @@ patid_t g_engine_backend_enroll_plain_pattern(GEngineBackend *, GScanContext *, void g_engine_backend_warm_up(GEngineBackend *); /* Parcours un contenu binaire à la recherche de motifs. */ -void g_engine_backend_run_scan(const GEngineBackend *, GScanContext *, GBinContent *); +void g_engine_backend_run_scan(const GEngineBackend *, GScanContext *); /* Imprime quelques faits quant aux éléments mis en place. */ void g_engine_backend_output_stats(const GEngineBackend *); diff --git a/src/analysis/scan/patterns/backends/acism.c b/src/analysis/scan/patterns/backends/acism.c index 12339f2..eef681a 100644 --- a/src/analysis/scan/patterns/backends/acism.c +++ b/src/analysis/scan/patterns/backends/acism.c @@ -96,7 +96,7 @@ static void g_acism_backend_build_interleave_array(GAcismBackend *); static void g_acism_backend_warm_up(GAcismBackend *); /* Parcours un contenu binaire à la recherche de motifs. */ -static void g_acism_backend_run_scan(const GAcismBackend *, GScanContext *, GBinContent *); +static void g_acism_backend_run_scan(const GAcismBackend *, GScanContext *); /* Affiche les caractéristques d'un noeud et de ses enfants. */ static void visit_and_output_node(const acism_trie_node_t *, unsigned int); @@ -1125,7 +1125,6 @@ static void g_acism_backend_warm_up(GAcismBackend *backend) * * * Paramètres : backend = moteur de recherche à manipuler. * * context = lieu d'enregistrement des résultats. * -* content = données binaires à analyser. * * * * Description : Parcours un contenu binaire à la recherche de motifs. * * * @@ -1135,8 +1134,9 @@ static void g_acism_backend_warm_up(GAcismBackend *backend) * * ******************************************************************************/ -static void g_acism_backend_run_scan(const GAcismBackend *backend, GScanContext *context, GBinContent *content) +static void g_acism_backend_run_scan(const GAcismBackend *backend, GScanContext *context) { + GBinContent *content; /* Contenu binaire manipulé */ phys_t dlen; /* Quantité de données */ vmpa2t pos; /* Point de départ ciblé */ const bin_t *data; /* Données à analyser */ @@ -1151,6 +1151,8 @@ static void g_acism_backend_run_scan(const GAcismBackend *backend, GScanContext acism_state_t *iter; /* Boucle de parcours #2 */ acism_state_t *test; /* Test de validité alternative*/ + content = g_scan_context_get_content(context); + dlen = g_binary_content_compute_size(content); g_binary_content_compute_start_pos(content, &pos); @@ -1238,6 +1240,8 @@ static void g_acism_backend_run_scan(const GAcismBackend *backend, GScanContext } + g_object_unref(G_OBJECT(content)); + } diff --git a/src/analysis/scan/patterns/backends/bitap.c b/src/analysis/scan/patterns/backends/bitap.c index bd80fb0..adf66d6 100644 --- a/src/analysis/scan/patterns/backends/bitap.c +++ b/src/analysis/scan/patterns/backends/bitap.c @@ -63,7 +63,7 @@ size_t g_bitap_backend_get_atom_max_size(const GBitapBackend *); static patid_t g_bitap_backend_enroll_plain_pattern(GBitapBackend *, GScanContext *, const uint8_t *, size_t); /* Parcours un contenu binaire à la recherche de motifs. */ -static void g_bitap_backend_run_scan(const GBitapBackend *, GScanContext *, GBinContent *); +static void g_bitap_backend_run_scan(const GBitapBackend *, GScanContext *); /* Imprime quelques faits quant aux éléments mis en place. */ static void g_bitap_backend_output_stats(const GBitapBackend *); @@ -80,7 +80,7 @@ static void extend_grouped_strings_avx2(grouped_strings_avx2_t ***, size_t *); static patid_t enroll_plain_pattern_avx2(GBitapBackend *, GScanContext *, const bin_t *, size_t); /* Parcours un contenu binaire à la recherche de motifs. */ -static void run_scan_avx2(const GBitapBackend *, GScanContext *, GBinContent *); +static void run_scan_avx2(const GBitapBackend *, GScanContext *, const bin_t *, phys_t); @@ -96,7 +96,7 @@ static void extend_grouped_strings_avx512(grouped_strings_avx512_t ***, size_t * static patid_t enroll_plain_pattern_avx512(GBitapBackend *, GScanContext *, const bin_t *, size_t); /* Parcours un contenu binaire à la recherche de motifs. */ -static void run_scan_avx512(const GBitapBackend *, GScanContext *, GBinContent *); +static void run_scan_avx512(const GBitapBackend *, GScanContext *, const bin_t *, phys_t); @@ -295,7 +295,6 @@ static patid_t g_bitap_backend_enroll_plain_pattern(GBitapBackend *backend, GSca * * * Paramètres : backend = moteur de recherche à manipuler. * * context = lieu d'enregistrement des résultats. * -* content = données binaires à analyser. * * * * Description : Parcours un contenu binaire à la recherche de motifs. * * * @@ -305,12 +304,16 @@ static patid_t g_bitap_backend_enroll_plain_pattern(GBitapBackend *backend, GSca * * ******************************************************************************/ -static void g_bitap_backend_run_scan(const GBitapBackend *backend, GScanContext *context, GBinContent *content) +static void g_bitap_backend_run_scan(const GBitapBackend *backend, GScanContext *context) { cpu_set_t old_mask; /* Cartographie des CPU #1 */ int ret; /* Bilan d'un appel */ unsigned int cpu; /* Processeur courant */ cpu_set_t new_mask; /* Cartographie des CPU #2 */ + GBinContent *content; /* Contenu binaire manipulé */ + phys_t dlen; /* Quantité de données */ + vmpa2t pos; /* Point de départ ciblé */ + const bin_t *data; /* Données à analyser */ ret = sched_getaffinity(0, sizeof(cpu_set_t), &old_mask); @@ -339,16 +342,24 @@ static void g_bitap_backend_run_scan(const GBitapBackend *backend, GScanContext goto exit; } + content = g_scan_context_get_content(context); + + dlen = g_binary_content_compute_size(content); + + g_binary_content_compute_start_pos(content, &pos); + data = g_binary_content_get_raw_access(content, &pos, dlen); + assert(data != NULL); if (0) - run_scan_avx2(backend, context, content); + run_scan_avx2(backend, context, data, dlen); else - run_scan_avx512(backend, context, content); + run_scan_avx512(backend, context, data, dlen); + g_object_unref(G_OBJECT(content)); exit: @@ -515,7 +526,8 @@ static patid_t enroll_plain_pattern_avx2(GBitapBackend *backend, GScanContext *c * * * Paramètres : backend = moteur de recherche à manipuler. * * context = lieu d'enregistrement des résultats. * -* content = données binaires à analyser. * +* data = données à analyser. * +* dlen = quantité de ces données. * * * * Description : Parcours un contenu binaire à la recherche de motifs. * * * @@ -525,12 +537,9 @@ static patid_t enroll_plain_pattern_avx2(GBitapBackend *backend, GScanContext *c * * ******************************************************************************/ -static void run_scan_avx2(const GBitapBackend *backend, GScanContext *context, GBinContent *content) +static void run_scan_avx2(const GBitapBackend *backend, GScanContext *context, const bin_t *data, phys_t dlen) { const group_manager_avx2_t *manager; /* Accès simplifié */ - phys_t dlen; /* Quantité de données */ - vmpa2t pos; /* Point de départ ciblé */ - const bin_t *data; /* Données à analyser */ register __m256i zero asm("ymm11"); /* Constante 0 sur 256 bits */ size_t k; /* Boucle de parcours #1 */ @@ -570,11 +579,6 @@ static void run_scan_avx2(const GBitapBackend *backend, GScanContext *context, G manager = &backend->manager_avx2; - dlen = g_binary_content_compute_size(content); - - g_binary_content_compute_start_pos(content, &pos); - data = g_binary_content_get_raw_access(content, &pos, dlen); - zero = _mm256_set1_epi16(0); asm volatile ("nop;nop;nop;nop;nop;nop;nop;nop;nop;"); @@ -1622,7 +1626,8 @@ static patid_t enroll_plain_pattern_avx512(GBitapBackend *backend, GScanContext * * * Paramètres : backend = moteur de recherche à manipuler. * * context = lieu d'enregistrement des résultats. * -* content = données binaires à analyser. * +* data = données à analyser. * +* dlen = quantité de ces données. * * * * Description : Parcours un contenu binaire à la recherche de motifs. * * * @@ -1632,12 +1637,9 @@ static patid_t enroll_plain_pattern_avx512(GBitapBackend *backend, GScanContext * * ******************************************************************************/ -static void run_scan_avx512(const GBitapBackend *backend, GScanContext *context, GBinContent *content) +static void run_scan_avx512(const GBitapBackend *backend, GScanContext *context, const bin_t *data, phys_t dlen) { const group_manager_avx512_t *manager; /* Accès simplifié */ - phys_t dlen; /* Quantité de données */ - vmpa2t pos; /* Point de départ ciblé */ - const bin_t *data; /* Données à analyser */ //register __m512i zero asm("zmm19"); /* Constante 0 sur 512 bits */ @@ -1674,10 +1676,6 @@ static void run_scan_avx512(const GBitapBackend *backend, GScanContext *context, manager = &backend->manager_avx512; - dlen = g_binary_content_compute_size(content); - - g_binary_content_compute_start_pos(content, &pos); - data = g_binary_content_get_raw_access(content, &pos, dlen); diff --git a/src/analysis/scan/rule.c b/src/analysis/scan/rule.c index 6c771fb..bf37585 100644 --- a/src/analysis/scan/rule.c +++ b/src/analysis/scan/rule.c @@ -338,7 +338,7 @@ bool g_scan_rule_setup_backend(GScanRule *rule, GEngineBackend *backend, GScanCo * * ******************************************************************************/ -void g_scan_rule_analyze(GScanRule *rule, GEngineBackend *backend, GScanContext *context) +void g_scan_rule_check(GScanRule *rule, GEngineBackend *backend, GScanContext *context) { GBinContent *content; /* Contenu à manipuler */ pending_matches_t matches; /* Suivi de correspondances */ @@ -350,8 +350,6 @@ void g_scan_rule_analyze(GScanRule *rule, GEngineBackend *backend, GScanContext content = g_scan_context_get_content(context); - g_engine_backend_run_scan(backend, context, content); - /* Consolidation des résultats */ for (i = 0; i < rule->data_used; i++) diff --git a/src/analysis/scan/rule.h b/src/analysis/scan/rule.h index edd57b3..e240da9 100644 --- a/src/analysis/scan/rule.h +++ b/src/analysis/scan/rule.h @@ -70,7 +70,7 @@ void g_scan_rule_set_match_condition(GScanRule *, GScanExpression *); bool g_scan_rule_setup_backend(GScanRule *, GEngineBackend *, GScanContext *); /* Lance une analyse d'un contenu binaire selon une règle. */ -void g_scan_rule_analyze(GScanRule *, GEngineBackend *, GScanContext *); +void g_scan_rule_check(GScanRule *, GEngineBackend *, GScanContext *); diff --git a/src/analysis/scan/scanner.c b/src/analysis/scan/scanner.c index ae3cb9a..d52c0fc 100644 --- a/src/analysis/scan/scanner.c +++ b/src/analysis/scan/scanner.c @@ -332,8 +332,10 @@ GScanContext *g_content_scanner_analyze(GContentScanner *scanner, GScanOptions * g_scan_context_set_content(result, content); + g_engine_backend_run_scan(scanner->data_backend, result); + for (i = 0; i < scanner->rule_count; i++) - g_scan_rule_analyze(scanner->rules[i], scanner->data_backend, result); + g_scan_rule_check(scanner->rules[i], scanner->data_backend, result); exit: diff --git a/src/analysis/scan/scope.h b/src/analysis/scan/scope.h new file mode 100644 index 0000000..1e5de2c --- /dev/null +++ b/src/analysis/scan/scope.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * scope.h - prototypes pour la définition d'une portée locale de variables + * + * Copyright (C) 2023 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_SCOPE_H +#define _ANALYSIS_SCAN_SCOPE_H + + + + + +typedef void *GScanScope; + + + + + +#endif /* _ANALYSIS_SCAN_SCOPE_H */ diff --git a/src/analysis/scan/space-int.h b/src/analysis/scan/space-int.h index fa4437d..386785d 100644 --- a/src/analysis/scan/space-int.h +++ b/src/analysis/scan/space-int.h @@ -37,6 +37,8 @@ struct _GScanNamespace { GRegisteredItem parent; /* A laisser en premier */ + char *name; /* Désignation de l'espace */ + GRegisteredItem **children; /* Sous-éléments inscrits */ char **names; /* Désignations correspondantes*/ size_t count; /* Quantité de sous-éléments */ @@ -51,5 +53,9 @@ struct _GScanNamespaceClass }; +/* Met en place un nouvel espace de noms pour scan. */ +bool g_scan_namespace_create(GScanNamespace *, const char *); + + #endif /* _ANALYSIS_SCAN_SPACE_INT_H */ diff --git a/src/analysis/scan/space.c b/src/analysis/scan/space.c index 34b67fe..dc9a237 100644 --- a/src/analysis/scan/space.c +++ b/src/analysis/scan/space.c @@ -52,11 +52,14 @@ static void g_scan_namespace_finalize(GScanNamespace *); /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ -/* Lance une résolution d'élément à appeler. */ -GRegisteredItem *g_scan_namespace_resolve(GScanNamespace *, const char *, GScanContext *, GScanExpression **, size_t, bool, bool); +/* Indique le nom associé à une expression d'évaluation. */ +static char *g_scan_namespace_get_name(const GScanNamespace *); + +/* Lance une résolution d'élément à solliciter. */ +static bool g_scan_namespace_resolve(GScanNamespace *, const char *, GScanContext *, GScanScope *, GRegisteredItem **); /* Réduit une expression à une forme plus simple. */ -GScanExpression *g_scan_namespace_reduce(GScanNamespace *, GScanContext *, GScanExpression **, size_t, bool); +static GScanExpression *g_scan_namespace_reduce(GScanNamespace *, GScanContext *, GScanExpression **, size_t, bool); @@ -93,6 +96,7 @@ static void g_scan_namespace_class_init(GScanNamespaceClass *klass) registered = G_REGISTERED_ITEM_CLASS(klass); + registered->get_name = (get_registered_item_name_fc)g_scan_namespace_get_name; registered->resolve = (resolve_registered_item_fc)g_scan_namespace_resolve; registered->reduce = (reduce_registered_item_fc)g_scan_namespace_reduce; @@ -113,6 +117,8 @@ static void g_scan_namespace_class_init(GScanNamespaceClass *klass) static void g_scan_namespace_init(GScanNamespace *space) { + space->name = NULL; + space->children = NULL; space->names = NULL; space->count = 0; @@ -160,6 +166,9 @@ static void g_scan_namespace_finalize(GScanNamespace *space) { size_t i; /* Boucle de parcours */ + if (space->name != NULL) + free(space->name); + if (space->children != NULL) free(space->children); @@ -176,7 +185,7 @@ static void g_scan_namespace_finalize(GScanNamespace *space) /****************************************************************************** * * -* Paramètres : - * +* Paramètres : name = désignation du futur espace de noms. * * * * Description : Construit un nouvel espace de noms pour scan. * * * @@ -186,12 +195,42 @@ static void g_scan_namespace_finalize(GScanNamespace *space) * * ******************************************************************************/ -GScanNamespace *g_scan_namespace_new(void) +GScanNamespace *g_scan_namespace_new(const char *name) { GScanNamespace *result; /* Instance à retourner */ result = g_object_new(G_TYPE_SCAN_NAMESPACE, NULL); + if (!g_scan_namespace_create(result, name)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : space = instance d'espace de noms à initialiser. * +* name = désignation du futur espace de noms. * +* * +* Description : Met en place un nouvel espace de noms pour scan. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_scan_namespace_create(GScanNamespace *space, const char *name) +{ + bool result; /* Bilan à retourner */ + + result = true; + + if (name != NULL) + space->name = strdup(name); + return result; } @@ -200,8 +239,7 @@ GScanNamespace *g_scan_namespace_new(void) /****************************************************************************** * * * Paramètres : space = espace de noms à compléter. * -* type = type d'élément à intégrer. * -* name = nom du futur espace ou NULL pour une racine. * +* child = élément d'évaluation à intégrer. * * * * Description : Intègre un nouvel élément dans l'esapce de noms. * * * @@ -211,19 +249,39 @@ GScanNamespace *g_scan_namespace_new(void) * * ******************************************************************************/ -bool g_scan_namespace_register(GScanNamespace *space, GRegisteredItem *child, const char *name) +bool g_scan_namespace_register_item(GScanNamespace *space, GRegisteredItem *child) { bool result; /* Bilan à retourner */ + char *name; /* Nom de l'élément à ajouter */ + size_t i; /* Boucle de parcours */ - result = true; + name = g_registered_item_get_name(child); + + /* Validation de l'unicité du nom */ + + for (i = 0; i < space->count; i++) + if (strcmp(name, space->names[i]) == 0) + break; - space->count++; + result = (i == space->count); - space->children = realloc(space->children, space->count * sizeof(GRegisteredItem *)); - space->children[space->count - 1] = child; + /* Inscription de l'élément ? */ - space->names = realloc(space->names, space->count * sizeof(char *)); - space->names[space->count - 1] = strdup(name); + if (!result) + free(name); + + else + { + space->count++; + + space->children = realloc(space->children, space->count * sizeof(GRegisteredItem *)); + space->children[space->count - 1] = child; + g_object_ref(G_OBJECT(child)); + + space->names = realloc(space->names, space->count * sizeof(char *)); + space->names[space->count - 1] = strdup(name); + + } return result; @@ -238,34 +296,59 @@ bool g_scan_namespace_register(GScanNamespace *space, GRegisteredItem *child, co /****************************************************************************** * * -* Paramètres : space = élément d'appel à consulter. * +* Paramètres : space = élément d'appel à consulter. * +* * +* Description : Indique le nom associé à une expression d'évaluation. * +* * +* Retour : Désignation humaine de l'expression d'évaluation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_namespace_get_name(const GScanNamespace *space) +{ + char *result; /* Désignation à retourner */ + + if (space->name != NULL) + result = strdup(space->name); + + else + result = NULL; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * * target = désignation de l'objet d'appel à identifier. * * ctx = contexte de suivi de l'analyse courante. * -* args = liste d'éventuels arguments fournis. * -* count = taille de cette liste. * -* last = l'élément est-il le dernier d'une chaîne d'appels ? * -* final = indique une ultime conversion dans le cycle en cours.* +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la résolution opérée. [OUT]* * * -* Description : Lance une résolution d'élément à appeler. * +* Description : Lance une résolution d'élément à solliciter. * * * -* Retour : Nouvel élément d'appel identifié ou NULL. * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * * Remarques : - * * * ******************************************************************************/ -GRegisteredItem *g_scan_namespace_resolve(GScanNamespace *space, const char *target, GScanContext *ctx, GScanExpression **args, size_t count, bool last, bool final) +static bool g_scan_namespace_resolve(GScanNamespace *item, const char *target, GScanContext *ctx, GScanScope *scope, GRegisteredItem **out) { - GRegisteredItem *result; /* Instance à renvoyer */ + bool result; /* Bilan à retourner */ size_t i; /* Boucle de parcours */ - result = NULL; + result = true; - for (i = 0; i < space->count; i++) - if (strcmp(target, space->names[i]) == 0) + for (i = 0; i < item->count; i++) + if (strcmp(target, item->names[i]) == 0) { - result = space->children[i]; - g_object_ref(G_OBJECT(result)); + *out = item->children[i]; + g_object_ref(G_OBJECT(*out)); break; } @@ -290,11 +373,11 @@ GRegisteredItem *g_scan_namespace_resolve(GScanNamespace *space, const char *tar * * ******************************************************************************/ -GScanExpression *g_scan_namespace_reduce(GScanNamespace *space, GScanContext *ctx, GScanExpression **args, size_t count, bool final) +static GScanExpression *g_scan_namespace_reduce(GScanNamespace *space, GScanContext *ctx, GScanExpression **args, size_t count, bool final) { GScanExpression *result; /* Instance à renvoyer */ - assert(false); + assert(false); /* REMME */ result = NULL; diff --git a/src/analysis/scan/space.h b/src/analysis/scan/space.h index 9058959..7a99387 100644 --- a/src/analysis/scan/space.h +++ b/src/analysis/scan/space.h @@ -52,10 +52,10 @@ typedef struct _GScanNamespaceClass GScanNamespaceClass; GType g_scan_namespace_get_type(void); /* Construit un nouvel espace de noms pour scan. */ -GScanNamespace *g_scan_namespace_new(void); +GScanNamespace *g_scan_namespace_new(const char *); /* Intègre un nouvel élément dans l'esapce de noms. */ -bool g_scan_namespace_register(GScanNamespace *, GRegisteredItem *, const char *); +bool g_scan_namespace_register_item(GScanNamespace *, GRegisteredItem *); diff --git a/src/analysis/scan/tokens.l b/src/analysis/scan/tokens.l index 92a5340..b541786 100644 --- a/src/analysis/scan/tokens.l +++ b/src/analysis/scan/tokens.l @@ -107,7 +107,11 @@ "rule" { PUSH_STATE(rule_intro); return RAW_RULE; } -<rule_intro>[A-Za-z0-9_]+ { yylval->cstring = yytext; return RULE_NAME; } +<rule_intro>[A-Za-z0-9_]+ { + yylval->sized_cstring.data = yytext; + yylval->sized_cstring.len = yyleng; + return RULE_NAME; + } <rule_intro>[ \t]* { } <rule_intro>"{" { POP_STATE; PUSH_STATE(raw_block); return BRACE_IN; } @@ -139,7 +143,8 @@ POP_STATE; EXTEND_BUFFER_IF_NEEDED(1); (*buf)[(*used)++] = '\0'; - yylval->cstring = *buf; + yylval->sized_cstring.data = *buf; + yylval->sized_cstring.len = *used; return STRING; } @@ -206,12 +211,12 @@ <strings,condition>$[A-Za-z0-9_]* { - yylval->sized_cstring.cstring = yytext + 1; + yylval->sized_cstring.data = yytext + 1; yylval->sized_cstring.len = yyleng - 1; return IDENTIFIER; } <condition>[A-Za-z_][A-Za-z0-9_]* { - yylval->sized_cstring.cstring = yytext; + yylval->sized_cstring.data = yytext; yylval->sized_cstring.len = yyleng; return NAME; } @@ -221,7 +226,7 @@ <strval>\"[^\"\\]+\" { POP_STATE; - yylval->sized_cstring.cstring = yytext + 1; + yylval->sized_cstring.data = yytext + 1; yylval->sized_cstring.len = yyleng - 2; return PLAIN_STRING; } |