diff options
Diffstat (limited to 'src/analysis/scan/exprs')
| -rw-r--r-- | src/analysis/scan/exprs/Makefile.am | 4 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/access-int.h | 6 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/access.c | 20 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/access.h | 4 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/call.c | 28 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/counter-int.h | 57 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/counter.c | 251 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/counter.h | 59 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/extract-int.h | 57 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/extract.c | 396 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/extract.h | 56 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/handler-int.h | 14 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/handler.c | 291 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/handler.h | 16 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/item.c | 4 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/literal.c | 73 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/logical.c | 7 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/setcounter-int.h | 11 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/setcounter.c | 137 | ||||
| -rw-r--r-- | src/analysis/scan/exprs/setcounter.h | 8 |
20 files changed, 1046 insertions, 453 deletions
diff --git a/src/analysis/scan/exprs/Makefile.am b/src/analysis/scan/exprs/Makefile.am index a0b2f3d..c97fa25 100644 --- a/src/analysis/scan/exprs/Makefile.am +++ b/src/analysis/scan/exprs/Makefile.am @@ -9,8 +9,8 @@ libanalysisscanexprs_la_SOURCES = \ arithmetic.h arithmetic.c \ call-int.h \ call.h call.c \ - counter-int.h \ - counter.h counter.c \ + extract-int.h \ + extract.h extract.c \ handler-int.h \ handler.h handler.c \ intersect-int.h \ diff --git a/src/analysis/scan/exprs/access-int.h b/src/analysis/scan/exprs/access-int.h index 3216493..be37241 100644 --- a/src/analysis/scan/exprs/access-int.h +++ b/src/analysis/scan/exprs/access-int.h @@ -42,8 +42,8 @@ struct _GScanNamedAccess union { - GRegisteredItem *base; /* Base de recherche */ - GRegisteredItem *resolved; /* Elément ciblé au final */ + GScanRegisteredItem *base; /* Base de recherche */ + GScanRegisteredItem *resolved; /* Elément ciblé au final */ GObject *any; /* Accès indistinct */ }; @@ -67,7 +67,7 @@ struct _GScanNamedAccessClass bool g_scan_named_access_create(GScanNamedAccess *, const sized_string_t *); /* Prépare une réduction en menant une résolution locale. */ -GRegisteredItem *_g_scan_named_access_prepare_reduction(const GScanNamedAccess *, GScanContext *, GScanScope *); +GScanRegisteredItem *_g_scan_named_access_prepare_reduction(const GScanNamedAccess *, GScanContext *, GScanScope *); diff --git a/src/analysis/scan/exprs/access.c b/src/analysis/scan/exprs/access.c index 0df46e6..342c2d7 100644 --- a/src/analysis/scan/exprs/access.c +++ b/src/analysis/scan/exprs/access.c @@ -281,7 +281,7 @@ static void g_scan_named_access_copy(GScanNamedAccess *dest, const GScanNamedAcc * * ******************************************************************************/ -GScanExpression *g_scan_named_access_duplicate(const GScanNamedAccess *access, GRegisteredItem *resolved) +GScanExpression *g_scan_named_access_duplicate(const GScanNamedAccess *access, GScanRegisteredItem *resolved) { GScanExpression *result; /* Instance copiée à retourner */ GType type; /* Type d'objet à copier */ @@ -315,7 +315,7 @@ GScanExpression *g_scan_named_access_duplicate(const GScanNamedAccess *access, G * * ******************************************************************************/ -void g_scan_named_access_set_base(GScanNamedAccess *access, GRegisteredItem *base) +void g_scan_named_access_set_base(GScanNamedAccess *access, GScanRegisteredItem *base) { g_clear_object(&access->base); @@ -372,10 +372,10 @@ void g_scan_named_access_attach_next(GScanNamedAccess *access, GScanNamedAccess * * ******************************************************************************/ -GRegisteredItem *_g_scan_named_access_prepare_reduction(const GScanNamedAccess *expr, GScanContext *ctx, GScanScope *scope) +GScanRegisteredItem *_g_scan_named_access_prepare_reduction(const GScanNamedAccess *expr, GScanContext *ctx, GScanScope *scope) { - GRegisteredItem *result; /* Etat synthétisé à retourner */ - GRegisteredItem *base; /* Base de recherche courante */ + GScanRegisteredItem *result; /* Etat synthétisé à retourner */ + GScanRegisteredItem *base; /* Base de recherche courante */ result = NULL; @@ -387,9 +387,11 @@ GRegisteredItem *_g_scan_named_access_prepare_reduction(const GScanNamedAccess * g_object_ref(G_OBJECT(base)); } else - base = G_REGISTERED_ITEM(get_rost_root_namespace()); + base = G_SCAN_REGISTERED_ITEM(get_rost_root_namespace()); - g_registered_item_resolve(base, expr->target, ctx, scope, &result); + g_scan_registered_item_resolve(base, expr->target, ctx, scope, &result); + + g_object_unref(G_OBJECT(base)); } @@ -429,7 +431,7 @@ GRegisteredItem *_g_scan_named_access_prepare_reduction(const GScanNamedAccess * static ScanReductionState g_scan_named_access_reduce(const GScanNamedAccess *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { ScanReductionState result; /* Etat synthétisé à retourner */ - GRegisteredItem *resolved; /* Cible concrète obtenue */ + GScanRegisteredItem *resolved; /* Cible concrète obtenue */ GScanExpression *new_next; /* Nouvelle version du suivant */ const char *current_rule; /* Nom de la règle courante */ bool status; /* Bilan d'une autre règle */ @@ -448,7 +450,7 @@ static ScanReductionState g_scan_named_access_reduce(const GScanNamedAccess *exp */ if (expr->next == NULL) { - status = g_registered_item_reduce(resolved, ctx, scope, out); + status = g_scan_registered_item_reduce(resolved, ctx, scope, out); result = (status ? SRS_REDUCED : SRS_UNRESOLVABLE); diff --git a/src/analysis/scan/exprs/access.h b/src/analysis/scan/exprs/access.h index 7c007a9..bf83dd0 100644 --- a/src/analysis/scan/exprs/access.h +++ b/src/analysis/scan/exprs/access.h @@ -53,10 +53,10 @@ GType g_scan_named_access_get_type(void); GScanExpression *g_scan_named_access_new(const sized_string_t *); /* Reproduit un accès en place dans une nouvelle instance. */ -GScanExpression *g_scan_named_access_duplicate(const GScanNamedAccess *, GRegisteredItem *); +GScanExpression *g_scan_named_access_duplicate(const GScanNamedAccess *, GScanRegisteredItem *); /* Définit une base de recherche pour la cible d'accès. */ -void g_scan_named_access_set_base(GScanNamedAccess *, GRegisteredItem *); +void g_scan_named_access_set_base(GScanNamedAccess *, GScanRegisteredItem *); /* Complète la chaine d'accès à des expressions. */ void g_scan_named_access_attach_next(GScanNamedAccess *, GScanNamedAccess *); diff --git a/src/analysis/scan/exprs/call.c b/src/analysis/scan/exprs/call.c index f68159f..3997ff6 100644 --- a/src/analysis/scan/exprs/call.c +++ b/src/analysis/scan/exprs/call.c @@ -264,16 +264,16 @@ static ScanReductionState g_scan_pending_call_reduce(const GScanPendingCall *exp { ScanReductionState result; /* Etat synthétisé à retourner */ GScanNamedAccess *access; /* Autre vision de l'expression*/ - GRegisteredItem *resolved; /* Cible concrète obtenue */ + GScanRegisteredItem *resolved; /* Cible concrète obtenue */ size_t i; /* Boucle de parcours #1 */ GScanExpression *arg; /* Argument réduit à échanger */ GScanExpression *new; /* Nouvelle réduction obtenue */ ScanReductionState state; /* Etat synthétisé d'un élément*/ size_t k; /* Boucle de parcours #2 */ GScanExpression **new_args; /* Nouvelle séquence d'args. */ - GScanExpression *new_next; /* Nouvelle version du suivant */ GObject *final; /* Expression ou élément ? */ bool valid; /* Validité de l'élément */ + GScanExpression *new_next; /* Nouvelle version du suivant */ access = G_SCAN_NAMED_ACCESS(expr); @@ -326,6 +326,10 @@ static ScanReductionState g_scan_pending_call_reduce(const GScanPendingCall *exp { if (new_args != NULL) new_args[i] = new; + + else + g_object_unref(G_OBJECT(new)); + } } @@ -358,15 +362,15 @@ static ScanReductionState g_scan_pending_call_reduce(const GScanPendingCall *exp else if (result == SRS_PENDING) { if (new_args == NULL) - valid = g_registered_item_run_call(resolved, - expr->args, - expr->count, - ctx, scope, &final); + valid = g_scan_registered_item_run_call(resolved, + expr->args, + expr->count, + ctx, scope, &final); else - valid = g_registered_item_run_call(resolved, - new_args, - expr->count, - ctx, scope, &final); + valid = g_scan_registered_item_run_call(resolved, + new_args, + expr->count, + ctx, scope, &final); if (valid && final != NULL) { @@ -376,7 +380,7 @@ static ScanReductionState g_scan_pending_call_reduce(const GScanPendingCall *exp * * Ce cas de figure ne se rencontre normalement qu'en bout de chaîne. */ - if (!G_IS_REGISTERED_ITEM(final)) + if (!G_IS_SCAN_REGISTERED_ITEM(final)) { if (access->next != NULL) result = SRS_UNRESOLVABLE; @@ -395,7 +399,7 @@ static ScanReductionState g_scan_pending_call_reduce(const GScanPendingCall *exp { assert(access->next != NULL); - new_next = g_scan_named_access_duplicate(access->next, G_REGISTERED_ITEM(final)); + new_next = g_scan_named_access_duplicate(access->next, G_SCAN_REGISTERED_ITEM(final)); result = g_scan_expression_reduce(new_next, ctx, scope, out); diff --git a/src/analysis/scan/exprs/counter-int.h b/src/analysis/scan/exprs/counter-int.h deleted file mode 100644 index 8c5e56b..0000000 --- a/src/analysis/scan/exprs/counter-int.h +++ /dev/null @@ -1,57 +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) 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_COUNTER_INT_H -#define _ANALYSIS_SCAN_EXPRS_COUNTER_INT_H - - -#include "counter.h" - - -#include "../expr-int.h" - - - -/* Décompte des identifications de motifs (instance) */ -struct _GScanMatchCounter -{ - GScanExpression parent; /* A laisser en premier */ - - GSearchPattern *pattern; /* Motif associé */ - -}; - -/* Décompte des identifications de motifs (classe) */ -struct _GScanMatchCounterClass -{ - GScanExpressionClass parent; /* A laisser en premier */ - -}; - - -/* Met en place un compteur de correspondances. */ -bool g_scan_match_counter_create(GScanMatchCounter *, GSearchPattern *); - - - -#endif /* _ANALYSIS_SCAN_EXPRS_COUNTER_INT_H */ diff --git a/src/analysis/scan/exprs/counter.c b/src/analysis/scan/exprs/counter.c deleted file mode 100644 index 7fadb91..0000000 --- a/src/analysis/scan/exprs/counter.c +++ /dev/null @@ -1,251 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * counter.c - décompte de correspondances identifiées dans du contenu binaire - * - * 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 "counter.h" - - -#include "counter-int.h" -#include "literal.h" - - - -/* --------------------- INSTANCIATION D'UNE FORME DE CONDITION --------------------- */ - - -/* Initialise la classe des opérations booléennes. */ -static void g_scan_match_counter_class_init(GScanMatchCounterClass *); - -/* Initialise une instance d'opération booléenne. */ -static void g_scan_match_counter_init(GScanMatchCounter *); - -/* Supprime toutes les références externes. */ -static void g_scan_match_counter_dispose(GScanMatchCounter *); - -/* Procède à la libération totale de la mémoire. */ -static void g_scan_match_counter_finalize(GScanMatchCounter *); - - - -/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ - - -/* Réduit une expression à une forme plus simple. */ -static ScanReductionState g_scan_match_counter_reduce(const GScanMatchCounter *, GScanContext *, GScanScope *, GScanExpression **); - - - -/* ---------------------------------------------------------------------------------- */ -/* 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(GScanMatchCounter, g_scan_match_counter, G_TYPE_SCAN_EXPRESSION); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des opérations booléennes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_scan_match_counter_class_init(GScanMatchCounterClass *klass) -{ - GObjectClass *object; /* Autre version de la classe */ - GScanExpressionClass *expr; /* Version de classe parente */ - - object = G_OBJECT_CLASS(klass); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_match_counter_dispose; - object->finalize = (GObjectFinalizeFunc)g_scan_match_counter_finalize; - - expr = G_SCAN_EXPRESSION_CLASS(klass); - - expr->cmp_rich = (compare_expr_rich_fc)NULL; - expr->reduce = (reduce_expr_fc)g_scan_match_counter_reduce; - -} - - -/****************************************************************************** -* * -* Paramètres : op = instance à initialiser. * -* * -* Description : Initialise une instance d'opération booléenne. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_scan_match_counter_init(GScanMatchCounter *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_scan_match_counter_dispose(GScanMatchCounter *counter) -{ - g_clear_object(&counter->pattern); - - G_OBJECT_CLASS(g_scan_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_scan_match_counter_finalize(GScanMatchCounter *counter) -{ - G_OBJECT_CLASS(g_scan_match_counter_parent_class)->finalize(G_OBJECT(counter)); - -} - - -/****************************************************************************** -* * -* Paramètres : pattern = motif à impliquer. * -* * -* Description : Met en place un décompte de correspondances obtenues. * -* * -* Retour : Expression mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GScanExpression *g_scan_match_counter_new(GSearchPattern *pattern) -{ - GScanExpression *result; /* Structure à retourner */ - - result = g_object_new(G_TYPE_SCAN_MATCH_COUNTER, NULL); - - if (!g_scan_match_counter_create(G_SCAN_MATCH_COUNTER(result), pattern)) - g_clear_object(&result); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : counter = instance à initialiser pleinement. * -* pattern = motif à impliquer. * -* * -* Description : Met en place un compteur de correspondances. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_scan_match_counter_create(GScanMatchCounter *counter, GSearchPattern *pattern) -{ - bool result; /* Bilan à retourner */ - - result = g_scan_expression_create(G_SCAN_EXPRESSION(counter), SRS_WAIT_FOR_SCAN); - if (!result) goto exit; - - counter->pattern = pattern; - g_object_ref(G_OBJECT(pattern)); - - exit: - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* 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 ScanReductionState g_scan_match_counter_reduce(const GScanMatchCounter *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) -{ - ScanReductionState result; /* Etat synthétisé à retourner */ - size_t count; /* Quantité de correspondances */ - - if (g_scan_context_is_scan_done(ctx)) - { - g_scan_context_get_full_matches(ctx, expr->pattern, &count); - - *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ count }); - - result = SRS_REDUCED; - - } - else - result = SRS_WAIT_FOR_SCAN; - - return result; - -} diff --git a/src/analysis/scan/exprs/counter.h b/src/analysis/scan/exprs/counter.h deleted file mode 100644 index c90953e..0000000 --- a/src/analysis/scan/exprs/counter.h +++ /dev/null @@ -1,59 +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) 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_COUNTER_H -#define _ANALYSIS_SCAN_EXPRS_COUNTER_H - - -#include <glib-object.h> - - -#include "../expr.h" -#include "../pattern.h" - - - -#define G_TYPE_SCAN_MATCH_COUNTER g_scan_match_counter_get_type() -#define G_SCAN_MATCH_COUNTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MATCH_COUNTER, GScanMatchCounter)) -#define G_IS_SCAN_MATCH_COUNTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MATCH_COUNTER)) -#define G_SCAN_MATCH_COUNTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MATCH_COUNTER, GScanMatchCounterClass)) -#define G_IS_SCAN_MATCH_COUNTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MATCH_COUNTER)) -#define G_SCAN_MATCH_COUNTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MATCH_COUNTER, GScanMatchCounterClass)) - - -/* Décompte des identifications de motifs (instance) */ -typedef struct _GScanMatchCounter GScanMatchCounter; - -/* Décompte des identifications de motifs (classe) */ -typedef struct _GScanMatchCounterClass GScanMatchCounterClass; - - -/* Indique le type défini pour un décompte de résultats lors d'une recherche de motifs. */ -GType g_scan_match_counter_get_type(void); - -/* Met en place un décompte de correspondances obtenues. */ -GScanExpression *g_scan_match_counter_new(GSearchPattern *); - - - -#endif /* _ANALYSIS_SCAN_EXPRS_COUNTER_H */ diff --git a/src/analysis/scan/exprs/extract-int.h b/src/analysis/scan/exprs/extract-int.h new file mode 100644 index 0000000..562e537 --- /dev/null +++ b/src/analysis/scan/exprs/extract-int.h @@ -0,0 +1,57 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * extract-int.h - prototypes internes pour l'organisation d'une extraction d'un élément d'une série interne + * + * 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_EXTRACT_INT_H +#define _ANALYSIS_SCAN_EXPRS_EXTRACT_INT_H + + +#include "extract.h" + + +#include "access-int.h" + + + +/* Extraction d'un élément donné au sein d'une série interne (instance) */ +struct _GScanPendingExtraction +{ + GScanNamedAccess parent; /* A laisser en premier */ + + GScanExpression *index; /* Arguments d'appel fournis */ + +}; + +/* Extraction d'un élément donné au sein d'une série interne (classe) */ +struct _GScanPendingExtractionClass +{ + GScanNamedAccessClass parent; /* A laisser en premier */ + +}; + + +/* Met en place une expression d'extraction d'élément interne. */ +bool g_scan_pending_extraction_create(GScanPendingExtraction *, const sized_string_t *, GScanExpression *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_EXTRACT_INT_H */ diff --git a/src/analysis/scan/exprs/extract.c b/src/analysis/scan/exprs/extract.c new file mode 100644 index 0000000..b140ed9 --- /dev/null +++ b/src/analysis/scan/exprs/extract.c @@ -0,0 +1,396 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * extract.c - organisation d'une extraction d'un élément d'une série interne + * + * 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 "extract.h" + + +#include <assert.h> +#include <string.h> + + +#include "extract-int.h" +#include "../../../core/global.h" + + + +/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */ + + +/* Initialise la classe des extractions d'éléments internes. */ +static void g_scan_pending_extraction_class_init(GScanPendingExtractionClass *); + +/* Initialise une instance d'extraction d'élément interne. */ +static void g_scan_pending_extraction_init(GScanPendingExtraction *); + +/* Supprime toutes les références externes. */ +static void g_scan_pending_extraction_dispose(GScanPendingExtraction *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_pending_extraction_finalize(GScanPendingExtraction *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Réduit une expression à une forme plus simple. */ +static ScanReductionState g_scan_pending_extraction_reduce(const GScanPendingExtraction *, GScanContext *, GScanScope *, GScanExpression **); + +/* Reproduit un accès en place dans une nouvelle instance. */ +static void g_scan_pending_extraction_copy(GScanPendingExtraction *, const GScanPendingExtraction *); + + + +/* ---------------------------------------------------------------------------------- */ +/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une extraction d'élément de série interne. */ +G_DEFINE_TYPE(GScanPendingExtraction, g_scan_pending_extraction, G_TYPE_SCAN_NAMED_ACCESS); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des extractions d'éléments internes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_pending_extraction_class_init(GScanPendingExtractionClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanExpressionClass *expr; /* Version de classe parente */ + GScanNamedAccessClass *access; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_pending_extraction_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_pending_extraction_finalize; + + expr = G_SCAN_EXPRESSION_CLASS(klass); + + expr->cmp_rich = (compare_expr_rich_fc)NULL; + expr->reduce = (reduce_expr_fc)g_scan_pending_extraction_reduce; + + access = G_SCAN_NAMED_ACCESS_CLASS(klass); + + access->copy = (copy_scan_access_fc)g_scan_pending_extraction_copy; + +} + + +/****************************************************************************** +* * +* Paramètres : extract = instance à initialiser. * +* * +* Description : Initialise une instance d'extraction d'élément interne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_pending_extraction_init(GScanPendingExtraction *extract) +{ + extract->index = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : extract = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_pending_extraction_dispose(GScanPendingExtraction *extract) +{ + g_clear_object(&extract->index); + + G_OBJECT_CLASS(g_scan_pending_extraction_parent_class)->dispose(G_OBJECT(extract)); + +} + + +/****************************************************************************** +* * +* Paramètres : extract = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_pending_extraction_finalize(GScanPendingExtraction *extract) +{ + G_OBJECT_CLASS(g_scan_pending_extraction_parent_class)->finalize(G_OBJECT(extract)); + +} + + +/****************************************************************************** +* * +* Paramètres : target = désignation de l'objet d'appel à identifier. * +* index = indice de l'élément à extraire. * +* * +* Description : Organise l'extraction d'un élément d'une série interne. * +* * +* Retour : Fonction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_scan_pending_extraction_new(const sized_string_t *target, GScanExpression *index) +{ + GScanExpression *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_PENDING_EXTRACTION, NULL); + + if (!g_scan_pending_extraction_create(G_SCAN_PENDING_EXTRACTION(result), target, index)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : extract = instance à initialiser pleinement. * +* target = désignation de l'objet d'appel à identifier. * +* index = indice de l'élément à extraire. * +* * +* Description : Met en place une expression d'extraction d'élément interne. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_scan_pending_extraction_create(GScanPendingExtraction *extract, const sized_string_t *target, GScanExpression *index) +{ + bool result; /* Bilan à retourner */ + + result = g_scan_named_access_create(G_SCAN_NAMED_ACCESS(extract), target); + if (!result) goto exit; + + extract->index = index; + g_object_ref(G_OBJECT(index)); + + exit: + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* 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 ScanReductionState g_scan_pending_extraction_reduce(const GScanPendingExtraction *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +{ + ScanReductionState result; /* Etat synthétisé à retourner */ + GScanNamedAccess *access; /* Autre vision de l'expression*/ + GScanRegisteredItem *resolved; /* Cible concrète obtenue */ + GScanExpression *new; /* Nouvelle réduction obtenue */ + GObject *final; /* Expression ou élément ? */ + GScanExpression *new_next; /* Nouvelle version du suivant */ + + access = G_SCAN_NAMED_ACCESS(expr); + + resolved = _g_scan_named_access_prepare_reduction(access, ctx, scope); + + if (resolved == NULL) + result = SRS_UNRESOLVABLE; + + else + { + /* Actualisation nécessaire des arguments ? */ + + result = g_scan_expression_reduce(expr->index, ctx, scope, &new); + + /* Suite des traitements */ + + if (result == SRS_WAIT_FOR_SCAN) + { + /** + * Si changement il y a eu... + */ + if (new != expr->index) + { + *out = g_scan_pending_extraction_new(NULL, new); + + /** + * Fonctionnement équivalent de : + * g_scan_named_access_set_base(G_SCAN_NAMED_ACCESS(*out), resolved); + */ + G_SCAN_NAMED_ACCESS(*out)->resolved = resolved; + g_object_ref(G_OBJECT(resolved)); + + if (G_SCAN_NAMED_ACCESS(expr)->next != NULL) + g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS(*out), G_SCAN_NAMED_ACCESS(expr)->next); + + } + + } + + else if (result == SRS_REDUCED) + { + final = g_scan_registered_item_extract_at(resolved, new, ctx, scope); + + if (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_SCAN_REGISTERED_ITEM(final)) + { + if (access->next != NULL) + result = SRS_UNRESOLVABLE; + + else + { + *out = G_SCAN_EXPRESSION(final); + g_object_ref(G_OBJECT(final)); + + result = SRS_REDUCED; + + } + + } + else + { + if (access->next != NULL) + { + new_next = g_scan_named_access_duplicate(access->next, G_SCAN_REGISTERED_ITEM(final)); + + result = g_scan_expression_reduce(new_next, ctx, scope, out); + + g_object_unref(G_OBJECT(new_next)); + + } + + /** + * Le cas ci-après est typique de l'extension Kaitai : field[n] + * renvoie vers une instance GScanRegisteredItem (GKaitaiBrowser). + * + * Il n'y a donc pas d'expression en jeu, et l'élément est le dernier + * de la liste. + */ + else + { + if (g_scan_registered_item_reduce(G_SCAN_REGISTERED_ITEM(final), ctx, scope, out)) + result = SRS_REDUCED; + else + result = SRS_UNRESOLVABLE; + + } + + } + + } + + else + result = SRS_UNRESOLVABLE; + + g_clear_object(&final); + + } + + /* Libération locale des arguments reconstruits */ + + g_clear_object(&new); + + g_object_unref(G_OBJECT(resolved)); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] * +* src = expression source à copier. * +* * +* Description : Reproduit un accès en place dans une nouvelle instance. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_pending_extraction_copy(GScanPendingExtraction *dest, const GScanPendingExtraction *src) +{ + GScanNamedAccessClass *class; /* Classe parente à solliciter */ + + class = G_SCAN_NAMED_ACCESS_CLASS(g_scan_pending_extraction_parent_class); + + class->copy(G_SCAN_NAMED_ACCESS(dest), G_SCAN_NAMED_ACCESS(src)); + + dest->index = src->index; + g_object_ref(G_OBJECT(src->index)); + +} diff --git a/src/analysis/scan/exprs/extract.h b/src/analysis/scan/exprs/extract.h new file mode 100644 index 0000000..8ed1cfa --- /dev/null +++ b/src/analysis/scan/exprs/extract.h @@ -0,0 +1,56 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * extract.h - prototypes pour l'organisation d'une extraction d'un élément d'une série interne + * + * 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_EXTRACT_H +#define _ANALYSIS_SCAN_EXPRS_EXTRACT_H + + +#include "../expr.h" +#include "../../../common/szstr.h" + + + +#define G_TYPE_SCAN_PENDING_EXTRACTION g_scan_pending_extraction_get_type() +#define G_SCAN_PENDING_EXTRACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_PENDING_EXTRACTION, GScanPendingExtraction)) +#define G_IS_SCAN_PENDING_EXTRACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_PENDING_EXTRACTION)) +#define G_SCAN_PENDING_EXTRACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_PENDING_EXTRACTION, GScanPendingExtractionClass)) +#define G_IS_SCAN_PENDING_EXTRACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_PENDING_EXTRACTION)) +#define G_SCAN_PENDING_EXTRACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_PENDING_EXTRACTION, GScanPendingExtractionClass)) + + +/* Extraction d'un élément donné au sein d'une série interne (instance) */ +typedef struct _GScanPendingExtraction GScanPendingExtraction; + +/* Extraction d'un élément donné au sein d'une série interne (classe) */ +typedef struct _GScanPendingExtractionClass GScanPendingExtractionClass; + + +/* Indique le type défini pour une extraction d'élément de série interne. */ +GType g_scan_pending_extraction_get_type(void); + +/* Organise l'extraction d'un élément d'une série interne. */ +GScanExpression *g_scan_pending_extraction_new(const sized_string_t *, GScanExpression *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_EXTRACT_H */ diff --git a/src/analysis/scan/exprs/handler-int.h b/src/analysis/scan/exprs/handler-int.h index f707fdb..e051b30 100644 --- a/src/analysis/scan/exprs/handler-int.h +++ b/src/analysis/scan/exprs/handler-int.h @@ -37,7 +37,14 @@ struct _GScanPatternHandler { GScanExpression parent; /* A laisser en premier */ - GSearchPattern *pattern; /* Motif associé */ + union + { + const GSearchPattern **patterns; /* Motifs associés */ + GSearchPattern **ref_patterns; /* Motifs associés */ + }; + size_t count; /* Nombre de ces motifs */ + bool shared; /* Définition de propriété */ + ScanHandlerType type; /* Manipulation attendue */ }; @@ -51,7 +58,10 @@ struct _GScanPatternHandlerClass /* Met en place une manipulation de correspondances établies. */ -bool g_scan_pattern_handler_create(GScanPatternHandler *, GSearchPattern *, ScanHandlerType); +bool g_scan_pattern_handler_create_shared(GScanPatternHandler *, const GSearchPattern ** const, size_t, ScanHandlerType); + +/* Met en place une manipulation de correspondances établies. */ +bool g_scan_pattern_handler_create_and_ref(GScanPatternHandler *, GSearchPattern ** const, size_t, ScanHandlerType); diff --git a/src/analysis/scan/exprs/handler.c b/src/analysis/scan/exprs/handler.c index 1676522..2706dae 100644 --- a/src/analysis/scan/exprs/handler.c +++ b/src/analysis/scan/exprs/handler.c @@ -122,7 +122,10 @@ static void g_scan_pattern_handler_class_init(GScanPatternHandlerClass *klass) static void g_scan_pattern_handler_init(GScanPatternHandler *handler) { - handler->pattern = NULL; + handler->patterns = NULL; + handler->count = 0; + handler->shared = true; + handler->type = SHT_RAW; } @@ -142,7 +145,11 @@ static void g_scan_pattern_handler_init(GScanPatternHandler *handler) static void g_scan_pattern_handler_dispose(GScanPatternHandler *handler) { - g_clear_object(&handler->pattern); + size_t i; /* Boucle de parcours */ + + if (!handler->shared) + for (i = 0; i < handler->count; i++) + g_clear_object(&handler->ref_patterns[i]); G_OBJECT_CLASS(g_scan_pattern_handler_parent_class)->dispose(G_OBJECT(handler)); @@ -163,6 +170,9 @@ static void g_scan_pattern_handler_dispose(GScanPatternHandler *handler) static void g_scan_pattern_handler_finalize(GScanPatternHandler *handler) { + if (handler->patterns != NULL) + free(handler->patterns); + G_OBJECT_CLASS(g_scan_pattern_handler_parent_class)->finalize(G_OBJECT(handler)); } @@ -170,8 +180,9 @@ static void g_scan_pattern_handler_finalize(GScanPatternHandler *handler) /****************************************************************************** * * -* Paramètres : pattern = motif à impliquer. * -* type = type de manipulation attendue. * +* Paramètres : patterns = motifs à impliquer. * +* count = quantité de ces motifs. * +* type = type de manipulation attendue. * * * * Description : Met en place une manipulation de correspondances établies. * * * @@ -181,13 +192,13 @@ static void g_scan_pattern_handler_finalize(GScanPatternHandler *handler) * * ******************************************************************************/ -GScanExpression *g_scan_pattern_handler_new(GSearchPattern *pattern, ScanHandlerType type) +GScanExpression *g_scan_pattern_handler_new_shared(const GSearchPattern ** const patterns, size_t count, ScanHandlerType type) { GScanExpression *result; /* Structure à retourner */ result = g_object_new(G_TYPE_SCAN_PATTERN_HANDLER, NULL); - if (!g_scan_pattern_handler_create(G_SCAN_PATTERN_HANDLER(result), pattern, type)) + if (!g_scan_pattern_handler_create_shared(G_SCAN_PATTERN_HANDLER(result), patterns, count, type)) g_clear_object(&result); return result; @@ -197,9 +208,10 @@ GScanExpression *g_scan_pattern_handler_new(GSearchPattern *pattern, ScanHandler /****************************************************************************** * * -* Paramètres : handler = instance à initialiser pleinement. * -* pattern = motif à impliquer. * -* type = type de manipulation attendue. * +* Paramètres : handler = instance à initialiser pleinement. * +* patterns = motifs à impliquer. * +* count = quantité de ces motifs. * +* type = type de manipulation attendue. * * * * Description : Met en place une manipulation de correspondances établies. * * * @@ -209,15 +221,19 @@ GScanExpression *g_scan_pattern_handler_new(GSearchPattern *pattern, ScanHandler * * ******************************************************************************/ -bool g_scan_pattern_handler_create(GScanPatternHandler *handler, GSearchPattern *pattern, ScanHandlerType type) +bool g_scan_pattern_handler_create_shared(GScanPatternHandler *handler, const GSearchPattern ** const patterns, size_t count, ScanHandlerType type) { bool result; /* Bilan à retourner */ result = g_scan_expression_create(G_SCAN_EXPRESSION(handler), SRS_WAIT_FOR_SCAN); if (!result) goto exit; - handler->pattern = pattern; - g_object_ref(G_OBJECT(pattern)); + handler->patterns = malloc(count * sizeof(GSearchPattern *)); + handler->count = count; + + memcpy(handler->patterns, patterns, count * sizeof(GSearchPattern *)); + + handler->shared = true; handler->type = type; @@ -228,6 +244,159 @@ bool g_scan_pattern_handler_create(GScanPatternHandler *handler, GSearchPattern } +/****************************************************************************** +* * +* Paramètres : patterns = motifs à impliquer. * +* count = quantité de ces motifs. * +* type = type de manipulation attendue. * +* * +* Description : Met en place une manipulation de correspondances établies. * +* * +* Retour : Expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_scan_pattern_handler_new(GSearchPattern ** const patterns, size_t count, ScanHandlerType type) +{ + GScanExpression *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_PATTERN_HANDLER, NULL); + + if (!g_scan_pattern_handler_create_and_ref(G_SCAN_PATTERN_HANDLER(result), patterns, count, type)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : handler = instance à initialiser pleinement. * +* patterns = motifs à impliquer. * +* count = quantité de ces motifs. * +* type = type de manipulation attendue. * +* * +* Description : Met en place une manipulation de correspondances établies. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_scan_pattern_handler_create_and_ref(GScanPatternHandler *handler, GSearchPattern ** const patterns, size_t count, ScanHandlerType type) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + + result = g_scan_expression_create(G_SCAN_EXPRESSION(handler), SRS_WAIT_FOR_SCAN); + if (!result) goto exit; + + handler->patterns = malloc(count * sizeof(GSearchPattern *)); + handler->count = count; + + memcpy(handler->patterns, patterns, count * sizeof(GSearchPattern *)); + + for (i = 0; i < count; i++) + g_object_ref(G_OBJECT(patterns[i])); + + handler->shared = false; + + handler->type = type; + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : handler = instance à initialiser pleinement. * +* * +* Description : Indique le type de manipulation de correspondances spécifié. * +* * +* Retour : Type de manipulation de correspondances représentée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +ScanHandlerType g_scan_pattern_handler_get_handler_type(const GScanPatternHandler *handler) +{ + ScanHandlerType result; /* Nature à retourner */ + + result = handler->type; + + return result; + +} + + +#if 0 /* FIXME */ + +/****************************************************************************** +* * +* Paramètres : handler = instance à initialiser pleinement. * +* ctx = contexte de suivi de l'analyse courante. * +* count = quantité de correspondances enregistrées. [OUT] * +* * +* Description : Fournit la liste de toutes les correspondances représentées. * +* * +* Retour : Liste courante de correspondances établies. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanMatch **g_scan_pattern_handler_get_all_matches(const GScanPatternHandler *handler, GScanContext *ctx, size_t *count) +{ + GScanMatch **result; /* Liste à retourner */ + size_t used; /* Indice pour le stockage */ + size_t i; /* Boucle de parcours #1 */ + size_t partial; /* Décompte partiel */ + const GScanMatch **matches; /* Correspondances en place */ + size_t k; /* Boucle de parcours #2 */ + + result = NULL; + + if (!g_scan_pattern_handler_count_items(handler, ctx, count)) + { + *count = 0; + goto exit; + } + + if (*count == 0) + goto exit; + + result = malloc(*count * sizeof(GScanMatch *)); + + used = 0; + + for (i = 0; i < handler->count; i++) + { + matches = g_scan_context_get_full_matches(ctx, handler->patterns[i], &partial); + + for (k = 0; k < partial; k++) + { + result[used++] = matches[k]; + g_object_ref(G_OBJECT(matches[k])); + } + + } + + exit: + + return result; + +} +#endif + + /* ---------------------------------------------------------------------------------- */ /* IMPLEMENTATION DES FONCTIONS DE CLASSE */ @@ -252,9 +421,27 @@ bool g_scan_pattern_handler_create(GScanPatternHandler *handler, GSearchPattern static ScanReductionState g_scan_pattern_handler_reduce(const GScanPatternHandler *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { ScanReductionState result; /* Etat synthétisé à retourner */ + size_t count; /* Quantité de correspondances */ if (g_scan_context_is_scan_done(ctx)) - result = SRS_REDUCED; + { + if (expr->type == SHT_COUNTER) + { + if (!g_scan_pattern_handler_count_items(expr, ctx, &count)) + result = SRS_UNRESOLVABLE; + + else + { + result = SRS_REDUCED; + *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ count }); + } + + } + + else + result = SRS_REDUCED; + + } else result = SRS_WAIT_FOR_SCAN; @@ -284,9 +471,7 @@ static bool g_scan_pattern_handler_reduce_to_boolean(const GScanPatternHandler * bool result; /* Bilan à retourner */ size_t count; /* Quantité de correspondances */ - result = true; - - g_scan_context_get_full_matches(ctx, expr->pattern, &count); + result = g_scan_pattern_handler_count_items(expr, ctx, &count); *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ count > 0 }); @@ -312,12 +497,16 @@ static bool g_scan_pattern_handler_reduce_to_boolean(const GScanPatternHandler * static bool g_scan_pattern_handler_count_items(const GScanPatternHandler *expr, GScanContext *ctx, size_t *count) { bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ result = true; assert(g_scan_context_is_scan_done(ctx)); - g_scan_context_get_full_matches(ctx, expr->pattern, count); + *count = 0; + + for (i = 0; i < expr->count; i++) + *count += g_scan_context_count_full_matches(ctx, expr->patterns[i]); return result; @@ -342,62 +531,90 @@ static bool g_scan_pattern_handler_count_items(const GScanPatternHandler *expr, static bool g_scan_pattern_handler_get_item(const GScanPatternHandler *expr, size_t index, GScanContext *ctx, GScanExpression **out) { bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ size_t count; /* Quantité de correspondances */ - const GScanMatch **matches; /* Correspondances en place */ - const GScanBytesMatch *match; /* Correspondance ciblée */ - phys_t start; /* Point de départ du motif */ - phys_t end; /* Point d'arrivée du motif */ - phys_t len; /* Taille du motif */ + GScanMatches *matches; /* Correspondances d'un motif */ + const match_area_t *area; /* Zone de correspondance */ GBinContent *content; /* Contenu binaire à relire */ vmpa2t pos; /* Tête de lecture */ const bin_t *data; /* Accès aux données brutes */ sized_string_t binary; /* Conversion de formats */ + result = false; + assert(g_scan_context_is_scan_done(ctx)); - matches = g_scan_context_get_full_matches(ctx, expr->pattern, &count); + /* Identification du motif concerné */ + + for (i = 0; i < expr->count; i++) + { + count = g_scan_context_count_full_matches(ctx, expr->patterns[i]); + + if (index < count) + break; + else + index -= count; + + } + + if (i == expr->count) goto done; - result = (index < count); - if (!result) goto done; + /* Identification de la correspondance concernée */ - result = G_IS_SCAN_BYTES_MATCH(matches[index]); - if (!result) goto done; + matches = g_scan_context_get_full_matches(ctx, expr->patterns[i]); + if (matches == NULL) goto done; - match = G_SCAN_BYTES_MATCH(matches[index]); + area = g_scan_bytes_matches_get(G_SCAN_BYTES_MATCHES(matches), index); + if (area == NULL) goto done_with_matches; - len = g_scan_bytes_match_get_location(match, &start, &end); + /* Traitement adapté de la requête */ switch (expr->type) { case SHT_RAW: - content = g_scan_bytes_match_get_content(match); + content = g_scan_context_get_content(ctx); - init_vmpa(&pos, start, VMPA_NO_VIRTUAL); + init_vmpa(&pos, area->start, VMPA_NO_VIRTUAL); - data = g_binary_content_get_raw_access(content, &pos, len); + data = g_binary_content_get_raw_access(content, &pos, area->end - area->start); - binary.data = data; - binary.len = len; + binary.static_bin_data = data; + binary.len = area->end - area->start; *out = g_scan_literal_expression_new(LVT_STRING, &binary); g_object_unref(G_OBJECT(content)); + result = true; + break; + + case SHT_COUNTER: + assert(false); break; case SHT_START: - *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ start }); + *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, + (unsigned long long []){ area->start }); + result = true; break; case SHT_LENGTH: - *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ len }); + *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, + (unsigned long long []){ area->end - area->start }); + result = true; break; case SHT_END: - *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ end }); + *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, + (unsigned long long []){ area->end }); + result = true; break; } + done_with_matches: + + g_object_unref(G_OBJECT(matches)); + done: return result; diff --git a/src/analysis/scan/exprs/handler.h b/src/analysis/scan/exprs/handler.h index 8ad700a..a1ddf98 100644 --- a/src/analysis/scan/exprs/handler.h +++ b/src/analysis/scan/exprs/handler.h @@ -48,6 +48,7 @@ typedef struct _GScanPatternHandlerClass GScanPatternHandlerClass; typedef enum _ScanHandlerType { SHT_RAW, /* Correspondances brutes */ + SHT_COUNTER, /* Dénombrement de résultats */ SHT_START, /* Départs de correspondances */ SHT_LENGTH, /* Taille de correspondances */ SHT_END, /* Fins de correspondances */ @@ -59,7 +60,20 @@ typedef enum _ScanHandlerType GType g_scan_pattern_handler_get_type(void); /* Met en place une manipulation de correspondances établies. */ -GScanExpression *g_scan_pattern_handler_new(GSearchPattern *, ScanHandlerType); +GScanExpression *g_scan_pattern_handler_new_shared(const GSearchPattern ** const, size_t, ScanHandlerType); + +/* Met en place une manipulation de correspondances établies. */ +GScanExpression *g_scan_pattern_handler_new(GSearchPattern ** const, size_t, ScanHandlerType); + +/* Indique le type de manipulation de correspondances spécifié. */ +ScanHandlerType g_scan_pattern_handler_get_handler_type(const GScanPatternHandler *); + +#if 0 /* FIXME */ + +/* Fournit la liste de toutes les correspondances représentées. */ +GScanMatch **g_scan_pattern_handler_get_all_matches(const GScanPatternHandler *, GScanContext *, size_t *); + +#endif diff --git a/src/analysis/scan/exprs/item.c b/src/analysis/scan/exprs/item.c index b7cd970..a5a6fdf 100644 --- a/src/analysis/scan/exprs/item.c +++ b/src/analysis/scan/exprs/item.c @@ -308,6 +308,7 @@ static ScanReductionState g_scan_set_item_reduce(const GScanSetItem *expr, GScan status = g_scan_expression_get_item(expr->set, val_s, ctx, out); } + else if (vtype == LVT_UNSIGNED_INTEGER) { if (!g_scan_literal_expression_get_unsigned_integer_value(op_index, &val_u)) @@ -320,6 +321,9 @@ static ScanReductionState g_scan_set_item_reduce(const GScanSetItem *expr, GScan } + else + status = false; + result = (status ? SRS_REDUCED : SRS_UNRESOLVABLE); } diff --git a/src/analysis/scan/exprs/literal.c b/src/analysis/scan/exprs/literal.c index de7e32a..b7aed5b 100644 --- a/src/analysis/scan/exprs/literal.c +++ b/src/analysis/scan/exprs/literal.c @@ -62,6 +62,9 @@ static bool g_scan_literal_expression_reduce_to_boolean(const GScanLiteralExpres /* Dénombre les éléments portés par une expression. */ static bool g_scan_literal_expression_count(const GScanLiteralExpression *, GScanContext *, size_t *); +/* Fournit un élément donné issu d'un ensemble constitué. */ +static bool g_scan_literal_expression_get_item(const GScanLiteralExpression *, size_t, GScanContext *, GScanExpression **); + /* ---------------------------------------------------------------------------------- */ @@ -100,6 +103,7 @@ static void g_scan_literal_expression_class_init(GScanLiteralExpressionClass *kl expr->cmp_rich = (compare_expr_rich_fc)g_scan_literal_expression_compare_rich; expr->reduce_to_bool = (reduce_expr_to_bool_fc)g_scan_literal_expression_reduce_to_boolean; expr->count = (count_scan_expr_fc)g_scan_literal_expression_count; + expr->get = (get_scan_expr_fc)g_scan_literal_expression_get_item; } @@ -120,6 +124,8 @@ static void g_scan_literal_expression_init(GScanLiteralExpression *expr) { G_SCAN_EXPRESSION(expr)->state = SRS_REDUCED; + memset(&expr->value, 0, sizeof(expr->value)); + } @@ -156,6 +162,25 @@ static void g_scan_literal_expression_dispose(GScanLiteralExpression *expr) static void g_scan_literal_expression_finalize(GScanLiteralExpression *expr) { + switch (expr->value_type) + { + case LVT_STRING: + exit_szstr(&expr->value.string); + break; + + case LVT_REG_EXPR: + if (expr->value.regex != NULL) + { + free(expr->value.regex); + regfree(&expr->value.preg); + } + break; + + default: + break; + + } + G_OBJECT_CLASS(g_scan_literal_expression_parent_class)->finalize(G_OBJECT(expr)); } @@ -659,3 +684,51 @@ static bool g_scan_literal_expression_count(const GScanLiteralExpression *expr, return result; } + + +/****************************************************************************** +* * +* Paramètres : expr = expression à consulter. * +* index = indice de l'élément à transférer. * +* ctx = contexte de suivi de l'analyse courante. * +* out = zone d'enregistrement de la réduction opérée. [OUT] * +* * +* Description : Fournit un élément donné issu d'un ensemble constitué. * +* * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_scan_literal_expression_get_item(const GScanLiteralExpression *expr, size_t index, GScanContext *ctx, GScanExpression **out) +{ + bool result; /* Bilan à retourner */ + sized_string_t ch; /* Caractère extrait */ + + switch (expr->value_type) + { + case LVT_STRING: + + result = (index < expr->value.string.len); + + if (result) + { + ch.data = expr->value.string.data + index; + ch.len = 1; + + *out = g_scan_literal_expression_new(LVT_STRING, &ch); + + } + + break; + + default: + result = false; + break; + + } + + return result; + +} diff --git a/src/analysis/scan/exprs/logical.c b/src/analysis/scan/exprs/logical.c index cc78a75..3b07843 100644 --- a/src/analysis/scan/exprs/logical.c +++ b/src/analysis/scan/exprs/logical.c @@ -230,7 +230,7 @@ bool g_scan_logical_operation_create(GScanLogicalOperation *op, BooleanOperation g_object_ref(G_OBJECT(op->first)); result = (second == NULL); - assert(second != NULL); + assert(second == NULL); break; default: @@ -483,6 +483,11 @@ static ScanReductionState g_scan_logical_operation_reduce(const GScanLogicalOper break; + /* Pour GCC... */ + default: + result = SRS_UNRESOLVABLE; + break; + } /* Mise à jour de la progression ? */ diff --git a/src/analysis/scan/exprs/setcounter-int.h b/src/analysis/scan/exprs/setcounter-int.h index fbed209..c9e3da5 100644 --- a/src/analysis/scan/exprs/setcounter-int.h +++ b/src/analysis/scan/exprs/setcounter-int.h @@ -37,8 +37,13 @@ struct _GScanSetMatchCounter { GScanExpression parent; /* A laisser en premier */ - GSearchPattern **patterns; /* Motifs associés */ + union + { + const GSearchPattern **patterns; /* Motifs associés */ + GSearchPattern **ref_patterns; /* Motifs associés */ + }; size_t count; /* Nombre de ces motifs */ + bool shared; /* Définition de propriété */ ScanSetCounterType type; /* Type de décompte */ size_t number; /* Eventuel volume associé */ @@ -53,9 +58,11 @@ struct _GScanSetMatchCounterClass }; +/* Met en place un décompte de motifs avec correspondances. */ +bool g_scan_set_match_counter_create_shared(GScanSetMatchCounter *, const GSearchPattern ** const, size_t); /* Met en place un décompte de motifs avec correspondances. */ -bool g_scan_set_match_counter_create(GScanSetMatchCounter *, GSearchPattern ** const, size_t); +bool g_scan_set_match_counter_create_and_ref(GScanSetMatchCounter *, GSearchPattern ** const, size_t); diff --git a/src/analysis/scan/exprs/setcounter.c b/src/analysis/scan/exprs/setcounter.c index 14e7676..bed315e 100644 --- a/src/analysis/scan/exprs/setcounter.c +++ b/src/analysis/scan/exprs/setcounter.c @@ -24,6 +24,10 @@ #include "setcounter.h" +#include <assert.h> +#include <string.h> + + #include "setcounter-int.h" #include "literal.h" @@ -109,6 +113,7 @@ static void g_scan_set_match_counter_init(GScanSetMatchCounter *counter) { counter->patterns = NULL; counter->count = 0; + counter->shared = true; counter->type = SSCT_NONE; counter->number = 0; @@ -132,8 +137,9 @@ static void g_scan_set_match_counter_dispose(GScanSetMatchCounter *counter) { size_t i; /* Boucle de parcours */ - for (i = 0; i < counter->count; i++) - g_clear_object(&counter->patterns[i]); + if (!counter->shared) + for (i = 0; i < counter->count; i++) + g_clear_object(&counter->ref_patterns[i]); G_OBJECT_CLASS(g_scan_set_match_counter_parent_class)->dispose(G_OBJECT(counter)); @@ -175,13 +181,75 @@ static void g_scan_set_match_counter_finalize(GScanSetMatchCounter *counter) * * ******************************************************************************/ +GScanExpression *g_scan_set_match_counter_new_shared(const GSearchPattern ** const patterns, size_t count) +{ + GScanExpression *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_SET_MATCH_COUNTER, NULL); + + if (!g_scan_set_match_counter_create_shared(G_SCAN_SET_MATCH_COUNTER(result), patterns, count)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : counter = instance à initialiser pleinement. * +* patterns = motifs à impliquer. * +* count = quantité de ces motifs. * +* * +* Description : Met en place un décompte de motifs avec correspondances. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_scan_set_match_counter_create_shared(GScanSetMatchCounter *counter, const GSearchPattern ** const patterns, size_t count) +{ + bool result; /* Bilan à retourner */ + + result = g_scan_expression_create(G_SCAN_EXPRESSION(counter), SRS_WAIT_FOR_SCAN); + if (!result) goto exit; + + counter->patterns = malloc(count * sizeof(GSearchPattern *)); + counter->count = count; + + memcpy(counter->patterns, patterns, count * sizeof(GSearchPattern *)); + + counter->shared = true; + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : patterns = motifs à impliquer. * +* count = quantité de ces motifs. * +* * +* Description : Constitue un décompte de motifs avec correspondances. * +* * +* Retour : Expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + GScanExpression *g_scan_set_match_counter_new(GSearchPattern ** const patterns, size_t count) { GScanExpression *result; /* Structure à retourner */ result = g_object_new(G_TYPE_SCAN_SET_MATCH_COUNTER, NULL); - if (!g_scan_set_match_counter_create(G_SCAN_SET_MATCH_COUNTER(result), patterns, count)) + if (!g_scan_set_match_counter_create_and_ref(G_SCAN_SET_MATCH_COUNTER(result), patterns, count)) g_clear_object(&result); return result; @@ -203,7 +271,7 @@ GScanExpression *g_scan_set_match_counter_new(GSearchPattern ** const patterns, * * ******************************************************************************/ -bool g_scan_set_match_counter_create(GScanSetMatchCounter *counter, GSearchPattern ** const patterns, size_t count) +bool g_scan_set_match_counter_create_and_ref(GScanSetMatchCounter *counter, GSearchPattern ** const patterns, size_t count) { bool result; /* Bilan à retourner */ size_t i; /* Boucle de parcours */ @@ -214,11 +282,12 @@ bool g_scan_set_match_counter_create(GScanSetMatchCounter *counter, GSearchPatte counter->patterns = malloc(count * sizeof(GSearchPattern *)); counter->count = count; + memcpy(counter->patterns, patterns, count * sizeof(GSearchPattern *)); + for (i = 0; i < count; i++) - { - counter->patterns[i] = patterns[i]; g_object_ref(G_OBJECT(patterns[i])); - } + + counter->shared = false; exit: @@ -241,21 +310,52 @@ bool g_scan_set_match_counter_create(GScanSetMatchCounter *counter, GSearchPatte * * ******************************************************************************/ -void g_scan_set_match_counter_add_extra_patterns(GScanSetMatchCounter *counter, GSearchPattern ** const patterns, size_t count) +void g_scan_set_match_counter_add_extra_shared_patterns(GScanSetMatchCounter *counter, const GSearchPattern ** const patterns, size_t count) +{ + size_t first; /* Premier emplacement libre */ + + assert(counter->shared); + + first = counter->count; + + counter->count += count; + counter->patterns = realloc(counter->patterns, counter->count * sizeof(GSearchPattern *)); + + memcpy(counter->patterns + first, patterns, count * sizeof(GSearchPattern *)); + +} + + +/****************************************************************************** +* * +* Paramètres : counter = décompte à compléter. * +* patterns = motifs à impliquer. * +* count = quantité de ces motifs. * +* * +* Description : Ajoute de nouveaux motifs à un ensemble à décompter. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_scan_set_match_counter_add_and_ref_extra_patterns(GScanSetMatchCounter *counter, GSearchPattern ** const patterns, size_t count) { size_t first; /* Premier emplacement libre */ size_t i; /* Boucle de parcours */ + assert(!counter->shared); + first = counter->count; counter->count += count; counter->patterns = realloc(counter->patterns, counter->count * sizeof(GSearchPattern *)); + memcpy(counter->patterns + first, patterns, count * sizeof(GSearchPattern *)); + for (i = 0; i < count; i++) - { - counter->patterns[first + i] = patterns[i]; g_object_ref(G_OBJECT(patterns[i])); - } } @@ -319,6 +419,7 @@ static ScanReductionState g_scan_set_match_counter_reduce(const GScanSetMatchCou ScanReductionState result; /* Etat synthétisé à retourner */ size_t matched; /* Qté de motifs avec résultats*/ size_t i; /* Boucle de parcours */ + GScanMatches *matches; /* Série de correspondances */ size_t count; /* Quantité de correspondances */ bool status; /* Bilan d'évaluation finale */ @@ -328,10 +429,18 @@ static ScanReductionState g_scan_set_match_counter_reduce(const GScanSetMatchCou for (i = 0; i < expr->count; i++) { - g_scan_context_get_full_matches(ctx, expr->patterns[i], &count); + matches = g_scan_context_get_full_matches(ctx, expr->patterns[i]); + + if (matches != NULL) + { + count = g_scan_matches_count(matches); + + if (count > 0) + matched++; + + g_object_unref(G_OBJECT(matches)); - if (count > 0) - matched++; + } } diff --git a/src/analysis/scan/exprs/setcounter.h b/src/analysis/scan/exprs/setcounter.h index 59762f9..28c92b4 100644 --- a/src/analysis/scan/exprs/setcounter.h +++ b/src/analysis/scan/exprs/setcounter.h @@ -52,10 +52,16 @@ typedef struct _GScanSetMatchCounterClass GScanSetMatchCounterClass; GType g_scan_set_match_counter_get_type(void); /* Met en place un décompte de correspondances obtenues. */ +GScanExpression *g_scan_set_match_counter_new_shared(const GSearchPattern ** const, size_t); + +/* Met en place un décompte de correspondances obtenues. */ GScanExpression *g_scan_set_match_counter_new(GSearchPattern ** const, size_t); /* Ajoute de nouveaux motifs à un ensemble à décompter. */ -void g_scan_set_match_counter_add_extra_patterns(GScanSetMatchCounter *, GSearchPattern ** const, size_t); +void g_scan_set_match_counter_add_extra_shared_patterns(GScanSetMatchCounter *, const GSearchPattern ** const, size_t); + +/* Ajoute de nouveaux motifs à un ensemble à décompter. */ +void g_scan_set_match_counter_add_and_ref_extra_patterns(GScanSetMatchCounter *, GSearchPattern ** const, size_t); /* Formes de volume de correspondances */ typedef enum _ScanSetCounterType |
