diff options
Diffstat (limited to 'src/analysis/scan/exprs')
-rw-r--r-- | src/analysis/scan/exprs/Makefile.am | 2 | ||||
-rw-r--r-- | src/analysis/scan/exprs/call.c | 2 | ||||
-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 |
5 files changed, 512 insertions, 1 deletions
diff --git a/src/analysis/scan/exprs/Makefile.am b/src/analysis/scan/exprs/Makefile.am index a0b2f3d..37f4133 100644 --- a/src/analysis/scan/exprs/Makefile.am +++ b/src/analysis/scan/exprs/Makefile.am @@ -11,6 +11,8 @@ libanalysisscanexprs_la_SOURCES = \ 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/call.c b/src/analysis/scan/exprs/call.c index 74e0cba..e335933 100644 --- a/src/analysis/scan/exprs/call.c +++ b/src/analysis/scan/exprs/call.c @@ -271,9 +271,9 @@ static ScanReductionState g_scan_pending_call_reduce(const GScanPendingCall *exp 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); 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 */ |