diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2023-08-06 16:54:57 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2023-08-06 16:54:57 (GMT) |
commit | 4fcc35a52ccb025b6d803d85e017931cd2452960 (patch) | |
tree | e95920f16c273e41f9cae1ea2f02571c221a514e /src/analysis/scan/exprs | |
parent | 74d062d4ec55d7ac3914bbf64b8b6c5ab52227df (diff) |
Extend the ROST grammar with a first batch of new features.
Diffstat (limited to 'src/analysis/scan/exprs')
35 files changed, 3242 insertions, 1086 deletions
diff --git a/src/analysis/scan/exprs/Makefile.am b/src/analysis/scan/exprs/Makefile.am index efe25fc..1266a63 100644 --- a/src/analysis/scan/exprs/Makefile.am +++ b/src/analysis/scan/exprs/Makefile.am @@ -5,16 +5,24 @@ noinst_LTLIBRARIES = libanalysisscanexprs.la libanalysisscanexprs_la_SOURCES = \ access-int.h \ access.h access.c \ - arithmop-int.h \ - arithmop.h arithmop.c \ - boolop-int.h \ - boolop.h boolop.c \ + arithmetic-int.h \ + arithmetic.h arithmetic.c \ call-int.h \ call.h call.c \ + counter-int.h \ + counter.h counter.c \ + intersect-int.h \ + intersect.h intersect.c \ literal-int.h \ literal.h literal.c \ - relop-int.h \ - relop.h relop.c \ + logical-int.h \ + logical.h logical.c \ + range-int.h \ + range.h range.c \ + relational-int.h \ + relational.h relational.c \ + set-int.h \ + set.h set.c \ strop-int.h \ strop.h strop.c diff --git a/src/analysis/scan/exprs/access-int.h b/src/analysis/scan/exprs/access-int.h index 2212b48..725051c 100644 --- a/src/analysis/scan/exprs/access-int.h +++ b/src/analysis/scan/exprs/access-int.h @@ -32,8 +32,11 @@ +/* Reproduit un accès en place dans une nouvelle instance. */ +typedef void (* copy_scan_access_fc) (GScanNamedAccess *, const GScanNamedAccess *); + /* Accès à un élément d'expression sous-jacent (instance) */ -struct _GNamedAccess +struct _GScanNamedAccess { GScanExpression parent; /* A laisser en premier */ @@ -46,23 +49,25 @@ struct _GNamedAccess char *target; /* Cible dans l'espace */ - struct _GNamedAccess *next; /* Evnetuel prochain élément */ + struct _GScanNamedAccess *next; /* Evnetuel prochain élément */ }; /* Accès à un élément d'expression sous-jacent (classe) */ -struct _GNamedAccessClass +struct _GScanNamedAccessClass { GScanExpressionClass parent; /* A laisser en premier */ + copy_scan_access_fc copy; /* Reproduction d'accès */ + }; /* Met en place une expression d'accès. */ -bool g_named_access_create(GNamedAccess *, const sized_string_t *); +bool g_scan_named_access_create(GScanNamedAccess *, const sized_string_t *); -/* Réduit une expression à une forme plus simple. */ -bool _g_named_access_reduce(GNamedAccess *, GScanContext *, GScanScope *, GScanExpression **); +/* Prépare une réduction en menant une résolution locale. */ +GRegisteredItem *_g_scan_named_access_prepare_reduction(GScanNamedAccess *, GScanContext *, GScanScope *); diff --git a/src/analysis/scan/exprs/access.c b/src/analysis/scan/exprs/access.c index ad66f60..1c3a880 100644 --- a/src/analysis/scan/exprs/access.c +++ b/src/analysis/scan/exprs/access.c @@ -30,6 +30,7 @@ #include "access-int.h" +#include "literal.h" #include "../../../core/global.h" @@ -38,27 +39,27 @@ /* Initialise la classe des appels de fonction avec arguments. */ -static void g_named_access_class_init(GNamedAccessClass *); +static void g_scan_named_access_class_init(GScanNamedAccessClass *); /* Initialise une instance d'appel de fonction avec arguments. */ -static void g_named_access_init(GNamedAccess *); +static void g_scan_named_access_init(GScanNamedAccess *); /* Supprime toutes les références externes. */ -static void g_named_access_dispose(GNamedAccess *); +static void g_scan_named_access_dispose(GScanNamedAccess *); /* Procède à la libération totale de la mémoire. */ -static void g_named_access_finalize(GNamedAccess *); +static void g_scan_named_access_finalize(GScanNamedAccess *); +/* Reproduit un accès en place dans une nouvelle instance. */ +static void g_scan_named_access_copy(GScanNamedAccess *, const GScanNamedAccess *); -/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ +/* --------------------- 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 **); +static ScanReductionState g_scan_named_access_reduce(GScanNamedAccess *, GScanContext *, GScanScope *, GScanExpression **); @@ -68,7 +69,7 @@ static bool g_named_access_reduce(GNamedAccess *, GScanContext *, GScanScope *, /* Indique le type défini pour un appel de fonction enregistrée. */ -G_DEFINE_TYPE(GNamedAccess, g_named_access, G_TYPE_SCAN_EXPRESSION); +G_DEFINE_TYPE(GScanNamedAccess, g_scan_named_access, G_TYPE_SCAN_EXPRESSION); /****************************************************************************** @@ -83,21 +84,22 @@ G_DEFINE_TYPE(GNamedAccess, g_named_access, G_TYPE_SCAN_EXPRESSION); * * ******************************************************************************/ -static void g_named_access_class_init(GNamedAccessClass *klass) +static void g_scan_named_access_class_init(GScanNamedAccessClass *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; + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_named_access_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_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; + expr->reduce = (reduce_expr_fc)g_scan_named_access_reduce; + + klass->copy = g_scan_named_access_copy; } @@ -114,7 +116,7 @@ static void g_named_access_class_init(GNamedAccessClass *klass) * * ******************************************************************************/ -static void g_named_access_init(GNamedAccess *access) +static void g_scan_named_access_init(GScanNamedAccess *access) { access->any = NULL; access->target = NULL; @@ -136,13 +138,13 @@ static void g_named_access_init(GNamedAccess *access) * * ******************************************************************************/ -static void g_named_access_dispose(GNamedAccess *access) +static void g_scan_named_access_dispose(GScanNamedAccess *access) { g_clear_object(&access->any); g_clear_object(&access->next); - G_OBJECT_CLASS(g_named_access_parent_class)->dispose(G_OBJECT(access)); + G_OBJECT_CLASS(g_scan_named_access_parent_class)->dispose(G_OBJECT(access)); } @@ -159,12 +161,12 @@ static void g_named_access_dispose(GNamedAccess *access) * * ******************************************************************************/ -static void g_named_access_finalize(GNamedAccess *access) +static void g_scan_named_access_finalize(GScanNamedAccess *access) { if (access->target != NULL) free(access->target); - G_OBJECT_CLASS(g_named_access_parent_class)->finalize(G_OBJECT(access)); + G_OBJECT_CLASS(g_scan_named_access_parent_class)->finalize(G_OBJECT(access)); } @@ -181,13 +183,13 @@ static void g_named_access_finalize(GNamedAccess *access) * * ******************************************************************************/ -GScanExpression *g_named_access_new(const sized_string_t *target) +GScanExpression *g_scan_named_access_new(const sized_string_t *target) { GScanExpression *result; /* Structure à retourner */ - result = g_object_new(G_TYPE_NAMED_ACCESS, NULL); + result = g_object_new(G_TYPE_SCAN_NAMED_ACCESS, NULL); - if (!g_named_access_create(G_NAMED_ACCESS(result), target)) + if (!g_scan_named_access_create(G_SCAN_NAMED_ACCESS(result), target)) g_clear_object(&result); return result; @@ -208,16 +210,14 @@ GScanExpression *g_named_access_new(const sized_string_t *target) * * ******************************************************************************/ -bool g_named_access_create(GNamedAccess *access, const sized_string_t *target) +bool g_scan_named_access_create(GScanNamedAccess *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); + result = true; - exit: + if (target != NULL) + access->target = strndup(target->data, target->len); return result; @@ -226,10 +226,10 @@ bool g_named_access_create(GNamedAccess *access, const sized_string_t *target) /****************************************************************************** * * -* Paramètres : access = expression d'appel à actualiser. * -* base = zone de recherche pour la résolution à venir. * +* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] * +* src = expression source à copier. * * * -* Description : Définit une base de recherche pour la cible d'accès. * +* Description : Reproduit un accès en place dans une nouvelle instance. * * * * Retour : - * * * @@ -237,55 +237,74 @@ bool g_named_access_create(GNamedAccess *access, const sized_string_t *target) * * ******************************************************************************/ -void g_named_access_set_base(GNamedAccess *access, GRegisteredItem *base) +static void g_scan_named_access_copy(GScanNamedAccess *dest, const GScanNamedAccess *src) { - g_clear_object(&access->base); + /** + * Les champs suivants sont voués à être remplacés ou supprimés. + * + * On évite donc une instanciation inutile. + */ - access->base = base; - g_object_ref(G_OBJECT(base)); + /* + 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 = src->next; + g_object_ref(src->next); + } } /****************************************************************************** * * -* Paramètres : access = expression d'appel à compléter. * -* next = expression d'appel suivante dans la chaîne. * +* Paramètres : accès = expression d'accès à copier. * +* resolved = nouvelle base à imposer. * * * -* Description : Complète la chaine d'accès à des expressions. * +* Description : Reproduit un accès en place dans une nouvelle instance. * * * -* Retour : - * +* Retour : Nouvelle instance d'expression d'accès. * * * * Remarques : - * * * ******************************************************************************/ -void g_named_access_attach_next(GNamedAccess *access, GNamedAccess *next) +GScanExpression *g_scan_named_access_duplicate(const GScanNamedAccess *access, GRegisteredItem *resolved) { - if (access->next != NULL) - g_named_access_attach_next(access->next, next); + GScanExpression *result; /* Instance copiée à retourner */ + GType type; /* Type d'objet à copier */ + GScanNamedAccessClass *class; /* Classe à activer */ - else - { - access->next = next; - g_object_ref(G_OBJECT(next)); - } + type = G_TYPE_FROM_INSTANCE(access); -} + result = g_object_new(type, NULL); + class = G_SCAN_NAMED_ACCESS_GET_CLASS(access); + class->copy(G_SCAN_NAMED_ACCESS(result), access); -/* ---------------------------------------------------------------------------------- */ -/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ -/* ---------------------------------------------------------------------------------- */ + g_scan_named_access_set_base(G_SCAN_NAMED_ACCESS(result), resolved); + + return result; + +} /****************************************************************************** * * -* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] * -* src = expression source à copier. * +* Paramètres : access = expression d'appel à actualiser. * +* base = zone de recherche pour la résolution à venir. * * * -* Description : Reproduit une expression en place dans une nouvelle instance.* +* Description : Définit une base de recherche pour la cible d'accès. * * * * Retour : - * * * @@ -293,27 +312,47 @@ void g_named_access_attach_next(GNamedAccess *access, GNamedAccess *next) * * ******************************************************************************/ -static void g_named_access_copy(GNamedAccess *dest, const GNamedAccess *src) +void g_scan_named_access_set_base(GScanNamedAccess *access, GRegisteredItem *base) { - GScanExpressionClass *class; /* Classe parente à solliciter */ + g_clear_object(&access->base); - class = G_SCAN_EXPRESSION_CLASS(g_named_access_parent_class); + access->base = base; + g_object_ref(G_OBJECT(base)); - class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src)); +} - if (src->any != NULL) + +/****************************************************************************** +* * +* 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_scan_named_access_attach_next(GScanNamedAccess *access, GScanNamedAccess *next) +{ + if (access->next != NULL) + g_scan_named_access_attach_next(access->next, next); + + else { - dest->any = src->any; - g_object_ref(src->any); + access->next = next; + g_object_ref(G_OBJECT(next)); } - 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))); -} + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** @@ -321,24 +360,21 @@ static void g_named_access_copy(GNamedAccess *dest, const GNamedAccess *src) * 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. * +* Description : Prépare une réduction en menant une résolution locale. * * * -* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* Retour : Elément résolu avec les moyens du bord ou NULL si échec. * * * * Remarques : - * * * ******************************************************************************/ -bool _g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +GRegisteredItem *_g_scan_named_access_prepare_reduction(GScanNamedAccess *expr, GScanContext *ctx, GScanScope *scope) { - bool result; /* Bilan à retourner */ + GRegisteredItem *result; /* Etat synthétisé à retourner */ GRegisteredItem *base; /* Base de recherche courante */ - GRegisteredItem *resolved; /* Cible concrète obtenue */ - GNamedAccess *new; /* Copie mise en place */ - result = true; + result = NULL; if (expr->target != NULL) { @@ -350,24 +386,7 @@ bool _g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *s 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); - - } + g_registered_item_resolve(base, expr->target, ctx, scope, &result); } @@ -379,8 +398,8 @@ bool _g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *s { assert(expr->resolved != NULL); - *out = G_SCAN_EXPRESSION(expr); - g_object_ref(G_OBJECT(*out)); + result = expr->resolved; + g_object_ref(G_OBJECT(result)); } @@ -404,25 +423,18 @@ bool _g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *s * * ******************************************************************************/ -static bool g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +static ScanReductionState g_scan_named_access_reduce(GScanNamedAccess *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - bool result; /* Bilan à retourner */ - GNamedAccess *new; /* Eventuel étage suivant */ - GScanExpression *final; /* Expression d'évaluation */ + ScanReductionState result; /* Etat synthétisé à retourner */ + GRegisteredItem *resolved; /* Cible concrète obtenue */ GScanExpression *new_next; /* Nouvelle version du suivant */ + bool status; /* Bilan d'une autre règle */ - result = _g_named_access_reduce(expr, ctx, scope, out); + resolved = _g_scan_named_access_prepare_reduction(expr, ctx, scope); - if (result && *out != NULL) + if (resolved != 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)); + result = SRS_PENDING; /** * Si l'élément résolu se trouve en fin de chaîne, alors cet élément @@ -430,15 +442,11 @@ static bool g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanSc * 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) + if (expr->next == NULL) { - result = g_registered_item_reduce(new->resolved, ctx, scope, &final); + status = g_registered_item_reduce(resolved, ctx, scope, out); - if (result && final != NULL) - { - g_clear_object(out); - *out = final; - } + result = (status ? SRS_REDUCED : SRS_UNRESOLVABLE); } @@ -448,21 +456,34 @@ static bool g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanSc */ 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); + new_next = g_scan_named_access_duplicate(expr->next, resolved); result = g_scan_expression_reduce(new_next, ctx, scope, out); - if (result && *out == NULL) - *out = new_next; + g_object_unref(G_OBJECT(new_next)); } - g_object_unref(G_OBJECT(new)); + g_object_unref(G_OBJECT(resolved)); + + } + + /** + * Si le nom fournit le correspond à aucun élément de la grammaire, + * des recherches sont menées ailleurs. + */ + else + { + result = SRS_UNRESOLVABLE; + + if (g_scan_context_has_rule_for_name(ctx, expr->target)) + { + status = g_scan_context_has_match_for_rule(ctx, expr->target); + + *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status); + result = SRS_REDUCED; + + } } diff --git a/src/analysis/scan/exprs/access.h b/src/analysis/scan/exprs/access.h index a04adc7..7c007a9 100644 --- a/src/analysis/scan/exprs/access.h +++ b/src/analysis/scan/exprs/access.h @@ -31,32 +31,35 @@ -#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)) +#define G_TYPE_SCAN_NAMED_ACCESS g_scan_named_access_get_type() +#define G_SCAN_NAMED_ACCESS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_NAMED_ACCESS, GScanNamedAccess)) +#define G_IS_SCAN_NAMED_ACCESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_NAMED_ACCESS)) +#define G_SCAN_NAMED_ACCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_NAMED_ACCESS, GScanNamedAccessClass)) +#define G_IS_SCAN_NAMED_ACCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_NAMED_ACCESS)) +#define G_SCAN_NAMED_ACCESS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_NAMED_ACCESS, GScanNamedAccessClass)) /* Accès à un élément d'expression sous-jacent (instance) */ -typedef struct _GNamedAccess GNamedAccess; +typedef struct _GScanNamedAccess GScanNamedAccess; /* Accès à un élément d'expression sous-jacent (classe) */ -typedef struct _GNamedAccessClass GNamedAccessClass; +typedef struct _GScanNamedAccessClass GScanNamedAccessClass; /* Indique le type défini pour un appel de fonction enregistrée. */ -GType g_named_access_get_type(void); +GType g_scan_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 *); +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 *); /* Définit une base de recherche pour la cible d'accès. */ -void g_named_access_set_base(GNamedAccess *, GRegisteredItem *); +void g_scan_named_access_set_base(GScanNamedAccess *, GRegisteredItem *); /* Complète la chaine d'accès à des expressions. */ -void g_named_access_attach_next(GNamedAccess *, GNamedAccess *); +void g_scan_named_access_attach_next(GScanNamedAccess *, GScanNamedAccess *); diff --git a/src/analysis/scan/exprs/arithmop-int.h b/src/analysis/scan/exprs/arithmetic-int.h index 031de84..c5010b0 100644 --- a/src/analysis/scan/exprs/arithmop-int.h +++ b/src/analysis/scan/exprs/arithmetic-int.h @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * arithmop-int.h - prototypes internes pour la gestion des opérations arithmétiques + * arithmetic-int.h - prototypes internes pour la gestion des opérations arithmétiques * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,11 +21,11 @@ */ -#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMOP_INT_H -#define _ANALYSIS_SCAN_EXPRS_ARITHMOP_INT_H +#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMETIC_INT_H +#define _ANALYSIS_SCAN_EXPRS_ARITHMETIC_INT_H -#include "arithmop.h" +#include "arithmetic.h" #include "../expr-int.h" @@ -33,7 +33,7 @@ /* Opération arithmétique impliquant deux opérandes (instance) */ -struct _GArithmOperation +struct _GScanArithmeticOperation { GScanExpression parent; /* A laisser en premier */ @@ -45,7 +45,7 @@ struct _GArithmOperation }; /* Opération arithmétique impliquant deux opérandes (classe) */ -struct _GArithmOperationClass +struct _GScanArithmeticOperationClass { GScanExpressionClass parent; /* A laisser en premier */ @@ -53,8 +53,8 @@ struct _GArithmOperationClass /* Met en place une opération arithmétique entre expressions. */ -bool g_arithmetic_operation_create(GArithmOperation *, ArithmeticExpressionOperator, GScanExpression *, GScanExpression *); +bool g_scan_arithmetic_operation_create(GScanArithmeticOperation *, ArithmeticExpressionOperator, GScanExpression *, GScanExpression *); -#endif /* _ANALYSIS_SCAN_EXPRS_ARITHMOP_INT_H */ +#endif /* _ANALYSIS_SCAN_EXPRS_ARITHMETIC_INT_H */ diff --git a/src/analysis/scan/exprs/arithmetic.c b/src/analysis/scan/exprs/arithmetic.c new file mode 100644 index 0000000..0c01d2a --- /dev/null +++ b/src/analysis/scan/exprs/arithmetic.c @@ -0,0 +1,638 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * arithmetic.c - gestion des opérations arithmétiques + * + * 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 "arithmetic.h" + + +#include <assert.h> + + +#include "arithmetic-int.h" +#include "literal.h" + + + +/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */ + + +/* Initialise la classe des opérations arithmétiques. */ +static void g_scan_arithmetic_operation_class_init(GScanArithmeticOperationClass *); + +/* Initialise une instance d'opération arithmétique. */ +static void g_scan_arithmetic_operation_init(GScanArithmeticOperation *); + +/* Supprime toutes les références externes. */ +static void g_scan_arithmetic_operation_dispose(GScanArithmeticOperation *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_arithmetic_operation_finalize(GScanArithmeticOperation *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Réalise une comparaison entre objets selon un critère précis. */ +static bool g_scan_arithmetic_operation_compare_rich(const GScanArithmeticOperation *, const GScanArithmeticOperation *, RichCmpOperation, bool *); + +/* Réduit une expression à une forme plus simple. */ +static ScanReductionState g_scan_arithmetic_operation_reduce(GScanArithmeticOperation *, GScanContext *, GScanScope *, GScanExpression **); + + + +/* ---------------------------------------------------------------------------------- */ +/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une opération de relation entre expressions. */ +G_DEFINE_TYPE(GScanArithmeticOperation, g_scan_arithmetic_operation, G_TYPE_SCAN_EXPRESSION); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des opérations arithmétiques. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_arithmetic_operation_class_init(GScanArithmeticOperationClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanExpressionClass *expr; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_arithmetic_operation_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_arithmetic_operation_finalize; + + expr = G_SCAN_EXPRESSION_CLASS(klass); + + expr->cmp_rich = (compare_expr_rich_fc)g_scan_arithmetic_operation_compare_rich; + expr->reduce = (reduce_expr_fc)g_scan_arithmetic_operation_reduce; + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance à initialiser. * +* * +* Description : Initialise une instance d'opération arithmétique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_arithmetic_operation_init(GScanArithmeticOperation *op) +{ + op->left = NULL; + op->right = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_arithmetic_operation_dispose(GScanArithmeticOperation *op) +{ + g_clear_object(&op->left); + g_clear_object(&op->right); + + G_OBJECT_CLASS(g_scan_arithmetic_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_scan_arithmetic_operation_finalize(GScanArithmeticOperation *op) +{ + G_OBJECT_CLASS(g_scan_arithmetic_operation_parent_class)->finalize(G_OBJECT(op)); + +} + + +/****************************************************************************** +* * +* Paramètres : operator = type d'opération arithmétique à représenter. * +* left = premier opérande concerné. * +* right = éventuel second opérande impliqué ou NULL. * +* * +* Description : Organise une opération arithmétique entre expressions. * +* * +* Retour : Fonction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_scan_arithmetic_operation_new(ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right) +{ + GScanExpression *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_ARITHMETIC_OPERATION, NULL); + + if (!g_scan_arithmetic_operation_create(G_SCAN_ARITHMETIC_OPERATION(result), operator, left, right)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance à initialiser pleinement. * +* operator = 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 arithmétique entre expressions. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_scan_arithmetic_operation_create(GScanArithmeticOperation *op, ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right) +{ + bool result; /* Bilan à retourner */ + + result = true; + + op->operator = operator; + + op->left = left; + g_object_ref(G_OBJECT(op->left)); + + op->right = right; + g_object_ref(G_OBJECT(op->right)); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : item = premier objet à consulter pour une comparaison. * +* other = second objet à consulter pour une comparaison. * +* op = opération de comparaison à réaliser. * +* status = bilan des opérations de comparaison. [OUT] * +* * +* Description : Réalise une comparaison entre objets selon un critère précis.* +* * +* Retour : true si la comparaison a pu être effectuée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_scan_arithmetic_operation_compare_rich(const GScanArithmeticOperation *item, const GScanArithmeticOperation *other, RichCmpOperation op, bool *status) +{ + bool result; /* Etat à retourner */ + + result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_SCAN_ARITHMETIC_OPERATION); + if (!result) goto done; + + if (item->operator != other->operator) + { + result = compare_rich_integer_values_unsigned(item->operator, other->operator, op); + goto done; + } + + 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; + + 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->right), + G_COMPARABLE_ITEM(other->right), + op, status); + + done: + + 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 ScanReductionState g_scan_arithmetic_operation_reduce(GScanArithmeticOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +{ + ScanReductionState result; /* Etat synthétisé à retourner */ + GScanExpression *new_left; /* Expression réduite (gauche) */ + GScanExpression *new_right; /* Expression réduite (droite) */ + ScanReductionState state_left; /* Etat synthétisé #1 */ + ScanReductionState state_right; /* Etat synthétisé #2 */ + GScanLiteralExpression *op_left; /* Opérande gauche final */ + GScanLiteralExpression *op_right; /* Opérande droite final */ + LiteralValueType vtype_left; /* Type de valeur portée #1 */ + LiteralValueType vtype_right; /* Type de valeur portée #2 */ + long long val_1_s; /* Première valeur à traiter */ + unsigned long long val_1_u; /* Première valeur à traiter */ + long long val_2_s; /* Seconde valeur à traiter */ + unsigned long long val_2_u; /* Seconde valeur à traiter */ + LiteralValueType state_final; /* Nature de la valeur finale */ + long long reduced_s; /* Valeur réduite finale */ + unsigned long long reduced_u; /* Valeur réduite finale */ + + /* Réduction des éléments considérés */ + + new_left = NULL; + new_right = NULL; + + state_left = g_scan_expression_reduce(expr->left, ctx, scope, &new_left); + if (state_left == SRS_UNRESOLVABLE) + { + result = SRS_UNRESOLVABLE; + goto exit; + } + + state_right = g_scan_expression_reduce(expr->right, ctx, scope, &new_right); + if (state_right == SRS_UNRESOLVABLE) + { + result = SRS_UNRESOLVABLE; + goto exit; + } + + /* Construction d'une réduction locale ? */ + + if (G_IS_SCAN_LITERAL_EXPRESSION(new_left) && G_IS_SCAN_LITERAL_EXPRESSION(new_right)) + { + /* Récupération de l'opérande de gauche */ + + op_left = G_SCAN_LITERAL_EXPRESSION(new_left); + vtype_left = g_scan_literal_expression_get_value_type(op_left); + + if (vtype_left == LVT_SIGNED_INTEGER) + { + if (!g_scan_literal_expression_get_signed_integer_value(op_left, &val_1_s)) + { + result = SRS_UNRESOLVABLE; + goto exit; + } + } + else if (vtype_left == LVT_UNSIGNED_INTEGER) + { + if (!g_scan_literal_expression_get_unsigned_integer_value(op_left, &val_1_u)) + { + result = SRS_UNRESOLVABLE; + goto exit; + } + } + else + { + result = SRS_UNRESOLVABLE; + goto exit; + } + + /* Récupération de l'opérande de droite */ + + op_right = G_SCAN_LITERAL_EXPRESSION(new_right); + vtype_right = g_scan_literal_expression_get_value_type(op_right); + + if (vtype_right == LVT_SIGNED_INTEGER) + { + if (!g_scan_literal_expression_get_signed_integer_value(op_right, &val_2_s)) + { + result = SRS_UNRESOLVABLE; + goto exit; + } + } + else if (vtype_right == LVT_UNSIGNED_INTEGER) + { + if (!g_scan_literal_expression_get_unsigned_integer_value(op_right, &val_2_u)) + { + result = SRS_UNRESOLVABLE; + goto exit; + } + } + else + { + result = SRS_UNRESOLVABLE; + goto exit; + } + + /* Partie des calculs */ + + result = SRS_REDUCED; + + switch (expr->operator) + { + case AEO_PLUS: + if (vtype_left == LVT_SIGNED_INTEGER) + { + if (vtype_right == LVT_SIGNED_INTEGER) + { + state_final = LVT_SIGNED_INTEGER; + reduced_s = val_1_s + val_2_s; + } + else + { + assert(vtype_right == LVT_UNSIGNED_INTEGER); + + if ((long long)val_2_u > val_1_s) + { + state_final = LVT_UNSIGNED_INTEGER; + reduced_u = val_1_s + (long long)val_2_u; + } + else + { + state_final = LVT_SIGNED_INTEGER; + reduced_s = val_1_s + (long long)val_2_u; + } + + } + } + else + { + assert(vtype_left == LVT_UNSIGNED_INTEGER); + + if (vtype_right == LVT_SIGNED_INTEGER) + { + if ((long long)val_1_u > val_2_s) + { + state_final = LVT_UNSIGNED_INTEGER; + reduced_u = (long long)val_1_u + val_2_s; + } + else + { + state_final = LVT_SIGNED_INTEGER; + reduced_s = (long long)val_1_u + val_2_s; + } + + } + else + { + assert(vtype_right == LVT_UNSIGNED_INTEGER); + + state_final = LVT_UNSIGNED_INTEGER; + reduced_u = val_1_u + val_2_u; + + } + } + break; + + case AEO_MINUS: + if (vtype_left == LVT_SIGNED_INTEGER) + { + if (vtype_right == LVT_SIGNED_INTEGER) + { + if (val_2_s < val_1_s) + { + state_final = LVT_UNSIGNED_INTEGER; + reduced_u = val_1_s - val_2_s; + } + else + { + state_final = LVT_SIGNED_INTEGER; + reduced_s = val_1_s - val_2_s; + } + + } + else + { + assert(vtype_right == LVT_UNSIGNED_INTEGER); + + state_final = LVT_SIGNED_INTEGER; + reduced_s = val_1_s - (long long)val_2_u; + + } + } + else + { + assert(vtype_left == LVT_UNSIGNED_INTEGER); + + if (vtype_right == LVT_SIGNED_INTEGER) + { + state_final = LVT_UNSIGNED_INTEGER; + reduced_u = (long long)val_1_u - val_2_s; + } + else + { + assert(vtype_right == LVT_UNSIGNED_INTEGER); + + if (val_1_u > val_2_u) + { + state_final = LVT_UNSIGNED_INTEGER; + reduced_u = val_1_u - val_2_u; + } + else + { + state_final = LVT_SIGNED_INTEGER; + reduced_s = val_1_u - val_2_u; + } + + } + } + break; + + case AEO_MUL: + if (vtype_left == LVT_SIGNED_INTEGER) + { + if (vtype_right == LVT_SIGNED_INTEGER) + { + state_final = LVT_UNSIGNED_INTEGER; + reduced_u = val_1_s * val_2_s; + } + else + { + assert(vtype_right == LVT_UNSIGNED_INTEGER); + + state_final = LVT_SIGNED_INTEGER; + reduced_s = val_1_s * (long long)val_2_u; + + } + } + else + { + assert(vtype_left == LVT_UNSIGNED_INTEGER); + + if (vtype_right == LVT_SIGNED_INTEGER) + { + state_final = LVT_SIGNED_INTEGER; + reduced_s = (long long)val_1_u * val_2_s; + } + else + { + assert(vtype_right == LVT_UNSIGNED_INTEGER); + + state_final = LVT_UNSIGNED_INTEGER; + reduced_u = val_1_u * val_2_u; + + } + } + break; + + case AEO_DIV: + if ((vtype_right == LVT_SIGNED_INTEGER && val_2_s == 0) + || (vtype_right == LVT_UNSIGNED_INTEGER && val_2_u == 0)) + { + result = SRS_UNRESOLVABLE; + break; + } + + if (vtype_left == LVT_SIGNED_INTEGER) + { + if (vtype_right == LVT_SIGNED_INTEGER) + { + state_final = LVT_UNSIGNED_INTEGER; + reduced_u = val_1_s / val_2_s; + } + else + { + assert(vtype_right == LVT_UNSIGNED_INTEGER); + + state_final = LVT_SIGNED_INTEGER; + reduced_s = val_1_s / (long long)val_2_u; + + } + } + else + { + assert(vtype_left == LVT_UNSIGNED_INTEGER); + + if (vtype_right == LVT_SIGNED_INTEGER) + { + state_final = LVT_SIGNED_INTEGER; + reduced_s = (long long)val_1_u / val_2_s; + } + else + { + assert(vtype_right == LVT_UNSIGNED_INTEGER); + + state_final = LVT_UNSIGNED_INTEGER; + reduced_u = val_1_u / val_2_u; + + } + } + break; + + case AEO_MOD: + result = SRS_UNRESOLVABLE; + /* FIXME + result = (val_2 != 0); + if (result) + reduced = val_1 % val_2; + */ + break; + + } + + if (result == SRS_REDUCED) + { + if (state_final == LVT_SIGNED_INTEGER) + *out = g_scan_literal_expression_new(LVT_SIGNED_INTEGER, &reduced_s); + else + { + assert(state_final == LVT_UNSIGNED_INTEGER); + *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &reduced_u); + } + + } + + } + + /* Mise à jour de la progression ? */ + + else if (state_left == SRS_WAIT_FOR_SCAN || state_right == SRS_WAIT_FOR_SCAN) + { + if (new_left != expr->left || new_right != expr->right) + *out = g_scan_arithmetic_operation_new(expr->operator, new_left, new_right); + + result = SRS_WAIT_FOR_SCAN; + + } + + /* Cas des situations où les expressions ne sont pas exploitables (!) */ + else + { + assert(state_left == SRS_REDUCED && state_right == SRS_REDUCED); + + result = SRS_UNRESOLVABLE; + + } + + /* Sortie propre */ + + exit: + + g_clear_object(&new_left); + g_clear_object(&new_right); + + return result; + +} diff --git a/src/analysis/scan/exprs/arithmop.h b/src/analysis/scan/exprs/arithmetic.h index dcc8bf8..8a1e844 100644 --- a/src/analysis/scan/exprs/arithmop.h +++ b/src/analysis/scan/exprs/arithmetic.h @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * arithmop.h - prototypes pour la gestion des opérations arithmétiques + * arithmetic.h - prototypes pour la gestion des opérations arithmétiques * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,27 +21,27 @@ */ -#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMOP_H -#define _ANALYSIS_SCAN_EXPRS_ARITHMOP_H +#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMETIC_H +#define _ANALYSIS_SCAN_EXPRS_ARITHMETIC_H #include "../expr.h" -#define G_TYPE_ARITHMETIC_OPERATION g_arithmetic_operation_get_type() -#define G_ARITHMETIC_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARITHMETIC_OPERATION, GArithmOperation)) -#define G_IS_ARITHMETIC_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARITHMETIC_OPERATION)) -#define G_ARITHMETIC_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARITHMETIC_OPERATION, GArithmOperationClass)) -#define G_IS_ARITHMETIC_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARITHMETIC_OPERATION)) -#define G_ARITHMETIC_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARITHMETIC_OPERATION, GArithmOperationClass)) +#define G_TYPE_SCAN_ARITHMETIC_OPERATION g_scan_arithmetic_operation_get_type() +#define G_SCAN_ARITHMETIC_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_ARITHMETIC_OPERATION, GScanArithmeticOperation)) +#define G_IS_SCAN_ARITHMETIC_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_ARITHMETIC_OPERATION)) +#define G_SCAN_ARITHMETIC_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_ARITHMETIC_OPERATION, GScanArithmeticOperationClass)) +#define G_IS_SCAN_ARITHMETIC_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_ARITHMETIC_OPERATION)) +#define G_SCAN_ARITHMETIC_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_ARITHMETIC_OPERATION, GScanArithmeticOperationClass)) /* Opération arithmétique impliquant deux opérandes (instance) */ -typedef struct _GArithmOperation GArithmOperation; +typedef struct _GScanArithmeticOperation GScanArithmeticOperation; /* Opération arithmétique impliquant deux opérandes (classe) */ -typedef struct _GArithmOperationClass GArithmOperationClass; +typedef struct _GScanArithmeticOperationClass GScanArithmeticOperationClass; /* Type d'opération arithmétique */ @@ -57,11 +57,11 @@ typedef enum _ArithmeticExpressionOperator /* Indique le type défini pour une opération arithmétique entre expressions. */ -GType g_arithmetic_operation_get_type(void); +GType g_scan_arithmetic_operation_get_type(void); /* Organise une opération arithmétique entre expressions. */ -GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator, GScanExpression *, GScanExpression *); +GScanExpression *g_scan_arithmetic_operation_new(ArithmeticExpressionOperator, GScanExpression *, GScanExpression *); -#endif /* _ANALYSIS_SCAN_EXPRS_ARITHMOP_H */ +#endif /* _ANALYSIS_SCAN_EXPRS_ARITHMETIC_H */ diff --git a/src/analysis/scan/exprs/call-int.h b/src/analysis/scan/exprs/call-int.h index 631a25b..9646b95 100644 --- a/src/analysis/scan/exprs/call-int.h +++ b/src/analysis/scan/exprs/call-int.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * call-int.h - prototypes internes pour l'organisation d'un appel à un élément de scan enregistré * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -33,9 +33,9 @@ /* Exécution d'une fonction auxiliaire d'analyse (instance) */ -struct _GPendingCall +struct _GScanPendingCall { - GNamedAccess parent; /* A laisser en premier */ + GScanNamedAccess parent; /* A laisser en premier */ GScanExpression **args; /* Arguments d'appel fournis */ size_t count; /* Quantité de ces arguments */ @@ -43,15 +43,15 @@ struct _GPendingCall }; /* Exécution d'une fonction auxiliaire d'analyse (classe) */ -struct _GPendingCallClass +struct _GScanPendingCallClass { - GNamedAccessClass parent; /* A laisser en premier */ + GScanNamedAccessClass parent; /* A laisser en premier */ }; /* Met en place une expression d'appel. */ -bool g_pending_call_create(GPendingCall *, const sized_string_t *, GScanExpression **, size_t); +bool g_scan_pending_call_create(GScanPendingCall *, const sized_string_t *, GScanExpression **, size_t); diff --git a/src/analysis/scan/exprs/call.c b/src/analysis/scan/exprs/call.c index dde627c..2fd1ff1 100644 --- a/src/analysis/scan/exprs/call.c +++ b/src/analysis/scan/exprs/call.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * call.c - organisation d'un appel à un élément de scan enregistré * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -38,27 +38,27 @@ /* Initialise la classe des appels de fonction avec arguments. */ -static void g_pending_call_class_init(GPendingCallClass *); +static void g_scan_pending_call_class_init(GScanPendingCallClass *); /* Initialise une instance d'appel de fonction avec arguments. */ -static void g_pending_call_init(GPendingCall *); +static void g_scan_pending_call_init(GScanPendingCall *); /* Supprime toutes les références externes. */ -static void g_pending_call_dispose(GPendingCall *); +static void g_scan_pending_call_dispose(GScanPendingCall *); /* Procède à la libération totale de la mémoire. */ -static void g_pending_call_finalize(GPendingCall *); +static void g_scan_pending_call_finalize(GScanPendingCall *); /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ -/* Reproduit une expression en place dans une nouvelle instance. */ -static void g_pending_call_copy(GPendingCall *, const GPendingCall *); - /* Réduit une expression à une forme plus simple. */ -static bool g_pending_call_reduce(GPendingCall *, GScanContext *, GScanScope *, GScanExpression **); +static ScanReductionState g_scan_pending_call_reduce(GScanPendingCall *, GScanContext *, GScanScope *, GScanExpression **); + +/* Reproduit un accès en place dans une nouvelle instance. */ +static void g_scan_pending_call_copy(GScanPendingCall *, const GScanPendingCall *); @@ -68,7 +68,7 @@ static bool g_pending_call_reduce(GPendingCall *, GScanContext *, GScanScope *, /* Indique le type défini pour un appel de fonction enregistrée. */ -G_DEFINE_TYPE(GPendingCall, g_pending_call, G_TYPE_NAMED_ACCESS); +G_DEFINE_TYPE(GScanPendingCall, g_scan_pending_call, G_TYPE_SCAN_NAMED_ACCESS); /****************************************************************************** @@ -83,21 +83,25 @@ G_DEFINE_TYPE(GPendingCall, g_pending_call, G_TYPE_NAMED_ACCESS); * * ******************************************************************************/ -static void g_pending_call_class_init(GPendingCallClass *klass) +static void g_scan_pending_call_class_init(GScanPendingCallClass *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_pending_call_dispose; - object->finalize = (GObjectFinalizeFunc)g_pending_call_finalize; + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_pending_call_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_pending_call_finalize; expr = G_SCAN_EXPRESSION_CLASS(klass); expr->cmp_rich = (compare_expr_rich_fc)NULL; - expr->copy = (copy_expr_fc)g_pending_call_copy; - expr->reduce = (reduce_expr_fc)g_pending_call_reduce; + expr->reduce = (reduce_expr_fc)g_scan_pending_call_reduce; + + access = G_SCAN_NAMED_ACCESS_CLASS(klass); + + access->copy = (copy_scan_access_fc)g_scan_pending_call_copy; } @@ -114,7 +118,7 @@ static void g_pending_call_class_init(GPendingCallClass *klass) * * ******************************************************************************/ -static void g_pending_call_init(GPendingCall *call) +static void g_scan_pending_call_init(GScanPendingCall *call) { call->args = NULL; call->count = 0; @@ -134,14 +138,14 @@ static void g_pending_call_init(GPendingCall *call) * * ******************************************************************************/ -static void g_pending_call_dispose(GPendingCall *call) +static void g_scan_pending_call_dispose(GScanPendingCall *call) { size_t i; /* Boucle de parcours */ for (i = 0; i < call->count; i++) g_clear_object(&call->args[i]); - G_OBJECT_CLASS(g_pending_call_parent_class)->dispose(G_OBJECT(call)); + G_OBJECT_CLASS(g_scan_pending_call_parent_class)->dispose(G_OBJECT(call)); } @@ -158,12 +162,12 @@ static void g_pending_call_dispose(GPendingCall *call) * * ******************************************************************************/ -static void g_pending_call_finalize(GPendingCall *call) +static void g_scan_pending_call_finalize(GScanPendingCall *call) { if (call->args != NULL) free(call->args); - G_OBJECT_CLASS(g_pending_call_parent_class)->finalize(G_OBJECT(call)); + G_OBJECT_CLASS(g_scan_pending_call_parent_class)->finalize(G_OBJECT(call)); } @@ -182,13 +186,13 @@ static void g_pending_call_finalize(GPendingCall *call) * * ******************************************************************************/ -GScanExpression *g_pending_call_new(const sized_string_t *target, GScanExpression **args, size_t count) +GScanExpression *g_scan_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); + result = g_object_new(G_TYPE_SCAN_PENDING_CALL, NULL); - if (!g_pending_call_create(G_PENDING_CALL(result), target, args, count)) + if (!g_scan_pending_call_create(G_SCAN_PENDING_CALL(result), target, args, count)) g_clear_object(&result); return result; @@ -211,12 +215,12 @@ GScanExpression *g_pending_call_new(const sized_string_t *target, GScanExpressio * * ******************************************************************************/ -bool g_pending_call_create(GPendingCall *call, const sized_string_t *target, GScanExpression **args, size_t count) +bool g_scan_pending_call_create(GScanPendingCall *call, const sized_string_t *target, GScanExpression **args, size_t count) { bool result; /* Bilan à retourner */ size_t i; /* Boucle de parcours */ - result = g_named_access_create(G_NAMED_ACCESS(call), target); + result = g_scan_named_access_create(G_SCAN_NAMED_ACCESS(call), target); if (!result) goto exit; call->args = malloc(count * sizeof(GScanExpression *)); @@ -243,37 +247,6 @@ bool g_pending_call_create(GPendingCall *call, const sized_string_t *target, GSc /****************************************************************************** * * -* 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_pending_call_copy(GPendingCall *dest, const GPendingCall *src) -{ - GScanExpressionClass *class; /* Classe parente à solliciter */ - size_t i; /* Boucle de parcours */ - - class = G_SCAN_EXPRESSION_CLASS(g_pending_call_parent_class); - - 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]); - -} - - -/****************************************************************************** -* * * Paramètres : expr = expression à consulter. * * ctx = contexte de suivi de l'analyse courante. * * scope = portée courante des variables locales. * @@ -287,89 +260,196 @@ static void g_pending_call_copy(GPendingCall *dest, const GPendingCall *src) * * ******************************************************************************/ -static bool g_pending_call_reduce(GPendingCall *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +static ScanReductionState g_scan_pending_call_reduce(GScanPendingCall *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - bool result; /* Bilan à retourner */ - GNamedAccess *new; /* Eventuel étage suivant */ - GPendingCall *new_call; /* Version en appel */ - size_t i; /* Boucle de parcours */ + ScanReductionState result; /* Etat synthétisé à retourner */ + GScanNamedAccess *access; /* Autre vision de l'expression*/ + GRegisteredItem *resolved; /* Cible concrète obtenue */ + size_t i; /* Boucle de parcours #1 */ GScanExpression *arg; /* Argument réduit à échanger */ - GObject *final; /* Expression ou élément ? */ + 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 */ - result = _g_named_access_reduce(G_NAMED_ACCESS(expr), ctx, scope, out); + access = G_SCAN_NAMED_ACCESS(expr); - if (result && *out != NULL) - { - assert(G_IS_NAMED_ACCESS(*out)); + resolved = _g_scan_named_access_prepare_reduction(access, ctx, scope); + + if (resolved == NULL) + result = SRS_UNRESOLVABLE; - new = G_NAMED_ACCESS(*out); - *out = NULL; + else + { + result = SRS_PENDING; - assert(new->target == NULL); - assert(G_IS_PENDING_CALL(new)); - assert(G_IS_REGISTERED_ITEM(new->resolved)); + /* Actualisation nécessaire des arguments ? */ - new_call = G_PENDING_CALL(new); + new_args = NULL; - for (i = 0; i < new_call->count; i++) + for (i = 0; i < expr->count; i++) { - result = g_scan_expression_reduce(new_call->args[i], ctx, scope, &arg); - if (!result) goto exit; + arg = expr->args[i]; - if (arg != NULL) + state = g_scan_expression_reduce(arg, ctx, scope, &new); + if (state == SRS_UNRESOLVABLE) { - g_object_unref(G_OBJECT(new_call->args[i])); - new_call->args[i] = arg; + result = SRS_UNRESOLVABLE; + break; } + if (state == SRS_WAIT_FOR_SCAN) + result = SRS_WAIT_FOR_SCAN; + + if (new != arg) + { + if (new_args == NULL) + { + new_args = calloc(expr->count, sizeof(GScanExpression *)); + + for (k = 0; k < i; k++) + { + new_args[k] = expr->args[i]; + g_object_ref(G_OBJECT(new_args[k])); + } + + } + + new_args[i] = new; + + } + + else + { + if (new_args != NULL) + new_args[i] = new; + } } - result = g_registered_item_run_call(new->resolved, - new_call->args, - new_call->count, - ctx, scope, &final); + /* Suite des traitements */ - if (result && final != NULL) + if (result == SRS_WAIT_FOR_SCAN) { /** - * 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. + * Si changement il y a eu... */ - if (!G_IS_REGISTERED_ITEM(final)) + if (new_args != NULL) { - assert(new->next == NULL); - *out = G_SCAN_EXPRESSION(final); + *out = g_scan_pending_call_new(NULL, new_args, expr->count); + + /** + * 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_PENDING) + { + if (new_args == NULL) + valid = g_registered_item_run_call(resolved, + expr->args, + expr->count, + ctx, scope, &final); else - { - assert(new->next != NULL); + valid = g_registered_item_run_call(resolved, + new_args, + expr->count, + ctx, scope, &final); - new_next = g_scan_expression_duplicate(G_SCAN_EXPRESSION(new->next)); - assert(G_IS_NAMED_ACCESS(new_next)); + if (valid && 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(access->next == NULL); - g_named_access_set_base(G_NAMED_ACCESS(new_next), G_REGISTERED_ITEM(final)); + *out = G_SCAN_EXPRESSION(final); - result = g_scan_expression_reduce(new_next, ctx, scope, out); + result = SRS_REDUCED; - if (result && *out == NULL) - *out = new_next; + } else + { + assert(access->next != NULL); + + new_next = g_scan_named_access_duplicate(access->next, resolved); + + result = g_scan_expression_reduce(new_next, ctx, scope, out); + g_object_unref(G_OBJECT(new_next)); + } + } + else + result = SRS_UNRESOLVABLE; + } - exit: + /* Libération locale des arguments reconstruits */ - g_object_unref(G_OBJECT(new)); + if (new_args != NULL) + { + for (i = 0; i < expr->count; i++) + g_clear_object(&new_args[i]); + } + + 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_call_copy(GScanPendingCall *dest, const GScanPendingCall *src) +{ + GScanNamedAccessClass *class; /* Classe parente à solliciter */ + size_t i; /* Boucle de parcours */ + + class = G_SCAN_NAMED_ACCESS_CLASS(g_scan_pending_call_parent_class); + + class->copy(G_SCAN_NAMED_ACCESS(dest), G_SCAN_NAMED_ACCESS(src)); + + dest->args = malloc(src->count * sizeof(GScanExpression *)); + dest->count = src->count; + + for (i = 0; i < src->count; i++) + { + dest->args[i] = src->args[i]; + g_object_ref(G_OBJECT(src->args[i])); + } + +} diff --git a/src/analysis/scan/exprs/call.h b/src/analysis/scan/exprs/call.h index c344036..c4d8964 100644 --- a/src/analysis/scan/exprs/call.h +++ b/src/analysis/scan/exprs/call.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * call.h - prototypes pour l'organisation d'un appel à un élément de scan enregistré * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -30,26 +30,26 @@ -#define G_TYPE_PENDING_CALL g_pending_call_get_type() -#define G_PENDING_CALL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PENDING_CALL, GPendingCall)) -#define G_IS_PENDING_CALL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PENDING_CALL)) -#define G_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PENDING_CALL, GPendingCallClass)) -#define G_IS_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PENDING_CALL)) -#define G_PENDING_CALL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PENDING_CALL, GPendingCallClass)) +#define G_TYPE_SCAN_PENDING_CALL g_scan_pending_call_get_type() +#define G_SCAN_PENDING_CALL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_PENDING_CALL, GScanPendingCall)) +#define G_IS_SCAN_PENDING_CALL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_PENDING_CALL)) +#define G_SCAN_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_PENDING_CALL, GScanPendingCallClass)) +#define G_IS_SCAN_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_PENDING_CALL)) +#define G_SCAN_PENDING_CALL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_PENDING_CALL, GScanPendingCallClass)) /* Exécution d'une fonction auxiliaire d'analyse (instance) */ -typedef struct _GPendingCall GPendingCall; +typedef struct _GScanPendingCall GScanPendingCall; /* Exécution d'une fonction auxiliaire d'analyse (classe) */ -typedef struct _GPendingCallClass GPendingCallClass; +typedef struct _GScanPendingCallClass GScanPendingCallClass; /* Indique le type défini pour un appel de fonction enregistrée. */ -GType g_pending_call_get_type(void); +GType g_scan_pending_call_get_type(void); /* Organise un appel de fonction avec ses arguments. */ -GScanExpression *g_pending_call_new(const sized_string_t *, GScanExpression **, size_t); +GScanExpression *g_scan_pending_call_new(const sized_string_t *, GScanExpression **, size_t); diff --git a/src/analysis/scan/exprs/counter-int.h b/src/analysis/scan/exprs/counter-int.h new file mode 100644 index 0000000..8c5e56b --- /dev/null +++ b/src/analysis/scan/exprs/counter-int.h @@ -0,0 +1,57 @@ + +/* 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 new file mode 100644 index 0000000..290fd02 --- /dev/null +++ b/src/analysis/scan/exprs/counter.c @@ -0,0 +1,248 @@ + +/* 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 bool g_scan_match_counter_reduce(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 = true; + + counter->pattern = pattern; + g_object_ref(G_OBJECT(pattern)); + + 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 bool g_scan_match_counter_reduce(GScanMatchCounter *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +{ + bool result; /* Bilan à retourner */ + size_t count; /* Quantité de correspondances */ + const GScanMatch **matches; /* Correspondances établies */ + + + matches = g_scan_context_get_full_matches(ctx, expr->pattern, &count); + + + printf("matches: %zu\n", count); + + + *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ count }); + result = true; + + + return result; + +} diff --git a/src/analysis/scan/exprs/counter.h b/src/analysis/scan/exprs/counter.h new file mode 100644 index 0000000..c90953e --- /dev/null +++ b/src/analysis/scan/exprs/counter.h @@ -0,0 +1,59 @@ + +/* 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/intersect-int.h b/src/analysis/scan/exprs/intersect-int.h new file mode 100644 index 0000000..83e4251 --- /dev/null +++ b/src/analysis/scan/exprs/intersect-int.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * intersect-int.h - prototypes internes pour l'intersection d'ensembles aux types indentiques + * + * 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_INTERSECT_INT_H +#define _ANALYSIS_SCAN_EXPRS_INTERSECT_INT_H + + +#include "intersect.h" + + +#include "../expr-int.h" + + + +/* Opération d'intersection entre deux ensembles (instance) */ +struct _GScanSetsIntersection +{ + GScanExpression parent; /* A laisser en premier */ + + GScanExpression *first; /* Expression impactée #1 */ + GScanExpression *second; /* Expression impactée #2 */ + +}; + +/* Opération d'intersection entre deux ensembles (classe) */ +struct _GScanSetsIntersectionClass +{ + GScanExpressionClass parent; /* A laisser en premier */ + +}; + + +/* Met en place une expression d'opération booléenne. */ +bool g_scan_sets_intersection_create(GScanSetsIntersection *, GScanExpression *, GScanExpression *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_INTERSECT_INT_H */ diff --git a/src/analysis/scan/exprs/intersect.c b/src/analysis/scan/exprs/intersect.c new file mode 100644 index 0000000..f0660e0 --- /dev/null +++ b/src/analysis/scan/exprs/intersect.c @@ -0,0 +1,290 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * intersect.c - intersection d'ensembles aux types indentiques + * + * 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 "intersect.h" + + +#include <assert.h> + + +#include "intersect-int.h" +#include "literal.h" + + + +/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */ + + +/* Initialise la classe des intersections entre deux ensembles. */ +static void g_scan_sets_intersection_class_init(GScanSetsIntersectionClass *); + +/* Initialise une instance d'intersection entre deux ensembles. */ +static void g_scan_sets_intersection_init(GScanSetsIntersection *); + +/* Supprime toutes les références externes. */ +static void g_scan_sets_intersection_dispose(GScanSetsIntersection *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_sets_intersection_finalize(GScanSetsIntersection *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Réduit une expression à une forme plus simple. */ +static ScanReductionState g_scan_sets_intersection_reduce(GScanSetsIntersection *, GScanContext *, GScanScope *, GScanExpression **); + + + +/* ---------------------------------------------------------------------------------- */ +/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une intersection entre deux ensembles. */ +G_DEFINE_TYPE(GScanSetsIntersection, g_scan_sets_intersection, G_TYPE_SCAN_EXPRESSION); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des intersections entre deux ensembles. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_sets_intersection_class_init(GScanSetsIntersectionClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanExpressionClass *expr; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_sets_intersection_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_sets_intersection_finalize; + + expr = G_SCAN_EXPRESSION_CLASS(klass); + + expr->reduce = (reduce_expr_fc)g_scan_sets_intersection_reduce; + +} + + +/****************************************************************************** +* * +* Paramètres : op = instance à initialiser. * +* * +* Description : Initialise une instance d'intersection entre deux ensembles. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_sets_intersection_init(GScanSetsIntersection *inter) +{ + inter->first = NULL; + inter->second = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : inter = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_sets_intersection_dispose(GScanSetsIntersection *inter) +{ + g_clear_object(&inter->first); + g_clear_object(&inter->second); + + G_OBJECT_CLASS(g_scan_sets_intersection_parent_class)->dispose(G_OBJECT(inter)); + +} + + +/****************************************************************************** +* * +* Paramètres : inter = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_sets_intersection_finalize(GScanSetsIntersection *inter) +{ + G_OBJECT_CLASS(g_scan_sets_intersection_parent_class)->finalize(G_OBJECT(inter)); + +} + + +/****************************************************************************** +* * +* Paramètres : type = type d'opération booléenne à représenter. * +* first = premier élément concerné. * +* second = second élément concerné. * +* * +* Description : Organise une intersection entre deux ensembles. * +* * +* Retour : Expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_scan_sets_intersection_new(GScanExpression *first, GScanExpression *second) +{ + GScanExpression *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_SETS_INTERSECTION, NULL); + + if (!g_scan_sets_intersection_create(G_SCAN_SETS_INTERSECTION(result), first, second)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : inter = instance à initialiser pleinement. * +* first = premier élément concerné. * +* second = second élément concerné. * +* * +* Description : Met en place une expression d'opération booléenne. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_scan_sets_intersection_create(GScanSetsIntersection *inter, GScanExpression *first, GScanExpression *second) +{ + bool result; /* Bilan à retourner */ + + result = true; + + inter->first = first; + g_object_ref(G_OBJECT(first)); + + inter->second = second; + g_object_ref(G_OBJECT(second)); + + 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_sets_intersection_reduce(GScanSetsIntersection *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +{ + ScanReductionState result; /* Etat synthétisé à retourner */ + GScanExpression *new_first; /* Nouvelle réduction #1 */ + GScanExpression *new_second; /* Nouvelle réduction #2 */ + ScanReductionState state_first; /* Etat synthétisé #1 */ + ScanReductionState state_second; /* Etat synthétisé #2 */ + + new_first = NULL; + new_second = NULL; + + state_first = g_scan_expression_reduce(expr->first, ctx, scope, &new_first); + if (state_first == SRS_UNRESOLVABLE) + { + result = SRS_UNRESOLVABLE; + goto exit; + } + + state_second = g_scan_expression_reduce(expr->second, ctx, scope, &new_second); + if (state_second == SRS_UNRESOLVABLE) + { + result = SRS_UNRESOLVABLE; + goto exit; + } + + if (state_first == SRS_WAIT_FOR_SCAN || state_second == SRS_WAIT_FOR_SCAN) + { + if (new_first != expr->first || new_second != expr->second) + *out = g_scan_sets_intersection_new(new_first, new_second); + + result = SRS_WAIT_FOR_SCAN; + + } + + else + { + assert(state_first == SRS_REDUCED && state_second == SRS_REDUCED); + + *out = g_scan_expression_intersect(new_first, new_second, ctx, scope); + + result = (*out != NULL ? SRS_REDUCED : SRS_UNRESOLVABLE); + + } + + exit: + + g_clear_object(&new_first); + g_clear_object(&new_second); + + return result; + +} diff --git a/src/analysis/scan/exprs/intersect.h b/src/analysis/scan/exprs/intersect.h new file mode 100644 index 0000000..56efdff --- /dev/null +++ b/src/analysis/scan/exprs/intersect.h @@ -0,0 +1,55 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * intersect.h - prototypes pour l'intersection d'ensembles aux types indentiques + * + * 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_INTERSECT_H +#define _ANALYSIS_SCAN_EXPRS_INTERSECT_H + + +#include "../expr.h" + + + +#define G_TYPE_SCAN_SETS_INTERSECTION g_scan_sets_intersection_get_type() +#define G_SCAN_SETS_INTERSECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_SETS_INTERSECTION, GScanSetsIntersection)) +#define G_IS_SCAN_SETS_INTERSECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_SETS_INTERSECTION)) +#define G_SCAN_SETS_INTERSECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_SETS_INTERSECTION, GScanSetsIntersectionClass)) +#define G_IS_SCAN_SETS_INTERSECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_SETS_INTERSECTION)) +#define G_SCAN_SETS_INTERSECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_SETS_INTERSECTION, GScanSetsIntersectionClass)) + + +/* Opération d'intersection entre deux ensembles (instance) */ +typedef struct _GScanSetsIntersection GScanSetsIntersection; + +/* Opération d'intersection entre deux ensembles (classe) */ +typedef struct _GScanSetsIntersectionClass GScanSetsIntersectionClass; + + +/* Indique le type défini pour une intersection entre deux ensembles. */ +GType g_scan_sets_intersection_get_type(void); + +/* Organise une intersection entre deux ensembles. */ +GScanExpression *g_scan_sets_intersection_new(GScanExpression *, GScanExpression *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_INTERSECT_H */ diff --git a/src/analysis/scan/exprs/literal-int.h b/src/analysis/scan/exprs/literal-int.h index 875b3de..b0a0ec5 100644 --- a/src/analysis/scan/exprs/literal-int.h +++ b/src/analysis/scan/exprs/literal-int.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * literal-int.h - prototypes internes pour la représentation d'une valeur concrète * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -28,24 +28,22 @@ #include "literal.h" -#include <stdbool.h> - - #include "../expr-int.h" /* Expression portant une valeur concrète (instance) */ -struct _GLiteralExpression +struct _GScanLiteralExpression { GScanExpression parent; /* A laisser en premier */ - ExprValueType value_type; /* Type de valeur portée */ + LiteralValueType value_type; /* Type de valeur portée */ union { bool boolean; /* Valeur booléenne */ - unsigned long long integer; /* Valeur entière 64 bits */ + long long s_integer; /* Valeur entière 64 bits */ + unsigned long long u_integer; /* Valeur entière 64 bits */ sized_string_t string; /* Chaîne de caractères */ struct { @@ -58,7 +56,7 @@ struct _GLiteralExpression }; /* Expression portant une valeur concrète (classe) */ -struct _GLiteralExpressionClass +struct _GScanLiteralExpressionClass { GScanExpressionClass parent; /* A laisser en premier */ @@ -66,7 +64,7 @@ struct _GLiteralExpressionClass /* Met en place une expression de valeur concrête. */ -bool g_literal_expression_create(GLiteralExpression *, ExprValueType, ...); +bool g_scan_literal_expression_create(GScanLiteralExpression *, LiteralValueType, ...); diff --git a/src/analysis/scan/exprs/literal.c b/src/analysis/scan/exprs/literal.c index 119b871..e468382 100644 --- a/src/analysis/scan/exprs/literal.c +++ b/src/analysis/scan/exprs/literal.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * literal.c - représentation d'une valeur concrète * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -37,16 +37,16 @@ /* Initialise la classe des expressions de valeur concrète. */ -static void g_literal_expression_class_init(GLiteralExpressionClass *); +static void g_scan_literal_expression_class_init(GScanLiteralExpressionClass *); /* Initialise une instance d'expression de valeur concrète. */ -static void g_literal_expression_init(GLiteralExpression *); +static void g_scan_literal_expression_init(GScanLiteralExpression *); /* Supprime toutes les références externes. */ -static void g_literal_expression_dispose(GLiteralExpression *); +static void g_scan_literal_expression_dispose(GScanLiteralExpression *); /* Procède à la libération totale de la mémoire. */ -static void g_literal_expression_finalize(GLiteralExpression *); +static void g_scan_literal_expression_finalize(GScanLiteralExpression *); @@ -54,13 +54,13 @@ static void g_literal_expression_finalize(GLiteralExpression *); /* Réalise une comparaison entre objets selon un critère précis. */ -static bool g_literal_expression_compare_rich(const GLiteralExpression *, const GLiteralExpression *, RichCmpOperation, bool *); +static bool g_scan_literal_expression_compare_rich(const GScanLiteralExpression *, const GScanLiteralExpression *, RichCmpOperation, bool *); -/* Reproduit une expression en place dans une nouvelle instance. */ -static void g_literal_expression_copy(GLiteralExpression *, const GLiteralExpression *); +/* Réduit une expression à une forme booléenne. */ +static bool g_scan_literal_expression_reduce_to_boolean(GScanLiteralExpression *, GScanContext *, GScanScope *, GScanExpression **); -/* Réduit une expression à une forme plus simple. */ -static bool g_literal_expression_reduce(GLiteralExpression *, GScanContext *, GScanScope *, GScanExpression **); +/* Dénombre les éléments portés par une expression. */ +static bool g_scan_literal_expression_count(const GScanLiteralExpression *, size_t *); @@ -70,7 +70,7 @@ static bool g_literal_expression_reduce(GLiteralExpression *, GScanContext *, GS /* Indique le type défini pour un appel de fonction enregistrée. */ -G_DEFINE_TYPE(GLiteralExpression, g_literal_expression, G_TYPE_SCAN_EXPRESSION); +G_DEFINE_TYPE(GScanLiteralExpression, g_scan_literal_expression, G_TYPE_SCAN_EXPRESSION); /****************************************************************************** @@ -85,21 +85,21 @@ G_DEFINE_TYPE(GLiteralExpression, g_literal_expression, G_TYPE_SCAN_EXPRESSION); * * ******************************************************************************/ -static void g_literal_expression_class_init(GLiteralExpressionClass *klass) +static void g_scan_literal_expression_class_init(GScanLiteralExpressionClass *klass) { GObjectClass *object; /* Autre version de la classe */ GScanExpressionClass *expr; /* Version de classe parente */ object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_literal_expression_dispose; - object->finalize = (GObjectFinalizeFunc)g_literal_expression_finalize; + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_literal_expression_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_literal_expression_finalize; expr = G_SCAN_EXPRESSION_CLASS(klass); - expr->cmp_rich = (compare_expr_rich_fc)g_literal_expression_compare_rich; - expr->copy = (copy_expr_fc)g_literal_expression_copy; - expr->reduce = (reduce_expr_fc)g_literal_expression_reduce; + 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; } @@ -116,8 +116,9 @@ static void g_literal_expression_class_init(GLiteralExpressionClass *klass) * * ******************************************************************************/ -static void g_literal_expression_init(GLiteralExpression *expr) +static void g_scan_literal_expression_init(GScanLiteralExpression *expr) { + G_SCAN_EXPRESSION(expr)->state = SRS_REDUCED; } @@ -134,9 +135,9 @@ static void g_literal_expression_init(GLiteralExpression *expr) * * ******************************************************************************/ -static void g_literal_expression_dispose(GLiteralExpression *expr) +static void g_scan_literal_expression_dispose(GScanLiteralExpression *expr) { - G_OBJECT_CLASS(g_literal_expression_parent_class)->dispose(G_OBJECT(expr)); + G_OBJECT_CLASS(g_scan_literal_expression_parent_class)->dispose(G_OBJECT(expr)); } @@ -153,9 +154,9 @@ static void g_literal_expression_dispose(GLiteralExpression *expr) * * ******************************************************************************/ -static void g_literal_expression_finalize(GLiteralExpression *expr) +static void g_scan_literal_expression_finalize(GScanLiteralExpression *expr) { - G_OBJECT_CLASS(g_literal_expression_parent_class)->finalize(G_OBJECT(expr)); + G_OBJECT_CLASS(g_scan_literal_expression_parent_class)->finalize(G_OBJECT(expr)); } @@ -167,25 +168,25 @@ static void g_literal_expression_finalize(GLiteralExpression *expr) * * * Description : Organise un appel de fonction avec ses arguments. * * * -* Retour : Fonction mise en place. * +* Retour : Expression mise en place. * * * * Remarques : - * * * ******************************************************************************/ -GScanExpression *g_literal_expression_new(ExprValueType vtype, ...) +GScanExpression *g_scan_literal_expression_new(LiteralValueType vtype, ...) { GScanExpression *result; /* Structure à retourner */ va_list ap; /* Liste d'arguements */ void *ptr; /* Vision générique de valeur */ - result = g_object_new(G_TYPE_LITERAL_EXPRESSION, NULL); + result = g_object_new(G_TYPE_SCAN_LITERAL_EXPRESSION, NULL); va_start(ap, vtype); ptr = va_arg(ap, void *); - if (!g_literal_expression_create(G_LITERAL_EXPRESSION(result), vtype, ptr)) + if (!g_scan_literal_expression_create(G_SCAN_LITERAL_EXPRESSION(result), vtype, ptr)) g_clear_object(&result); va_end(ap); @@ -209,12 +210,13 @@ GScanExpression *g_literal_expression_new(ExprValueType vtype, ...) * * ******************************************************************************/ -bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype, ...) +bool g_scan_literal_expression_create(GScanLiteralExpression *expr, LiteralValueType vtype, ...) { bool result; /* Bilan à retourner */ va_list ap; /* Liste d'arguements */ const bool *boolean; /* Valeur booléenne */ - const unsigned long long *integer; /* Valeur entière 64 bits */ + const long long *s_integer; /* Valeur entière 64 bits #1 */ + const unsigned long long *u_integer; /* Valeur entière 64 bits #2 */ 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 */ @@ -223,89 +225,115 @@ bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype, char *tmp; /* Zone de travail temporaire */ int ret; /* Bilan d'une opération */ - result = g_scan_expression_create(G_SCAN_EXPRESSION(expr), vtype); + va_start(ap, vtype); - if (result) + switch (vtype) { - va_start(ap, vtype); + case LVT_BOOLEAN: + boolean = va_arg(ap, const bool *); + expr->value.boolean = *boolean; + result = true; + break; - switch (vtype) - { - case EVT_BOOLEAN: - boolean = va_arg(ap, const bool *); - expr->value.boolean = *boolean; - break; + case LVT_SIGNED_INTEGER: + s_integer = va_arg(ap, const long long *); + expr->value.s_integer = *s_integer; + result = true; + break; - case EVT_INTEGER: - integer = va_arg(ap, const unsigned long long *); - expr->value.integer = *integer; - break; + case LVT_UNSIGNED_INTEGER: + u_integer = va_arg(ap, const unsigned long long *); + expr->value.u_integer = *u_integer; + result = true; + break; + + case LVT_STRING: + string = va_arg(ap, const sized_string_t *); + szstrdup(&expr->value.string, string); + result = true; + break; - case EVT_STRING: - string = va_arg(ap, const sized_string_t *); - szstrdup(&expr->value.string, string); - break; + case LVT_REG_EXPR: + raw = va_arg(ap, const char *); + len = strlen(raw); - case EVT_REG_EXPR: - raw = va_arg(ap, const char *); - len = strlen(raw); + result = (len > 2 && raw[0] == '/'); - result = (len > 2 && raw[0] == '/'); + cflags = REG_EXTENDED | REG_NOSUB; - cflags = REG_EXTENDED | REG_NOSUB; + for (i = 0; i < 2 && result; i++) + { + result = (len > 2); - for (i = 0; i < 2 && result; i++) + if (raw[len - 1] == 'i') { - result = (len > 2); + cflags |= REG_ICASE; + len -= 1; + } - if (raw[len - 1] == 'i') - { - cflags |= REG_ICASE; - len -= 1; - } + else if (raw[len - 1] == 's') + { + cflags |= REG_NEWLINE; + len -= 1; + } - else if (raw[len - 1] == 's') - { - cflags |= REG_NEWLINE; - len -= 1; - } + else if (raw[len - 1] == '/') + break; - else if (raw[len - 1] == '/') - break; + } - } + if (result) + result = (raw[len - 1] == '/'); - if (result) - result = (raw[len - 1] == '/'); + if (result) + { + assert(len > 2); + + tmp = strndup(&raw[1], len - 2); + ret = regcomp(&expr->value.preg, tmp, cflags); + free(tmp); + + result = (ret == 0); if (result) - { - assert(len > 2); + expr->value.regex = strdup(raw); + + } + + break; - tmp = strndup(&raw[1], len - 2); - ret = regcomp(&expr->value.preg, tmp, cflags); - free(tmp); + default: + result = false; + break; - result = (ret == 0); + } - if (result) - expr->value.regex = strdup(raw); + va_end(ap); - } + expr->value_type = vtype; - break; + return result; - default: - result = false; - break; +} - } - va_end(ap); +/****************************************************************************** +* * +* Paramètres : expr = expression à consulter. * +* * +* Description : Indique le type de valeur portée par une expression. * +* * +* Retour : Type de valeur associée à l'expression. * +* * +* Remarques : - * +* * +******************************************************************************/ - } +LiteralValueType g_scan_literal_expression_get_value_type(const GScanLiteralExpression *expr) +{ + LiteralValueType result; /* Type à retourner */ - expr->value_type = vtype; + result = expr->value_type; return result; @@ -314,7 +342,7 @@ bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype, /****************************************************************************** * * -* Paramètres : item = premier objet à consulter pour une comparaison. * +* Paramètres : expr = premier objet à consulter pour une comparaison. * * value = valeur portée portée par l'expression. [OUT] * * * * Description : Indique la valeur portée par une expression booléenne. * @@ -325,14 +353,41 @@ bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype, * * ******************************************************************************/ -bool g_literal_expression_get_boolean_value(const GLiteralExpression *item, bool *value) +bool g_scan_literal_expression_get_boolean_value(const GScanLiteralExpression *expr, bool *value) +{ + bool result; /* Etat à retourner */ + + result = (expr->value_type == LVT_BOOLEAN); + + if (result) + *value = expr->value.boolean; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = premier objet à consulter pour une comparaison. * +* value = valeur portée portée par l'expression. [OUT] * +* * +* Description : Indique la valeur portée par une expression d'entier. * +* * +* Retour : true si l'expression est de type entier, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_scan_literal_expression_get_signed_integer_value(const GScanLiteralExpression *expr, long long *value) { bool result; /* Etat à retourner */ - result = (item->value_type == EVT_BOOLEAN); + result = (expr->value_type == LVT_SIGNED_INTEGER); if (result) - *value = item->value.boolean; + *value = expr->value.u_integer; return result; @@ -341,7 +396,7 @@ bool g_literal_expression_get_boolean_value(const GLiteralExpression *item, bool /****************************************************************************** * * -* Paramètres : item = premier objet à consulter pour une comparaison. * +* Paramètres : expr = premier objet à consulter pour une comparaison. * * value = valeur portée portée par l'expression. [OUT] * * * * Description : Indique la valeur portée par une expression d'entier. * @@ -352,14 +407,14 @@ bool g_literal_expression_get_boolean_value(const GLiteralExpression *item, bool * * ******************************************************************************/ -bool g_literal_expression_get_integer_value(const GLiteralExpression *item, unsigned long long *value) +bool g_scan_literal_expression_get_unsigned_integer_value(const GScanLiteralExpression *expr, unsigned long long *value) { bool result; /* Etat à retourner */ - result = (item->value_type == EVT_INTEGER); + result = (expr->value_type == LVT_UNSIGNED_INTEGER); if (result) - *value = item->value.integer; + *value = expr->value.u_integer; return result; @@ -368,7 +423,7 @@ bool g_literal_expression_get_integer_value(const GLiteralExpression *item, unsi /****************************************************************************** * * -* Paramètres : item = premier objet à consulter pour une comparaison. * +* Paramètres : expr = premier objet à consulter pour une comparaison. * * value = valeur portée portée par l'expression. [OUT] * * * * Description : Indique la valeur portée par une expression de chaîne. * @@ -379,14 +434,14 @@ bool g_literal_expression_get_integer_value(const GLiteralExpression *item, unsi * * ******************************************************************************/ -bool g_literal_expression_get_string_value(const GLiteralExpression *item, const sized_string_t **value) +bool g_scan_literal_expression_get_string_value(const GScanLiteralExpression *expr, const sized_string_t **value) { bool result; /* Etat à retourner */ - result = (item->value_type == EVT_STRING); + result = (expr->value_type == LVT_STRING); if (result) - *value = &item->value.string; + *value = &expr->value.string; return result; @@ -395,7 +450,7 @@ bool g_literal_expression_get_string_value(const GLiteralExpression *item, const /****************************************************************************** * * -* Paramètres : item = premier objet à consulter pour une comparaison. * +* Paramètres : expr = premier objet à consulter pour une comparaison. * * value = valeur portée portée par l'expression. [OUT] * * * * Description : Indique la valeur portée par une expression rationnelle. * @@ -406,14 +461,14 @@ bool g_literal_expression_get_string_value(const GLiteralExpression *item, const * * ******************************************************************************/ -bool g_literal_expression_get_regex_value(const GLiteralExpression *item, const regex_t **value) +bool g_scan_literal_expression_get_regex_value(const GScanLiteralExpression *expr, const regex_t **value) { bool result; /* Etat à retourner */ - result = (item->value_type == EVT_REG_EXPR); + result = (expr->value_type == LVT_REG_EXPR); if (result) - *value = &item->value.preg; + *value = &expr->value.preg; return result; @@ -428,7 +483,7 @@ bool g_literal_expression_get_regex_value(const GLiteralExpression *item, const /****************************************************************************** * * -* Paramètres : item = premier objet à consulter pour une comparaison. * +* Paramètres : expr = premier objet à consulter pour une comparaison. * * other = second objet à consulter pour une comparaison. * * op = opération de comparaison à réaliser. * * status = bilan des opérations de comparaison. [OUT] * @@ -441,32 +496,32 @@ bool g_literal_expression_get_regex_value(const GLiteralExpression *item, const * * ******************************************************************************/ -static bool g_literal_expression_compare_rich(const GLiteralExpression *item, const GLiteralExpression *other, RichCmpOperation op, bool *status) +static bool g_scan_literal_expression_compare_rich(const GScanLiteralExpression *expr, const GScanLiteralExpression *other, RichCmpOperation op, bool *status) { bool result; /* Etat à retourner */ int cmp; /* Bilan intermédiaire */ - result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_LITERAL_EXPRESSION); + result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_SCAN_LITERAL_EXPRESSION); if (!result) goto done; - if (item->value_type != other->value_type) + if (expr->value_type != other->value_type) { - *status = compare_rich_integer_values(item->value_type, other->value_type, op); + *status = compare_rich_integer_values_unsigned(expr->value_type, other->value_type, op); goto done; } - switch (item->value_type) + switch (expr->value_type) { - case EVT_BOOLEAN: + case LVT_BOOLEAN: switch (op) { case RCO_EQ: - *status = (item->value.boolean == other->value.boolean); + *status = (expr->value.boolean == other->value.boolean); result = true; break; case RCO_NE: - *status = (item->value.boolean != other->value.boolean); + *status = (expr->value.boolean != other->value.boolean); result = true; break; @@ -477,20 +532,25 @@ static bool g_literal_expression_compare_rich(const GLiteralExpression *item, co }; break; - case EVT_INTEGER: - *status = compare_rich_integer_values(item->value.integer, other->value.integer, op); + case LVT_SIGNED_INTEGER: + *status = compare_rich_integer_values_signed(expr->value.s_integer, other->value.s_integer, op); result = true; break; - case EVT_STRING: - cmp = szstrcmp(&item->value.string, &other->value.string); - *status = compare_rich_integer_values(cmp, 0, op); + case LVT_UNSIGNED_INTEGER: + *status = compare_rich_integer_values_unsigned(expr->value.u_integer, other->value.u_integer, op); result = true; break; - case EVT_REG_EXPR: - cmp = strcmp(item->value.regex, other->value.regex); - *status = compare_rich_integer_values(cmp, 0, op); + case LVT_STRING: + cmp = szstrcmp(&expr->value.string, &other->value.string); + *status = compare_rich_integer_values_signed(cmp, 0, op); + result = true; + break; + + case LVT_REG_EXPR: + cmp = strcmp(expr->value.regex, other->value.regex); + *status = compare_rich_integer_values_signed(cmp, 0, op); result = true; break; @@ -509,62 +569,63 @@ static bool g_literal_expression_compare_rich(const GLiteralExpression *item, co /****************************************************************************** * * -* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] * -* src = expression source à copier. * +* 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 : Reproduit une expression en place dans une nouvelle instance.* +* Description : Réduit une expression à une forme booléenne. * * * -* Retour : - * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * * Remarques : - * * * ******************************************************************************/ -static void g_literal_expression_copy(GLiteralExpression *dest, const GLiteralExpression *src) +static bool g_scan_literal_expression_reduce_to_boolean(GScanLiteralExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - 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)); - - dest->value_type = src->value_type; + bool result; /* Bilan à retourner */ - switch (src->value_type) + switch (expr->value_type) { - case EVT_BOOLEAN: - dest->value.boolean = src->value.boolean; + case LVT_BOOLEAN: + *out = G_SCAN_EXPRESSION(expr); + g_object_ref(G_OBJECT(expr)); + result = true; break; - case EVT_INTEGER: - dest->value.integer = src->value.integer; + case LVT_SIGNED_INTEGER: + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->value.s_integer != 0 }); + result = true; break; - case EVT_STRING: - szstrdup(&dest->value.string, &src->value.string); + case LVT_UNSIGNED_INTEGER: + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->value.u_integer != 0 }); + result = true; break; - case EVT_REG_EXPR: - /*ptr = &expr->value.regex*//* FIXME */; + case LVT_STRING: + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->value.string.len > 0 }); + result = true; break; default: - assert(false); + result = false; break; } + 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] * +* count = quantité d'éléments déterminée. [OUT] * * * -* Description : Réduit une expression à une forme plus simple. * +* Description : Dénombre les éléments portés par une expression. * * * * Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * @@ -572,14 +633,22 @@ static void g_literal_expression_copy(GLiteralExpression *dest, const GLiteralEx * * ******************************************************************************/ -static bool g_literal_expression_reduce(GLiteralExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +static bool g_scan_literal_expression_count(const GScanLiteralExpression *expr, size_t *count) { bool result; /* Bilan à retourner */ - result = true; + switch (expr->value_type) + { + case LVT_STRING: + *count = expr->value.string.len; + result = true; + break; + + default: + result = false; + break; - *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 7120c07..9352baf 100644 --- a/src/analysis/scan/exprs/literal.h +++ b/src/analysis/scan/exprs/literal.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * literal.h - prototypes pour la représentation d'une valeur concrète * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -26,6 +26,7 @@ #include <regex.h> +#include <stdbool.h> #include "../expr.h" @@ -33,38 +34,56 @@ -#define G_TYPE_LITERAL_EXPRESSION g_literal_expression_get_type() -#define G_LITERAL_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_LITERAL_EXPRESSION, GLiteralExpression)) -#define G_IS_LITERAL_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_LITERAL_EXPRESSION)) -#define G_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_LITERAL_EXPRESSION, GLiteralExpressionClass)) -#define G_IS_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_LITERAL_EXPRESSION)) -#define G_LITERAL_EXPRESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_LITERAL_EXPRESSION, GLiteralExpressionClass)) +#define G_TYPE_SCAN_LITERAL_EXPRESSION g_scan_literal_expression_get_type() +#define G_SCAN_LITERAL_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_LITERAL_EXPRESSION, GScanLiteralExpression)) +#define G_IS_SCAN_LITERAL_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_LITERAL_EXPRESSION)) +#define G_SCAN_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_LITERAL_EXPRESSION, GScanLiteralExpressionClass)) +#define G_IS_SCAN_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_LITERAL_EXPRESSION)) +#define G_SCAN_LITERAL_EXPRESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_LITERAL_EXPRESSION, GScanLiteralExpressionClass)) /* Expression portant une valeur concrète (instance) */ -typedef struct _GLiteralExpression GLiteralExpression; +typedef struct _GScanLiteralExpression GScanLiteralExpression; /* Expression portant une valeur concrète (classe) */ -typedef struct _GLiteralExpressionClass GLiteralExpressionClass; +typedef struct _GScanLiteralExpressionClass GScanLiteralExpressionClass; + + +/* Types naturel équivalant à l'expression */ +typedef enum _LiteralValueType +{ + LVT_BOOLEAN, /* Valeur booléenne */ + LVT_SIGNED_INTEGER, /* Nombre entier 64 bits #1 */ + LVT_UNSIGNED_INTEGER, /* Nombre entier 64 bits #2 */ + LVT_STRING, /* Chaîne de caractères */ + LVT_REG_EXPR, /* Expression rationnelle */ + +} LiteralValueType; /* Indique le type défini pour un appel de fonction enregistrée. */ -GType g_literal_expression_get_type(void); +GType g_scan_literal_expression_get_type(void); /* Organise un appel de fonction avec ses arguments. */ -GScanExpression *g_literal_expression_new(ExprValueType, ...); +GScanExpression *g_scan_literal_expression_new(LiteralValueType, ...); + +/* Indique le type de valeur portée par une expression. */ +LiteralValueType g_scan_literal_expression_get_value_type(const GScanLiteralExpression *); /* Indique la valeur portée par une expression booléenne. */ -bool g_literal_expression_get_boolean_value(const GLiteralExpression *, bool *); +bool g_scan_literal_expression_get_boolean_value(const GScanLiteralExpression *, bool *); + +/* Indique la valeur portée par une expression d'entier. */ +bool g_scan_literal_expression_get_signed_integer_value(const GScanLiteralExpression *, long long *); /* Indique la valeur portée par une expression d'entier. */ -bool g_literal_expression_get_integer_value(const GLiteralExpression *, unsigned long long *); +bool g_scan_literal_expression_get_unsigned_integer_value(const GScanLiteralExpression *, unsigned long long *); /* Indique la valeur portée par une expression de chaîne. */ -bool g_literal_expression_get_string_value(const GLiteralExpression *, const sized_string_t **); +bool g_scan_literal_expression_get_string_value(const GScanLiteralExpression *, 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 **); +bool g_scan_literal_expression_get_regex_value(const GScanLiteralExpression *, const regex_t **); diff --git a/src/analysis/scan/exprs/boolop-int.h b/src/analysis/scan/exprs/logical-int.h index c381cfe..6df55d0 100644 --- a/src/analysis/scan/exprs/boolop-int.h +++ b/src/analysis/scan/exprs/logical-int.h @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * boolop-int.h - prototypes internes pour la gestion des opérations booléennes + * logical-int.h - prototypes internes pour la gestion des opérations booléennes * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,11 +21,11 @@ */ -#ifndef _ANALYSIS_SCAN_EXPRS_BOOLOP_INT_H -#define _ANALYSIS_SCAN_EXPRS_BOOLOP_INT_H +#ifndef _ANALYSIS_SCAN_EXPRS_LOGICAL_INT_H +#define _ANALYSIS_SCAN_EXPRS_LOGICAL_INT_H -#include "boolop.h" +#include "logical.h" #include "../expr-int.h" @@ -33,7 +33,7 @@ /* Opération booléenne avec un ou deux opérandes (instance) */ -struct _GBoolOperation +struct _GScanLogicalOperation { GScanExpression parent; /* A laisser en premier */ @@ -45,7 +45,7 @@ struct _GBoolOperation }; /* Opération booléenne avec un ou deux opérandes (classe) */ -struct _GBoolOperationClass +struct _GScanLogicalOperationClass { GScanExpressionClass parent; /* A laisser en premier */ @@ -53,8 +53,8 @@ struct _GBoolOperationClass /* Met en place une expression d'opération booléenne. */ -bool g_boolean_operation_create(GBoolOperation *, BooleanOperationType, GScanExpression *, GScanExpression *); +bool g_scan_logical_operation_create(GScanLogicalOperation *, BooleanOperationType, GScanExpression *, GScanExpression *); -#endif /* _ANALYSIS_SCAN_EXPRS_BOOLOP_INT_H */ +#endif /* _ANALYSIS_SCAN_EXPRS_LOGICAL_INT_H */ diff --git a/src/analysis/scan/exprs/boolop.c b/src/analysis/scan/exprs/logical.c index f6a80dd..4c82b1e 100644 --- a/src/analysis/scan/exprs/boolop.c +++ b/src/analysis/scan/exprs/logical.c @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * boolop.c - gestion des opérations booléennes + * logical.c - gestion des opérations booléennes * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,13 +21,13 @@ */ -#include "boolop.h" +#include "logical.h" #include <assert.h> -#include "boolop-int.h" +#include "logical-int.h" #include "literal.h" @@ -36,16 +36,16 @@ /* Initialise la classe des opérations booléennes. */ -static void g_boolean_operation_class_init(GBoolOperationClass *); +static void g_scan_logical_operation_class_init(GScanLogicalOperationClass *); /* Initialise une instance d'opération booléenne. */ -static void g_boolean_operation_init(GBoolOperation *); +static void g_scan_logical_operation_init(GScanLogicalOperation *); /* Supprime toutes les références externes. */ -static void g_boolean_operation_dispose(GBoolOperation *); +static void g_scan_logical_operation_dispose(GScanLogicalOperation *); /* Procède à la libération totale de la mémoire. */ -static void g_boolean_operation_finalize(GBoolOperation *); +static void g_scan_logical_operation_finalize(GScanLogicalOperation *); @@ -53,13 +53,10 @@ static void g_boolean_operation_finalize(GBoolOperation *); /* Réalise une comparaison entre objets selon un critère précis. */ -static bool g_boolean_operation_compare_rich(const GBoolOperation *, const GBoolOperation *, RichCmpOperation, bool *); - -/* Reproduit une expression en place dans une nouvelle instance. */ -static void g_boolean_operation_copy(GBoolOperation *, const GBoolOperation *); +static bool g_scan_logical_operation_compare_rich(const GScanLogicalOperation *, const GScanLogicalOperation *, RichCmpOperation, bool *); /* Réduit une expression à une forme plus simple. */ -static bool g_boolean_operation_reduce(GBoolOperation *, GScanContext *, GScanScope *, GScanExpression **); +static ScanReductionState g_scan_logical_operation_reduce(GScanLogicalOperation *, GScanContext *, GScanScope *, GScanExpression **); @@ -69,7 +66,7 @@ static bool g_boolean_operation_reduce(GBoolOperation *, GScanContext *, GScanSc /* Indique le type défini pour une opération booléenne sur expression(s). */ -G_DEFINE_TYPE(GBoolOperation, g_boolean_operation, G_TYPE_SCAN_EXPRESSION); +G_DEFINE_TYPE(GScanLogicalOperation, g_scan_logical_operation, G_TYPE_SCAN_EXPRESSION); /****************************************************************************** @@ -84,21 +81,20 @@ G_DEFINE_TYPE(GBoolOperation, g_boolean_operation, G_TYPE_SCAN_EXPRESSION); * * ******************************************************************************/ -static void g_boolean_operation_class_init(GBoolOperationClass *klass) +static void g_scan_logical_operation_class_init(GScanLogicalOperationClass *klass) { GObjectClass *object; /* Autre version de la classe */ GScanExpressionClass *expr; /* Version de classe parente */ object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_boolean_operation_dispose; - object->finalize = (GObjectFinalizeFunc)g_boolean_operation_finalize; + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_logical_operation_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_logical_operation_finalize; expr = G_SCAN_EXPRESSION_CLASS(klass); - expr->cmp_rich = (compare_expr_rich_fc)g_boolean_operation_compare_rich; - expr->copy = (copy_expr_fc)g_boolean_operation_copy; - expr->reduce = (reduce_expr_fc)g_boolean_operation_reduce; + expr->cmp_rich = (compare_expr_rich_fc)g_scan_logical_operation_compare_rich; + expr->reduce = (reduce_expr_fc)g_scan_logical_operation_reduce; } @@ -115,7 +111,7 @@ static void g_boolean_operation_class_init(GBoolOperationClass *klass) * * ******************************************************************************/ -static void g_boolean_operation_init(GBoolOperation *op) +static void g_scan_logical_operation_init(GScanLogicalOperation *op) { op->first = NULL; op->second = NULL; @@ -135,12 +131,12 @@ static void g_boolean_operation_init(GBoolOperation *op) * * ******************************************************************************/ -static void g_boolean_operation_dispose(GBoolOperation *op) +static void g_scan_logical_operation_dispose(GScanLogicalOperation *op) { g_clear_object(&op->first); g_clear_object(&op->second); - G_OBJECT_CLASS(g_boolean_operation_parent_class)->dispose(G_OBJECT(op)); + G_OBJECT_CLASS(g_scan_logical_operation_parent_class)->dispose(G_OBJECT(op)); } @@ -157,9 +153,9 @@ static void g_boolean_operation_dispose(GBoolOperation *op) * * ******************************************************************************/ -static void g_boolean_operation_finalize(GBoolOperation *op) +static void g_scan_logical_operation_finalize(GScanLogicalOperation *op) { - G_OBJECT_CLASS(g_boolean_operation_parent_class)->finalize(G_OBJECT(op)); + G_OBJECT_CLASS(g_scan_logical_operation_parent_class)->finalize(G_OBJECT(op)); } @@ -178,13 +174,13 @@ static void g_boolean_operation_finalize(GBoolOperation *op) * * ******************************************************************************/ -GScanExpression *g_boolean_operation_new(BooleanOperationType type, GScanExpression *first, GScanExpression *second) +GScanExpression *g_scan_logical_operation_new(BooleanOperationType type, GScanExpression *first, GScanExpression *second) { GScanExpression *result; /* Structure à retourner */ result = g_object_new(G_TYPE_BOOLEAN_OPERATION, NULL); - if (!g_boolean_operation_create(G_BOOLEAN_OPERATION(result), type, first, second)) + if (!g_scan_logical_operation_create(G_SCAN_LOGICAL_OPERATION(result), type, first, second)) g_clear_object(&result); return result; @@ -207,21 +203,10 @@ GScanExpression *g_boolean_operation_new(BooleanOperationType type, GScanExpress * * ******************************************************************************/ -bool g_boolean_operation_create(GBoolOperation *op, BooleanOperationType type, GScanExpression *first, GScanExpression *second) +bool g_scan_logical_operation_create(GScanLogicalOperation *op, BooleanOperationType type, GScanExpression *first, GScanExpression *second) { bool result; /* Bilan à retourner */ - result = false; - - if (g_scan_expression_get_value_type(first) != EVT_BOOLEAN) - goto exit; - - if (g_scan_expression_get_value_type(second) != EVT_BOOLEAN) - goto exit; - - if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_BOOLEAN)) - goto exit; - op->type = type; switch (type) @@ -245,9 +230,11 @@ bool g_boolean_operation_create(GBoolOperation *op, BooleanOperationType type, G assert(second != NULL); break; - } + default: + result = false; + break; - exit: + } return result; @@ -275,7 +262,7 @@ 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) +static bool g_scan_logical_operation_compare_rich(const GScanLogicalOperation *item, const GScanLogicalOperation *other, RichCmpOperation op, bool *status) { bool result; /* Etat à retourner */ @@ -284,7 +271,7 @@ static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const G if (item->type != other->type) { - *status = compare_rich_integer_values(item->type, other->type, op); + *status = compare_rich_integer_values_unsigned(item->type, other->type, op); goto done; } @@ -332,37 +319,6 @@ static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const G /****************************************************************************** * * -* 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_boolean_operation_copy(GBoolOperation *dest, const GBoolOperation *src) -{ - GScanExpressionClass *class; /* Classe parente à solliciter */ - - class = G_SCAN_EXPRESSION_CLASS(g_boolean_operation_parent_class); - - 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); - -} - - -/****************************************************************************** -* * * Paramètres : expr = expression à consulter. * * ctx = contexte de suivi de l'analyse courante. * * scope = portée courante des variables locales. * @@ -376,100 +332,173 @@ static void g_boolean_operation_copy(GBoolOperation *dest, const GBoolOperation * * ******************************************************************************/ -static bool g_boolean_operation_reduce(GBoolOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +static ScanReductionState g_scan_logical_operation_reduce(GScanLogicalOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - bool result; /* Bilan à retourner */ + ScanReductionState result; /* Etat synthétisé à retourner */ GScanExpression *new_first; /* Expression réduite (gauche) */ + ScanReductionState state[2]; /* Bilan de sous-réductons */ GScanExpression *new_second; /* Expression réduite (droite) */ + GScanExpression *bool_operands[2]; /* Expressions booléennes */ bool values[2]; /* Valeurs des éléments portés */ bool valid[2]; /* Validité de ces valeurs */ /* Réduction des éléments considérés */ - new_first = NULL; - new_second = NULL; - - result = g_scan_expression_reduce(expr->first, ctx, scope, &new_first); - if (!result) goto exit; + state[0] = g_scan_expression_reduce(expr->first, ctx, scope, &new_first); - if (expr->second == NULL) - new_second = NULL; + if (expr->second != NULL) + state[1] = g_scan_expression_reduce(expr->second, ctx, scope, &new_second); else { - result = g_scan_expression_reduce(expr->second, ctx, scope, &new_second); - if (!result) goto exit; + new_second = NULL; + state[1] = SRS_REDUCED; } - /* Construction d'une réduction locale ? */ + /* Récupération des valeurs booléennes */ - valid[0] = G_IS_LITERAL_EXPRESSION(new_first); + if (new_first != NULL) + { + valid[0] = g_scan_expression_reduce_to_boolean(new_first, ctx, scope, &bool_operands[0]); - if (valid[0]) - valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(new_first), &values[0]); + if (valid[0]) + valid[0] = g_scan_literal_expression_get_boolean_value(G_SCAN_LITERAL_EXPRESSION(bool_operands[0]), + &values[0]); + else + bool_operands[0] = NULL; - valid[1] = G_IS_LITERAL_EXPRESSION(new_second); + } + else + { + bool_operands[0] = NULL; + valid[0] = false; + } - if (valid[1]) - valid[1] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(new_second), &values[1]); + if (new_second != NULL) + { + valid[1] = g_scan_expression_reduce_to_boolean(new_second, ctx, scope, &bool_operands[1]); + + if (valid[1]) + valid[1] = g_scan_literal_expression_get_boolean_value(G_SCAN_LITERAL_EXPRESSION(bool_operands[1]), + &values[1]); + else + bool_operands[1] = NULL; + + } + else + { + bool_operands[1] = NULL; + valid[1] = false; + } + + /* Construction d'une réduction locale ? */ switch (expr->type) { case BOT_AND: if (valid[0] && valid[1]) - *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] && values[1] }); + { + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { values[0] && values[1] }); + result = SRS_REDUCED; + } else if (valid[0] && !values[0]) - *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false }); + { + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { false }); + result = SRS_REDUCED; + } else if (valid[1] && !values[1]) - *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false }); + { + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { false }); + result = SRS_REDUCED; + } + + else + { + if (state[0] == SRS_UNRESOLVABLE || state[1] == SRS_UNRESOLVABLE) + result = SRS_UNRESOLVABLE; + else + { + assert(state[0] == SRS_WAIT_FOR_SCAN || state[1] == SRS_WAIT_FOR_SCAN); + result = SRS_WAIT_FOR_SCAN; + } + } break; case BOT_OR: if (valid[0] && valid[1]) - *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] || values[1] }); + { + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { values[0] || values[1] }); + result = SRS_REDUCED; + } else if (valid[0] && values[0]) - *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { true }); + { + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { true }); + result = SRS_REDUCED; + } else if (valid[1] && values[1]) - *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { true }); + { + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { true }); + result = SRS_REDUCED; + } + + else + { + if (state[0] == SRS_UNRESOLVABLE || state[1] == SRS_UNRESOLVABLE) + result = SRS_UNRESOLVABLE; + else + { + assert(state[0] == SRS_WAIT_FOR_SCAN || state[1] == SRS_WAIT_FOR_SCAN); + result = SRS_WAIT_FOR_SCAN; + } + } break; case BOT_NOT: if (valid[0]) - *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { !values[0] }); + { + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { !values[0] }); + result = SRS_REDUCED; + } + + else + { + if (state[0] == SRS_UNRESOLVABLE) + result = SRS_UNRESOLVABLE; + else + { + assert(state[0] == SRS_WAIT_FOR_SCAN); + result = SRS_WAIT_FOR_SCAN; + } + } + break; } /* Mise à jour de la progression ? */ - if (*out == NULL) + if (result == SRS_WAIT_FOR_SCAN) { - if ((new_first != NULL && new_first != expr->first) || (new_second != NULL && new_second != expr->second)) + if (new_first != expr->first || new_second != expr->second) { - if (new_first == NULL) - { - new_first = expr->first; - g_object_ref(G_OBJECT(new_first)); - } + assert(new_first != NULL); + assert(new_second != NULL || expr->second == NULL); - if (new_second == NULL) - { - new_second = expr->second; - g_object_ref(G_OBJECT(new_second)); - } - - *out = g_boolean_operation_new(expr->type, new_first, new_second); + *out = g_scan_logical_operation_new(expr->type, new_first, new_second); } } - exit: + /* Sortie propre */ + + g_clear_object(&bool_operands[0]); + g_clear_object(&bool_operands[1]); g_clear_object(&new_first); g_clear_object(&new_second); diff --git a/src/analysis/scan/exprs/boolop.h b/src/analysis/scan/exprs/logical.h index 4add5a1..e98bf11 100644 --- a/src/analysis/scan/exprs/boolop.h +++ b/src/analysis/scan/exprs/logical.h @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * boolop.h - prototypes pour la gestion des opérations booléennes + * logical.h - prototypes pour la gestion des opérations booléennes * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,27 +21,27 @@ */ -#ifndef _ANALYSIS_SCAN_EXPRS_BOOLOP_H -#define _ANALYSIS_SCAN_EXPRS_BOOLOP_H +#ifndef _ANALYSIS_SCAN_EXPRS_LOGICAL_H +#define _ANALYSIS_SCAN_EXPRS_LOGICAL_H #include "../expr.h" -#define G_TYPE_BOOLEAN_OPERATION g_boolean_operation_get_type() -#define G_BOOLEAN_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BOOLEAN_OPERATION, GBoolOperation)) +#define G_TYPE_BOOLEAN_OPERATION g_scan_logical_operation_get_type() +#define G_SCAN_LOGICAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BOOLEAN_OPERATION, GScanLogicalOperation)) #define G_IS_BOOLEAN_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BOOLEAN_OPERATION)) -#define G_BOOLEAN_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BOOLEAN_OPERATION, GBoolOperationClass)) +#define G_SCAN_LOGICAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BOOLEAN_OPERATION, GScanLogicalOperationClass)) #define G_IS_BOOLEAN_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BOOLEAN_OPERATION)) -#define G_BOOLEAN_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BOOLEAN_OPERATION, GBoolOperationClass)) +#define G_SCAN_LOGICAL_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BOOLEAN_OPERATION, GScanLogicalOperationClass)) /* Opération booléenne avec un ou deux opérandes (instance) */ -typedef struct _GBoolOperation GBoolOperation; +typedef struct _GScanLogicalOperation GScanLogicalOperation; /* Opération booléenne avec un ou deux opérandes (classe) */ -typedef struct _GBoolOperationClass GBoolOperationClass; +typedef struct _GScanLogicalOperationClass GScanLogicalOperationClass; /* Types d'opérations booléennes supportées */ @@ -55,11 +55,11 @@ typedef enum _BooleanOperationType /* Indique le type défini pour une opération booléenne sur expression(s). */ -GType g_boolean_operation_get_type(void); +GType g_scan_logical_operation_get_type(void); /* Organise un appel de fonction avec ses arguments. */ -GScanExpression *g_boolean_operation_new(BooleanOperationType, GScanExpression *, GScanExpression *); +GScanExpression *g_scan_logical_operation_new(BooleanOperationType, GScanExpression *, GScanExpression *); -#endif /* _ANALYSIS_SCAN_EXPRS_BOOLOP_H */ +#endif /* _ANALYSIS_SCAN_EXPRS_LOGICAL_H */ diff --git a/src/analysis/scan/exprs/range-int.h b/src/analysis/scan/exprs/range-int.h new file mode 100644 index 0000000..6257874 --- /dev/null +++ b/src/analysis/scan/exprs/range-int.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * range-int.h - prototypes internes pour la représentation compacte d'un éventail de valeurs + * + * 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_RANGE_INT_H +#define _ANALYSIS_SCAN_EXPRS_RANGE_INT_H + + +#include "range.h" + + +#include "../expr-int.h" + + + +/* Représentation compacte d'un éventail de valeurs (instance) */ +struct _GScanCompactRange +{ + GScanExpression parent; /* A laisser en premier */ + + GScanExpression *start; /* Point de départ */ + GScanExpression *end; /* Point d'arrivée */ + +}; + +/* Représentation compacte d'un éventail de valeurs (classe) */ +struct _GScanCompactRangeClass +{ + GScanExpressionClass parent; /* A laisser en premier */ + +}; + + +/* Met en place une réprésentation d'un éventail de valeurs. */ +bool g_scan_compact_range_create(GScanCompactRange *, GScanExpression *, GScanExpression *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_RANGE_INT_H */ diff --git a/src/analysis/scan/exprs/range.c b/src/analysis/scan/exprs/range.c new file mode 100644 index 0000000..f97b15e --- /dev/null +++ b/src/analysis/scan/exprs/range.c @@ -0,0 +1,352 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * range.c - représentation compacte d'un éventail de valeurs + * + * 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 "range.h" + + +#include "literal.h" +#include "range-int.h" + + + +/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */ + + +/* Initialise la classe des éventail de valeurs. */ +static void g_scan_compact_range_class_init(GScanCompactRangeClass *); + +/* Initialise une instance d'éventail de valeurs. */ +static void g_scan_compact_range_init(GScanCompactRange *); + +/* Supprime toutes les références externes. */ +static void g_scan_compact_range_dispose(GScanCompactRange *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_compact_range_finalize(GScanCompactRange *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Réduit une expression à une forme plus simple. */ +static ScanReductionState g_scan_compact_range_reduce(GScanCompactRange *, GScanContext *, GScanScope *, GScanExpression **); + +/* Réduit une expression à une forme booléenne. */ +static bool g_scan_compact_range_reduce_to_boolean(GScanCompactRange *, GScanContext *, GScanScope *, GScanExpression **); + +/* Réalise l'intersection entre deux ensembles. */ +static GScanExpression *g_scan_compact_range_intersect(GScanCompactRange *expr, const GScanExpression *, GScanContext *, GScanScope *); + + + +/* ---------------------------------------------------------------------------------- */ +/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une représentation compacte d'un éventail de valeurs. */ +G_DEFINE_TYPE(GScanCompactRange, g_scan_compact_range, G_TYPE_SCAN_EXPRESSION); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des éventail de valeurs. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_compact_range_class_init(GScanCompactRangeClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanExpressionClass *expr; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_compact_range_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_compact_range_finalize; + + expr = G_SCAN_EXPRESSION_CLASS(klass); + + expr->reduce = (reduce_expr_fc)g_scan_compact_range_reduce; + expr->reduce_to_bool = (reduce_expr_to_bool_fc)g_scan_compact_range_reduce_to_boolean; + expr->intersect = (intersect_scan_expr_fc)g_scan_compact_range_intersect; + +} + + +/****************************************************************************** +* * +* Paramètres : range = instance à initialiser. * +* * +* Description : Initialise une instance d'éventail de valeurs. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_compact_range_init(GScanCompactRange *range) +{ + range->start = NULL; + range->end = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : range = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_compact_range_dispose(GScanCompactRange *range) +{ + g_clear_object(&range->start); + g_clear_object(&range->end); + + G_OBJECT_CLASS(g_scan_compact_range_parent_class)->dispose(G_OBJECT(range)); + +} + + +/****************************************************************************** +* * +* Paramètres : range = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_compact_range_finalize(GScanCompactRange *range) +{ + G_OBJECT_CLASS(g_scan_compact_range_parent_class)->finalize(G_OBJECT(range)); + +} + + +/****************************************************************************** +* * +* Paramètres : start = point de départ de la plage de valeurs. * +* end = point d'arrivée de la plage de valeurs. * +* * +* Description : Organise une réprésentation d'un éventail de valeurs. * +* * +* Retour : Expression mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_scan_compact_range_new(GScanExpression *start, GScanExpression *end) +{ + GScanExpression *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_COMPACT_RANGE, NULL); + + if (!g_scan_compact_range_create(G_SCAN_COMPACT_RANGE(result), start, end)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : range = instance à initialiser pleinement. * +* start = point de départ de la plage de valeurs. * +* end = point d'arrivée de la plage de valeurs. * +* * +* Description : Met en place une réprésentation d'un éventail de valeurs. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_scan_compact_range_create(GScanCompactRange *range, GScanExpression *start, GScanExpression *end) +{ + bool result; /* Bilan à retourner */ + + result = true; + + range->start = start; + g_object_ref(G_OBJECT(start)); + + range->end = end; + g_object_ref(G_OBJECT(end)); + + 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_compact_range_reduce(GScanCompactRange *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +{ + ScanReductionState result; /* Etat synthétisé à retourner */ + GScanExpression *new_start; /* Nouvelle réduction #1 */ + GScanExpression *new_end; /* Nouvelle réduction #2 */ + ScanReductionState state_start; /* Etat synthétisé #1 */ + ScanReductionState state_end; /* Etat synthétisé #2 */ + + new_start = NULL; + new_end = NULL; + + state_start = g_scan_expression_reduce(expr->start, ctx, scope, &new_start); + if (state_start == SRS_UNRESOLVABLE) + { + result = SRS_UNRESOLVABLE; + goto exit; + } + + state_end = g_scan_expression_reduce(expr->end, ctx, scope, &new_end); + if (state_end == SRS_UNRESOLVABLE) + { + result = SRS_UNRESOLVABLE; + goto exit; + } + + if (state_start == SRS_WAIT_FOR_SCAN || state_end == SRS_WAIT_FOR_SCAN) + result = SRS_WAIT_FOR_SCAN; + else + result = SRS_REDUCED; + + if (new_start != expr->start || new_end != expr->end) + *out = g_scan_compact_range_new(new_start, new_end); + + exit: + + g_clear_object(&new_start); + g_clear_object(&new_end); + + 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 booléenne. * +* * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_scan_compact_range_reduce_to_boolean(GScanCompactRange *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +{ + bool result; /* Bilan à retourner */ + bool status; /* Bilan d'une comparaison */ + + result = G_IS_SCAN_LITERAL_EXPRESSION(expr->start) && G_IS_SCAN_LITERAL_EXPRESSION(expr->end); + if (!result) goto exit; + + result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(expr->start), + G_COMPARABLE_ITEM(expr->end), + RCO_LE, &status); + if (!result) goto exit; + + *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = expression à filtrer. * +* other = expression utilisée pour le filtrage. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* * +* Description : Réalise l'intersection entre deux ensembles. * +* * +* Retour : Intersection entre les deux ensembles ou NULL en cas d'échec.* +* * +* Remarques : - * +* * +******************************************************************************/ + +static GScanExpression *g_scan_compact_range_intersect(GScanCompactRange *expr, const GScanExpression *other, GScanContext *ctx, GScanScope *scope) +{ + GScanExpression *result; /* Instance à retourner */ + + + + + result = true; // TODO + + + + + return result; + +} diff --git a/src/analysis/scan/exprs/range.h b/src/analysis/scan/exprs/range.h new file mode 100644 index 0000000..4b7ad04 --- /dev/null +++ b/src/analysis/scan/exprs/range.h @@ -0,0 +1,55 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * range.h - prototypes pour la représentation compacte d'un éventail de valeurs + * + * 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_SET_H +#define _ANALYSIS_SCAN_EXPRS_SET_H + + +#include "../expr.h" + + + +#define G_TYPE_SCAN_COMPACT_RANGE g_scan_compact_range_get_type() +#define G_SCAN_COMPACT_RANGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_COMPACT_RANGE, GScanCompactRange)) +#define G_IS_SCAN_COMPACT_RANGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_COMPACT_RANGE)) +#define G_SCAN_COMPACT_RANGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_COMPACT_RANGE, GScanCompactRangeClass)) +#define G_IS_SCAN_COMPACT_RANGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_COMPACT_RANGE)) +#define G_SCAN_COMPACT_RANGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_COMPACT_RANGE, GScanCompactRangeClass)) + + +/* Représentation compacte d'un éventail de valeurs (instance) */ +typedef struct _GScanCompactRange GScanCompactRange; + +/* Représentation compacte d'un éventail de valeurs (classe) */ +typedef struct _GScanCompactRangeClass GScanCompactRangeClass; + + +/* Indique le type défini pour une représentation compacte d'un éventail de valeurs. */ +GType g_scan_compact_range_get_type(void); + +/* Organise une réprésentation d'un éventail de valeurs. */ +GScanExpression *g_scan_compact_range_new(GScanExpression *, GScanExpression *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_SET_H */ diff --git a/src/analysis/scan/exprs/relop-int.h b/src/analysis/scan/exprs/relational-int.h index 3adbcf0..813b89d 100644 --- a/src/analysis/scan/exprs/relop-int.h +++ b/src/analysis/scan/exprs/relational-int.h @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * relop-int.h - prototypes internes pour la gestion des opérations relationnelles + * relational-int.h - prototypes internes pour la gestion des opérations relationnelles * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,11 +21,11 @@ */ -#ifndef _ANALYSIS_SCAN_EXPRS_RELOP_INT_H -#define _ANALYSIS_SCAN_EXPRS_RELOP_INT_H +#ifndef _ANALYSIS_SCAN_EXPRS_RELATIONAL_INT_H +#define _ANALYSIS_SCAN_EXPRS_RELATIONAL_INT_H -#include "relop.h" +#include "relational.h" #include "../expr-int.h" @@ -33,7 +33,7 @@ /* Opération relationnelle impliquant deux opérandes (instance) */ -struct _GRelOperation +struct _GScanRelationalOperation { GScanExpression parent; /* A laisser en premier */ @@ -45,7 +45,7 @@ struct _GRelOperation }; /* Opération relationnelle impliquant deux opérandes (classe) */ -struct _GRelOperationClass +struct _GScanRelationalOperationClass { GScanExpressionClass parent; /* A laisser en premier */ @@ -53,8 +53,8 @@ struct _GRelOperationClass /* Met en place une opération relationnelle entre expressions. */ -bool g_relational_operation_create(GRelOperation *, RichCmpOperation, GScanExpression *, GScanExpression *); +bool g_scan_relational_operation_create(GScanRelationalOperation *, RichCmpOperation, GScanExpression *, GScanExpression *); -#endif /* _ANALYSIS_SCAN_EXPRS_RELOP_INT_H */ +#endif /* _ANALYSIS_SCAN_EXPRS_RELATIONAL_INT_H */ diff --git a/src/analysis/scan/exprs/relop.c b/src/analysis/scan/exprs/relational.c index 7dc6864..b56b599 100644 --- a/src/analysis/scan/exprs/relop.c +++ b/src/analysis/scan/exprs/relational.c @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * relop.c - gestion des opérations relationnelles + * relational.c - gestion des opérations relationnelles * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,10 +21,13 @@ */ -#include "relop.h" +#include "relational.h" -#include "relop-int.h" +#include <assert.h> + + +#include "relational-int.h" #include "literal.h" @@ -33,16 +36,16 @@ /* Initialise la classe des opérations de relations. */ -static void g_relational_operation_class_init(GRelOperationClass *); +static void g_scan_relational_operation_class_init(GScanRelationalOperationClass *); /* Initialise une instance d'opération de relation. */ -static void g_relational_operation_init(GRelOperation *); +static void g_scan_relational_operation_init(GScanRelationalOperation *); /* Supprime toutes les références externes. */ -static void g_relational_operation_dispose(GRelOperation *); +static void g_scan_relational_operation_dispose(GScanRelationalOperation *); /* Procède à la libération totale de la mémoire. */ -static void g_relational_operation_finalize(GRelOperation *); +static void g_scan_relational_operation_finalize(GScanRelationalOperation *); @@ -50,13 +53,10 @@ 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 *); - -/* Reproduit une expression en place dans une nouvelle instance. */ -static void g_relational_operation_copy(GRelOperation *, const GRelOperation *); +static bool g_scan_relational_operation_compare_rich(const GScanRelationalOperation *, const GScanRelationalOperation *, RichCmpOperation, bool *); /* Réduit une expression à une forme plus simple. */ -static bool g_relational_operation_reduce(GRelOperation *, GScanContext *, GScanScope *, GScanExpression **); +static ScanReductionState g_scan_relational_operation_reduce(GScanRelationalOperation *, GScanContext *, GScanScope *, GScanExpression **); @@ -66,7 +66,7 @@ static bool g_relational_operation_reduce(GRelOperation *, GScanContext *, GScan /* Indique le type défini pour une opération de relation entre expressions. */ -G_DEFINE_TYPE(GRelOperation, g_relational_operation, G_TYPE_SCAN_EXPRESSION); +G_DEFINE_TYPE(GScanRelationalOperation, g_scan_relational_operation, G_TYPE_SCAN_EXPRESSION); /****************************************************************************** @@ -81,21 +81,20 @@ G_DEFINE_TYPE(GRelOperation, g_relational_operation, G_TYPE_SCAN_EXPRESSION); * * ******************************************************************************/ -static void g_relational_operation_class_init(GRelOperationClass *klass) +static void g_scan_relational_operation_class_init(GScanRelationalOperationClass *klass) { GObjectClass *object; /* Autre version de la classe */ GScanExpressionClass *expr; /* Version de classe parente */ object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_relational_operation_dispose; - object->finalize = (GObjectFinalizeFunc)g_relational_operation_finalize; + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_relational_operation_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_relational_operation_finalize; expr = G_SCAN_EXPRESSION_CLASS(klass); - expr->cmp_rich = (compare_expr_rich_fc)g_relational_operation_compare_rich; - expr->copy = (copy_expr_fc)g_relational_operation_copy; - expr->reduce = (reduce_expr_fc)g_relational_operation_reduce; + expr->cmp_rich = (compare_expr_rich_fc)g_scan_relational_operation_compare_rich; + expr->reduce = (reduce_expr_fc)g_scan_relational_operation_reduce; } @@ -112,7 +111,7 @@ static void g_relational_operation_class_init(GRelOperationClass *klass) * * ******************************************************************************/ -static void g_relational_operation_init(GRelOperation *op) +static void g_scan_relational_operation_init(GScanRelationalOperation *op) { op->left = NULL; op->right = NULL; @@ -132,12 +131,12 @@ static void g_relational_operation_init(GRelOperation *op) * * ******************************************************************************/ -static void g_relational_operation_dispose(GRelOperation *op) +static void g_scan_relational_operation_dispose(GScanRelationalOperation *op) { g_clear_object(&op->left); g_clear_object(&op->right); - G_OBJECT_CLASS(g_relational_operation_parent_class)->dispose(G_OBJECT(op)); + G_OBJECT_CLASS(g_scan_relational_operation_parent_class)->dispose(G_OBJECT(op)); } @@ -154,9 +153,9 @@ static void g_relational_operation_dispose(GRelOperation *op) * * ******************************************************************************/ -static void g_relational_operation_finalize(GRelOperation *op) +static void g_scan_relational_operation_finalize(GScanRelationalOperation *op) { - G_OBJECT_CLASS(g_relational_operation_parent_class)->finalize(G_OBJECT(op)); + G_OBJECT_CLASS(g_scan_relational_operation_parent_class)->finalize(G_OBJECT(op)); } @@ -175,13 +174,13 @@ static void g_relational_operation_finalize(GRelOperation *op) * * ******************************************************************************/ -GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpression *left, GScanExpression *right) +GScanExpression *g_scan_relational_operation_new(RichCmpOperation type, GScanExpression *left, GScanExpression *right) { GScanExpression *result; /* Structure à retourner */ - result = g_object_new(G_TYPE_RELATIONAL_OPERATION, NULL); + result = g_object_new(G_TYPE_SCAN_RELATIONAL_OPERATION, NULL); - if (!g_relational_operation_create(G_RELATIONAL_OPERATION(result), type, left, right)) + if (!g_scan_relational_operation_create(G_SCAN_RELATIONAL_OPERATION(result), type, left, right)) g_clear_object(&result); return result; @@ -204,17 +203,11 @@ GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpressi * * ******************************************************************************/ -bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GScanExpression *left, GScanExpression *right) +bool g_scan_relational_operation_create(GScanRelationalOperation *op, RichCmpOperation type, GScanExpression *left, GScanExpression *right) { bool result; /* Bilan à retourner */ - result = false; - - 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)) - goto exit; + result = true; op->rel_type = type; @@ -224,10 +217,6 @@ bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GSc op->right = right; g_object_ref(G_OBJECT(op->right)); - result = true; - - exit: - return result; } @@ -254,16 +243,16 @@ 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) +static bool g_scan_relational_operation_compare_rich(const GScanRelationalOperation *item, const GScanRelationalOperation *other, RichCmpOperation op, bool *status) { bool result; /* Etat à retourner */ - result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_RELATIONAL_OPERATION); + result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_SCAN_RELATIONAL_OPERATION); if (!result) goto done; if (item->rel_type != other->rel_type) { - *status = compare_rich_integer_values(item->rel_type, other->rel_type, op); + *status = compare_rich_integer_values_unsigned(item->rel_type, other->rel_type, op); goto done; } @@ -288,35 +277,6 @@ static bool g_relational_operation_compare_rich(const GRelOperation *item, const /****************************************************************************** * * -* 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_relational_operation_copy(GRelOperation *dest, const GRelOperation *src) -{ - GScanExpressionClass *class; /* Classe parente à solliciter */ - - class = G_SCAN_EXPRESSION_CLASS(g_relational_operation_parent_class); - - 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); - -} - - -/****************************************************************************** -* * * Paramètres : expr = expression à consulter. * * ctx = contexte de suivi de l'analyse courante. * * scope = portée courante des variables locales. * @@ -330,11 +290,16 @@ static void g_relational_operation_copy(GRelOperation *dest, const GRelOperation * * ******************************************************************************/ -static bool g_relational_operation_reduce(GRelOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +static ScanReductionState g_scan_relational_operation_reduce(GScanRelationalOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - bool result; /* Bilan à retourner */ + ScanReductionState result; /* Etat synthétisé à retourner */ GScanExpression *new_left; /* Expression réduite (gauche) */ GScanExpression *new_right; /* Expression réduite (droite) */ + ScanReductionState state_left; /* Etat synthétisé #1 */ + ScanReductionState state_right; /* Etat synthétisé #2 */ + LiteralValueType vtype_left; /* Type de valeur portée #1 */ + LiteralValueType vtype_right; /* Type de valeur portée #2 */ + GScanExpression *casted; /* Nouvelle forme en booléen */ bool status; /* Bilan d'une comparaison */ bool valid; /* Validité de ce bilan obtenu */ @@ -343,45 +308,96 @@ static bool g_relational_operation_reduce(GRelOperation *expr, GScanContext *ctx new_left = NULL; new_right = NULL; - result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left); - if (!result) goto exit; + state_left = g_scan_expression_reduce(expr->left, ctx, scope, &new_left); + if (state_left == SRS_UNRESOLVABLE) + { + result = SRS_UNRESOLVABLE; + goto exit; + } + + state_right = g_scan_expression_reduce(expr->right, ctx, scope, &new_right); + if (state_right == SRS_UNRESOLVABLE) + { + result = SRS_UNRESOLVABLE; + goto exit; + } + + /* Transtypage vers des booléens imposé ? */ + + if (expr->rel_type == RCO_EQ || expr->rel_type == RCO_NE) + { + if (G_IS_SCAN_LITERAL_EXPRESSION(new_left)) + { + vtype_left = g_scan_literal_expression_get_value_type(G_SCAN_LITERAL_EXPRESSION(new_left)); + + if (vtype_left == LVT_BOOLEAN) + { + if (g_scan_expression_reduce_to_boolean(new_right, ctx, scope, &casted)) + { + g_object_unref(G_OBJECT(new_right)); + new_right = casted; + } + } + + } + + if (G_IS_SCAN_LITERAL_EXPRESSION(new_right)) + { + vtype_right = g_scan_literal_expression_get_value_type(G_SCAN_LITERAL_EXPRESSION(new_right)); - result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right); - if (!result) goto exit; + if (vtype_right == LVT_BOOLEAN) + { + if (g_scan_expression_reduce_to_boolean(new_left, ctx, scope, &casted)) + { + g_object_unref(G_OBJECT(new_left)); + new_left = casted; + } + } + + } + + } /* Construction d'une réduction locale ? */ - if (G_IS_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right)) + if (G_IS_SCAN_LITERAL_EXPRESSION(new_left) && G_IS_SCAN_LITERAL_EXPRESSION(new_right)) { valid = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(new_left), G_COMPARABLE_ITEM(new_right), expr->rel_type, &status); if (valid) - *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { status }); + { + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { status }); + result = SRS_REDUCED; + } + else + result = SRS_UNRESOLVABLE; } /* Mise à jour de la progression ? */ - else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right)) + else if (state_left == SRS_WAIT_FOR_SCAN || state_right == SRS_WAIT_FOR_SCAN) { - if (new_left == NULL) - { - new_left = expr->left; - g_object_ref(G_OBJECT(new_left)); - } + if (new_left != expr->left || new_right != expr->right) + *out = g_scan_relational_operation_new(expr->rel_type, new_left, new_right); - if (new_right == NULL) - { - new_right = expr->right; - g_object_ref(G_OBJECT(new_right)); - } + result = SRS_WAIT_FOR_SCAN; - *out = g_relational_operation_new(expr->rel_type, new_left, new_right); + } + + /* Cas des situations où les expressions ne sont pas exploitables (!) */ + else + { + assert(state_left == SRS_REDUCED && state_right == SRS_REDUCED); + + result = SRS_UNRESOLVABLE; } + /* Sortie propre */ + exit: g_clear_object(&new_left); diff --git a/src/analysis/scan/exprs/relational.h b/src/analysis/scan/exprs/relational.h new file mode 100644 index 0000000..10d58a6 --- /dev/null +++ b/src/analysis/scan/exprs/relational.h @@ -0,0 +1,56 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * relational.h - prototypes pour la gestion des opérations relationnelles + * + * 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_RELATIONAL_H +#define _ANALYSIS_SCAN_EXPRS_RELATIONAL_H + + +#include "../expr.h" +#include "../../../glibext/comparison.h" + + + +#define G_TYPE_SCAN_RELATIONAL_OPERATION g_scan_relational_operation_get_type() +#define G_SCAN_RELATIONAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_RELATIONAL_OPERATION, GScanRelationalOperation)) +#define G_IS_SCAN_RELATIONAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_RELATIONAL_OPERATION)) +#define G_SCAN_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_RELATIONAL_OPERATION, GScanRelationalOperationClass)) +#define G_IS_SCAN_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_RELATIONAL_OPERATION)) +#define G_SCAN_RELATIONAL_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_RELATIONAL_OPERATION, GScanRelationalOperationClass)) + + +/* Opération relationnelle impliquant deux opérandes (instance) */ +typedef struct _GScanRelationalOperation GScanRelationalOperation; + +/* Opération relationnelle impliquant deux opérandes (classe) */ +typedef struct _GScanRelationalOperationClass GScanRelationalOperationClass; + + +/* Indique le type défini pour une opération de relation entre expressions. */ +GType g_scan_relational_operation_get_type(void); + +/* Organise une opération relationnelle entre expressions. */ +GScanExpression *g_scan_relational_operation_new(RichCmpOperation, GScanExpression *, GScanExpression *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_RELATIONAL_H */ diff --git a/src/analysis/scan/exprs/relop.h b/src/analysis/scan/exprs/relop.h deleted file mode 100644 index ecbc8ef..0000000 --- a/src/analysis/scan/exprs/relop.h +++ /dev/null @@ -1,56 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * relop.h - prototypes pour la gestion des opérations relationnelles - * - * 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_EXPRS_RELOP_H -#define _ANALYSIS_SCAN_EXPRS_RELOP_H - - -#include "../expr.h" -#include "../../../glibext/comparison.h" - - - -#define G_TYPE_RELATIONAL_OPERATION g_relational_operation_get_type() -#define G_RELATIONAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RELATIONAL_OPERATION, GRelOperation)) -#define G_IS_RELATIONAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RELATIONAL_OPERATION)) -#define G_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RELATIONAL_OPERATION, GRelOperationClass)) -#define G_IS_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RELATIONAL_OPERATION)) -#define G_RELATIONAL_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RELATIONAL_OPERATION, GRelOperationClass)) - - -/* Opération relationnelle impliquant deux opérandes (instance) */ -typedef struct _GRelOperation GRelOperation; - -/* Opération relationnelle impliquant deux opérandes (classe) */ -typedef struct _GRelOperationClass GRelOperationClass; - - -/* Indique le type défini pour une opération de relation entre expressions. */ -GType g_relational_operation_get_type(void); - -/* Organise une opération relationnelle entre expressions. */ -GScanExpression *g_relational_operation_new(RichCmpOperation, GScanExpression *, GScanExpression *); - - - -#endif /* _ANALYSIS_SCAN_EXPRS_RELOP_H */ diff --git a/src/analysis/scan/exprs/set-int.h b/src/analysis/scan/exprs/set-int.h new file mode 100644 index 0000000..ebb4380 --- /dev/null +++ b/src/analysis/scan/exprs/set-int.h @@ -0,0 +1,54 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * set-int.h - prototypes internes pour la base d'ensembles de valeurs diverses, de types hétérogènes ou homogènes + * + * 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_SET_INT_H +#define _ANALYSIS_SCAN_EXPRS_SET_INT_H + + +#include "set.h" + + +#include "../expr-int.h" + + + +/* Base d'un ensemble d'éléments homogènes ou hétérogènes (instance) */ +struct _GScanGenericSet +{ + GScanExpression parent; /* A laisser en premier */ + + GScanExpression **items; /* Liste d'éléments embarqués */ + size_t count; /* Quantité de ces éléments */ + +}; + +/* Base d'un ensemble d'éléments homogènes ou hétérogènes (classe) */ +struct _GScanGenericSetClass +{ + GScanExpressionClass parent; /* A laisser en premier */ + +}; + + + +#endif /* _ANALYSIS_SCAN_EXPRS_SET_INT_H */ diff --git a/src/analysis/scan/exprs/arithmop.c b/src/analysis/scan/exprs/set.c index 5f9e3f1..0a93ced 100644 --- a/src/analysis/scan/exprs/arithmop.c +++ b/src/analysis/scan/exprs/set.c @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * arithmop.c - gestion des opérations arithmétiques + * set.c - base d'ensembles de valeurs diverses, de types hétérogènes ou homogènes * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,42 +21,49 @@ */ -#include "arithmop.h" +#include "set.h" + + +#include <assert.h> +#include <malloc.h> -#include "arithmop-int.h" #include "literal.h" +#include "set-int.h" /* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */ -/* Initialise la classe des opérations arithmétiques. */ -static void g_arithmetic_operation_class_init(GArithmOperationClass *); +/* Initialise la classe des bases d'ensembles d'éléments. */ +static void g_scan_generic_set_class_init(GScanGenericSetClass *); -/* Initialise une instance d'opération arithmétique. */ -static void g_arithmetic_operation_init(GArithmOperation *); +/* Initialise une instance de base d'ensemble d'éléments. */ +static void g_scan_generic_set_init(GScanGenericSet *); /* Supprime toutes les références externes. */ -static void g_arithmetic_operation_dispose(GArithmOperation *); +static void g_scan_generic_set_dispose(GScanGenericSet *); /* Procède à la libération totale de la mémoire. */ -static void g_arithmetic_operation_finalize(GArithmOperation *); +static void g_scan_generic_set_finalize(GScanGenericSet *); /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ -/* 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 *); +/* Réduit une expression à une forme plus simple. */ +static ScanReductionState g_scan_generic_set_reduce(GScanGenericSet *, GScanContext *, GScanScope *, GScanExpression **); + +/* Réduit une expression à une forme booléenne. */ +static bool g_scan_generic_set_reduce_to_boolean(GScanGenericSet *, GScanContext *, GScanScope *, GScanExpression **); -/* Reproduit une expression en place dans une nouvelle instance. */ -static void g_arithmetic_operation_copy(GArithmOperation *, const GArithmOperation *); +/* Dénombre les éléments portés par une expression. */ +static bool g_scan_generic_set_count_items(const GScanGenericSet *, size_t *); -/* Réduit une expression à une forme plus simple. */ -static bool g_arithmetic_operation_reduce(GArithmOperation *, GScanContext *, GScanScope *, GScanExpression **); +/* Fournit un élément donné issu d'un ensemble constitué. */ +static bool g_scan_generic_set_get_item(const GScanGenericSet *, size_t, GScanExpression **); @@ -65,15 +72,15 @@ static bool g_arithmetic_operation_reduce(GArithmOperation *, GScanContext *, GS /* ---------------------------------------------------------------------------------- */ -/* Indique le type défini pour une opération de relation entre expressions. */ -G_DEFINE_TYPE(GArithmOperation, g_arithmetic_operation, G_TYPE_SCAN_EXPRESSION); +/* Indique le type défini pour une base d'ensembles d'éléments homogènes ou hétérogènes. */ +G_DEFINE_TYPE(GScanGenericSet, g_scan_generic_set, G_TYPE_SCAN_EXPRESSION); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * -* Description : Initialise la classe des opérations arithmétiques. * +* Description : Initialise la classe des bases d'ensembles d'éléments. * * * * Retour : - * * * @@ -81,30 +88,31 @@ G_DEFINE_TYPE(GArithmOperation, g_arithmetic_operation, G_TYPE_SCAN_EXPRESSION); * * ******************************************************************************/ -static void g_arithmetic_operation_class_init(GArithmOperationClass *klass) +static void g_scan_generic_set_class_init(GScanGenericSetClass *klass) { GObjectClass *object; /* Autre version de la classe */ GScanExpressionClass *expr; /* Version de classe parente */ object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_arithmetic_operation_dispose; - object->finalize = (GObjectFinalizeFunc)g_arithmetic_operation_finalize; + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_generic_set_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_generic_set_finalize; expr = G_SCAN_EXPRESSION_CLASS(klass); - expr->cmp_rich = (compare_expr_rich_fc)g_arithmetic_operation_compare_rich; - expr->copy = (copy_expr_fc)g_arithmetic_operation_copy; - expr->reduce = (reduce_expr_fc)g_arithmetic_operation_reduce; + expr->reduce = (reduce_expr_fc)g_scan_generic_set_reduce; + expr->reduce_to_bool = (reduce_expr_to_bool_fc)g_scan_generic_set_reduce_to_boolean; + expr->count = (count_scan_expr_fc)g_scan_generic_set_count_items; + expr->get = (get_scan_expr_fc)g_scan_generic_set_get_item; } /****************************************************************************** * * -* Paramètres : op = instance à initialiser. * +* Paramètres : set = instance à initialiser. * * * -* Description : Initialise une instance d'opération arithmétique. * +* Description : Initialise une instance de base d'ensemble d'éléments. * * * * Retour : - * * * @@ -112,17 +120,17 @@ static void g_arithmetic_operation_class_init(GArithmOperationClass *klass) * * ******************************************************************************/ -static void g_arithmetic_operation_init(GArithmOperation *op) +static void g_scan_generic_set_init(GScanGenericSet *set) { - op->left = NULL; - op->right = NULL; + set->items = NULL; + set->count = 0; } /****************************************************************************** * * -* Paramètres : op = instance d'objet GLib à traiter. * +* Paramètres : set = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -132,19 +140,21 @@ static void g_arithmetic_operation_init(GArithmOperation *op) * * ******************************************************************************/ -static void g_arithmetic_operation_dispose(GArithmOperation *op) +static void g_scan_generic_set_dispose(GScanGenericSet *set) { - g_clear_object(&op->left); - g_clear_object(&op->right); + size_t i; /* Boucle de parcours */ + + for (i = 0; i < set->count; i++) + g_clear_object(&set->items[i]); - G_OBJECT_CLASS(g_arithmetic_operation_parent_class)->dispose(G_OBJECT(op)); + G_OBJECT_CLASS(g_scan_generic_set_parent_class)->dispose(G_OBJECT(set)); } /****************************************************************************** * * -* Paramètres : op = instance d'objet GLib à traiter. * +* Paramètres : set = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -154,35 +164,33 @@ static void g_arithmetic_operation_dispose(GArithmOperation *op) * * ******************************************************************************/ -static void g_arithmetic_operation_finalize(GArithmOperation *op) +static void g_scan_generic_set_finalize(GScanGenericSet *set) { - G_OBJECT_CLASS(g_arithmetic_operation_parent_class)->finalize(G_OBJECT(op)); + if (set->items != NULL) + free(set->items); + + G_OBJECT_CLASS(g_scan_generic_set_parent_class)->finalize(G_OBJECT(set)); } /****************************************************************************** * * -* Paramètres : operator = type d'opération arithmétique à représenter. * -* left = premier opérande concerné. * -* right = éventuel second opérande impliqué ou NULL. * +* Paramètres : - * * * -* Description : Organise une opération arithmétique entre expressions. * +* Description : Met en place un ensemble d'éléments homogènes ou hétérogènes.* * * -* Retour : Fonction mise en place. * +* Retour : Expression mise en place. * * * * Remarques : - * * * ******************************************************************************/ -GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right) +GScanExpression *g_scan_generic_set_new(void) { GScanExpression *result; /* Structure à retourner */ - result = g_object_new(G_TYPE_ARITHMETIC_OPERATION, NULL); - - if (!g_arithmetic_operation_create(G_ARITHMETIC_OPERATION(result), operator, left, right)) - g_clear_object(&result); + result = g_object_new(G_TYPE_SCAN_GENERIC_SET, NULL); return result; @@ -191,52 +199,23 @@ GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operato /****************************************************************************** * * -* Paramètres : op = instance à initialiser pleinement. * -* operator = type d'opération booléenne à représenter. * -* left = premier opérande concerné. * -* right = éventuel second opérande impliqué ou NULL. * +* Paramètres : set = ensemble à compléter. * +* item = nouvel élément à intégrer. * * * -* Description : Met en place une opération arithmétique entre expressions. * +* Description : Ajoute un nouvel élément à un ensemble. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right) +void g_scan_generic_set_add_item(GScanGenericSet *set, GScanExpression *item) { - bool result; /* Bilan à retourner */ - ExprValueType vtype; /* Type de valeur portée */ - - result = false; - - vtype = g_scan_expression_get_value_type(left); + set->items = realloc(set->items, ++set->count * sizeof(GScanExpression *)); - if (vtype != EVT_INTEGER && vtype != EVT_PENDING) - goto exit; - - vtype = g_scan_expression_get_value_type(right); - - if (vtype != EVT_INTEGER && vtype != EVT_PENDING) - goto exit; - - if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_INTEGER)) - goto exit; - - op->operator = operator; - - op->left = left; - g_object_ref(G_OBJECT(op->left)); - - op->right = right; - g_object_ref(G_OBJECT(op->right)); - - result = true; - - exit: - - return result; + set->items[set->count - 1] = item; + g_object_ref(G_OBJECT(item)); } @@ -249,45 +228,69 @@ bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOpe /****************************************************************************** * * -* Paramètres : item = premier objet à consulter pour une comparaison. * -* other = second objet à consulter pour une comparaison. * -* op = opération de comparaison à réaliser. * -* status = bilan des opérations de comparaison. [OUT] * +* 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éalise une comparaison entre objets selon un critère précis.* +* Description : Réduit une expression à une forme plus simple. * * * -* Retour : true si la comparaison a pu être effectuée, false sinon. * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * * Remarques : - * * * ******************************************************************************/ -static bool g_arithmetic_operation_compare_rich(const GArithmOperation *item, const GArithmOperation *other, RichCmpOperation op, bool *status) +static ScanReductionState g_scan_generic_set_reduce(GScanGenericSet *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - bool result; /* Etat à retourner */ + ScanReductionState result; /* Etat synthétisé à retourner */ + size_t i; /* Boucle de parcours #1 */ + GScanExpression *item; /* Elément en cours d'analyse */ + GScanExpression *new; /* Nouvelle réduction obtenue */ + ScanReductionState state; /* Etat synthétisé d'un élément*/ + size_t k; /* Boucle de parcours #2 */ - result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_ARITHMETIC_OPERATION); - if (!result) goto done; + result = SRS_REDUCED; - if (item->operator != other->operator) + for (i = 0; i < expr->count; i++) { - result = compare_rich_integer_values(item->operator, other->operator, op); - goto done; - } + item = expr->items[i]; - 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; + state = g_scan_expression_reduce(item, ctx, scope, &new); + if (state == SRS_UNRESOLVABLE) + { + result = SRS_UNRESOLVABLE; + g_clear_object(out); + break; + } + + if (state == SRS_WAIT_FOR_SCAN) + result = SRS_WAIT_FOR_SCAN; - 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; + if (new != item) + { + if (*out == NULL) + { + *out = g_scan_generic_set_new(); + + for (k = 0; k < i; k++) + g_scan_generic_set_add_item(G_SCAN_GENERIC_SET(*out), expr->items[k]); - result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->right), - G_COMPARABLE_ITEM(other->right), - op, status); + } - done: + g_scan_generic_set_add_item(G_SCAN_GENERIC_SET(*out), new); + + } + + else + { + if (*out != NULL) + g_scan_generic_set_add_item(G_SCAN_GENERIC_SET(*out), item); + } + + g_object_unref(G_OBJECT(new)); + + } return result; @@ -296,29 +299,28 @@ static bool g_arithmetic_operation_compare_rich(const GArithmOperation *item, co /****************************************************************************** * * -* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] * -* src = expression source à copier. * +* 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 : Reproduit une expression en place dans une nouvelle instance.* +* Description : Réduit une expression à une forme booléenne. * * * -* Retour : - * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * * Remarques : - * * * ******************************************************************************/ -static void g_arithmetic_operation_copy(GArithmOperation *dest, const GArithmOperation *src) +static bool g_scan_generic_set_reduce_to_boolean(GScanGenericSet *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - GScanExpressionClass *class; /* Classe parente à solliciter */ - - class = G_SCAN_EXPRESSION_CLASS(g_arithmetic_operation_parent_class); + bool result; /* Bilan à retourner */ - class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src)); + result = true; - dest->operator = src->operator; + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->count > 0 }); - dest->left = g_scan_expression_duplicate(src->left); - dest->right = g_scan_expression_duplicate(src->right); + return result; } @@ -326,11 +328,9 @@ static void g_arithmetic_operation_copy(GArithmOperation *dest, const GArithmOpe /****************************************************************************** * * * 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] * +* count = quantité d'éléments déterminée. [OUT] * * * -* Description : Réduit une expression à une forme plus simple. * +* Description : Dénombre les éléments portés par une expression. * * * * Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * @@ -338,98 +338,41 @@ static void g_arithmetic_operation_copy(GArithmOperation *dest, const GArithmOpe * * ******************************************************************************/ -static bool g_arithmetic_operation_reduce(GArithmOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +static bool g_scan_generic_set_count_items(const GScanGenericSet *expr, size_t *count) { 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; /* Seconde valeur à traiter */ - unsigned long long reduced; /* Valeur réduite finale */ - - /* Réduction des éléments considérés */ - - new_left = NULL; - new_right = NULL; - - 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 (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); - - result = g_literal_expression_get_integer_value(op_left, &val_1); - if (!result) goto exit; - - result = g_literal_expression_get_integer_value(op_right, &val_2); - if (!result) goto exit; - - 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; - - } - if (result) - *out = g_literal_expression_new(EVT_INTEGER, &reduced); + result = true; - } + *count = expr->count; - /* Mise à jour de la progression ? */ + return result; - 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); +/****************************************************************************** +* * +* Paramètres : expr = expression à consulter. * +* index = indice de l'élément à transférer. * +* 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_generic_set_get_item(const GScanGenericSet *expr, size_t index, GScanExpression **out) +{ + bool result; /* Bilan à retourner */ - exit: + result = (index < expr->count); - g_clear_object(&new_left); - g_clear_object(&new_right); + if (result) + *out = expr->items[index]; return result; diff --git a/src/analysis/scan/exprs/set.h b/src/analysis/scan/exprs/set.h new file mode 100644 index 0000000..f857ce9 --- /dev/null +++ b/src/analysis/scan/exprs/set.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * set.h - prototypes pour la base d'ensembles de valeurs diverses, de types hétérogènes ou homogènes + * + * 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_SET_H +#define _ANALYSIS_SCAN_EXPRS_SET_H + + +#include "../expr.h" + + + +#define G_TYPE_SCAN_GENERIC_SET g_scan_generic_set_get_type() +#define G_SCAN_GENERIC_SET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_GENERIC_SET, GScanGenericSet)) +#define G_IS_SCAN_GENERIC_SET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_GENERIC_SET)) +#define G_SCAN_GENERIC_SET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_GENERIC_SET, GScanGenericSetClass)) +#define G_IS_SCAN_GENERIC_SET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_GENERIC_SET)) +#define G_SCAN_GENERIC_SET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_GENERIC_SET, GScanGenericSetClass)) + + +/* Base d'un ensemble d'éléments homogènes ou hétérogènes (instance) */ +typedef struct _GScanGenericSet GScanGenericSet; + +/* Base d'un ensemble d'éléments homogènes ou hétérogènes (classe) */ +typedef struct _GScanGenericSetClass GScanGenericSetClass; + + +/* Indique le type défini pour une base d'ensembles d'éléments homogènes ou hétérogènes. */ +GType g_scan_generic_set_get_type(void); + +/* Met en place un ensemble d'éléments homogènes ou hétérogènes. */ +GScanExpression *g_scan_generic_set_new(void); + +/* Ajoute un nouvel élément à un ensemble. */ +void g_scan_generic_set_add_item(GScanGenericSet *, GScanExpression *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_SET_H */ diff --git a/src/analysis/scan/exprs/strop-int.h b/src/analysis/scan/exprs/strop-int.h index 234ae8f..c2b40cf 100644 --- a/src/analysis/scan/exprs/strop-int.h +++ b/src/analysis/scan/exprs/strop-int.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * strop-int.h - prototypes internes pour la gestion des opérations booléennes * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -34,7 +34,7 @@ /* Opération booléenne avec un ou deux opérandes (instance) */ -struct _GStringOperation +struct _GScanStringOperation { GScanExpression parent; /* A laisser en premier */ @@ -47,7 +47,7 @@ struct _GStringOperation }; /* Opération booléenne avec un ou deux opérandes (classe) */ -struct _GStringOperationClass +struct _GScanStringOperationClass { GScanExpressionClass parent; /* A laisser en premier */ @@ -55,7 +55,7 @@ struct _GStringOperationClass /* Met en place une expression d'opération traite une chaîne. */ -bool g_string_operation_create(GStringOperation *, StringOperationType, GScanExpression *, GScanExpression *, bool); +bool g_scan_string_operation_create(GScanStringOperation *, StringOperationType, GScanExpression *, GScanExpression *, bool); diff --git a/src/analysis/scan/exprs/strop.c b/src/analysis/scan/exprs/strop.c index 145e8da..c7c2878 100644 --- a/src/analysis/scan/exprs/strop.c +++ b/src/analysis/scan/exprs/strop.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * strop.c - gestion des opérations booléennes * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -38,27 +38,24 @@ /* Initialise la classe des opérations visant des chaînes. */ -static void g_string_operation_class_init(GStringOperationClass *); +static void g_scan_string_operation_class_init(GScanStringOperationClass *); /* Initialise une instance d'opération visant une chaîne. */ -static void g_string_operation_init(GStringOperation *); +static void g_scan_string_operation_init(GScanStringOperation *); /* Supprime toutes les références externes. */ -static void g_string_operation_dispose(GStringOperation *); +static void g_scan_string_operation_dispose(GScanStringOperation *); /* Procède à la libération totale de la mémoire. */ -static void g_string_operation_finalize(GStringOperation *); +static void g_scan_string_operation_finalize(GScanStringOperation *); /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ -/* Reproduit une expression en place dans une nouvelle instance. */ -static void g_string_operation_copy(GStringOperation *, const GStringOperation *); - /* Réduit une expression à une forme plus simple. */ -static bool g_string_operation_reduce(GStringOperation *, GScanContext *, GScanScope *, GScanExpression **); +static ScanReductionState g_scan_string_operation_reduce(GScanStringOperation *, GScanContext *, GScanScope *, GScanExpression **); @@ -68,7 +65,7 @@ static bool g_string_operation_reduce(GStringOperation *, GScanContext *, GScanS /* Indique le type défini pour une opération traitant une chaîne de caractères. */ -G_DEFINE_TYPE(GStringOperation, g_string_operation, G_TYPE_SCAN_EXPRESSION); +G_DEFINE_TYPE(GScanStringOperation, g_scan_string_operation, G_TYPE_SCAN_EXPRESSION); /****************************************************************************** @@ -83,21 +80,20 @@ G_DEFINE_TYPE(GStringOperation, g_string_operation, G_TYPE_SCAN_EXPRESSION); * * ******************************************************************************/ -static void g_string_operation_class_init(GStringOperationClass *klass) +static void g_scan_string_operation_class_init(GScanStringOperationClass *klass) { GObjectClass *object; /* Autre version de la classe */ GScanExpressionClass *expr; /* Version de classe parente */ object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_string_operation_dispose; - object->finalize = (GObjectFinalizeFunc)g_string_operation_finalize; + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_string_operation_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_string_operation_finalize; expr = G_SCAN_EXPRESSION_CLASS(klass); expr->cmp_rich = (compare_expr_rich_fc)NULL; - expr->copy = (copy_expr_fc)g_string_operation_copy; - expr->reduce = (reduce_expr_fc)g_string_operation_reduce; + expr->reduce = (reduce_expr_fc)g_scan_string_operation_reduce; } @@ -114,7 +110,7 @@ static void g_string_operation_class_init(GStringOperationClass *klass) * * ******************************************************************************/ -static void g_string_operation_init(GStringOperation *op) +static void g_scan_string_operation_init(GScanStringOperation *op) { op->left = NULL; op->right = NULL; @@ -134,12 +130,12 @@ static void g_string_operation_init(GStringOperation *op) * * ******************************************************************************/ -static void g_string_operation_dispose(GStringOperation *op) +static void g_scan_string_operation_dispose(GScanStringOperation *op) { g_clear_object(&op->left); g_clear_object(&op->right); - G_OBJECT_CLASS(g_string_operation_parent_class)->dispose(G_OBJECT(op)); + G_OBJECT_CLASS(g_scan_string_operation_parent_class)->dispose(G_OBJECT(op)); } @@ -156,9 +152,9 @@ static void g_string_operation_dispose(GStringOperation *op) * * ******************************************************************************/ -static void g_string_operation_finalize(GStringOperation *op) +static void g_scan_string_operation_finalize(GScanStringOperation *op) { - G_OBJECT_CLASS(g_string_operation_parent_class)->finalize(G_OBJECT(op)); + G_OBJECT_CLASS(g_scan_string_operation_parent_class)->finalize(G_OBJECT(op)); } @@ -178,13 +174,13 @@ static void g_string_operation_finalize(GStringOperation *op) * * ******************************************************************************/ -GScanExpression *g_string_operation_new(StringOperationType type, GScanExpression *first, GScanExpression *second, bool sensitive) +GScanExpression *g_scan_string_operation_new(StringOperationType type, GScanExpression *first, GScanExpression *second, bool sensitive) { GScanExpression *result; /* Structure à retourner */ - result = g_object_new(G_TYPE_STRING_OPERATION, NULL); + result = g_object_new(G_TYPE_SCAN_STRING_OPERATION, NULL); - if (!g_string_operation_create(G_STRING_OPERATION(result), type, first, second, sensitive)) + if (!g_scan_string_operation_create(G_SCAN_STRING_OPERATION(result), type, first, second, sensitive)) g_clear_object(&result); return result; @@ -198,7 +194,7 @@ GScanExpression *g_string_operation_new(StringOperationType type, GScanExpressio * type = type d'opération booléenne à représenter. * * left = premier opérande concerné. * * right = éventuel second opérande impliqué ou NULL. * -* sensitive = détermine la prise en compte de la casse. * +* sensitive = détermine la prise en compte de la casse. * * * * Description : Met en place une expression d'opération traite une chaîne. * * * @@ -208,22 +204,11 @@ GScanExpression *g_string_operation_new(StringOperationType type, GScanExpressio * * ******************************************************************************/ -bool g_string_operation_create(GStringOperation *op, StringOperationType type, GScanExpression *left, GScanExpression *right, bool sensitive) +bool g_scan_string_operation_create(GScanStringOperation *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(left); - - if (vtype != EVT_STRING && vtype != EVT_PENDING) - goto exit; - - vtype = g_scan_expression_get_value_type(right); - if (vtype != EVT_STRING && vtype != EVT_REG_EXPR && vtype != EVT_PENDING) - goto exit; + result = true; op->type = type; @@ -251,10 +236,6 @@ bool g_string_operation_create(GStringOperation *op, StringOperationType type, G op->right = right; g_object_ref(G_OBJECT(op->right)); - result = true; - - exit: - return result; } @@ -268,36 +249,6 @@ bool g_string_operation_create(GStringOperation *op, StringOperationType type, G /****************************************************************************** * * -* 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_string_operation_copy(GStringOperation *dest, const GStringOperation *src) -{ - GScanExpressionClass *class; /* Classe parente à solliciter */ - - class = G_SCAN_EXPRESSION_CLASS(g_string_operation_parent_class); - - 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 : expr = expression à consulter. * * ctx = contexte de suivi de l'analyse courante. * * scope = portée courante des variables locales. * @@ -311,47 +262,65 @@ static void g_string_operation_copy(GStringOperation *dest, const GStringOperati * * ******************************************************************************/ -static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +static ScanReductionState g_scan_string_operation_reduce(GScanStringOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - bool result; /* Bilan à retourner */ + ScanReductionState result; /* Etat synthétisé à 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 */ + ScanReductionState state_left; /* Etat synthétisé #1 */ + ScanReductionState state_right; /* Etat synthétisé #2 */ + GScanLiteralExpression *op_left; /* Opérande gauche final */ + GScanLiteralExpression *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 */ + int ret; /* Bilan de comparaison #2 */ size_t offset; /* Point de départ d'analyse */ const regex_t *preg; /* Expression rationnelle */ - int ret; /* Bilan de comparaison #2 */ /* Réduction des éléments considérés */ new_left = NULL; new_right = NULL; - result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left); - if (!result) goto exit; + state_left = g_scan_expression_reduce(expr->left, ctx, scope, &new_left); + if (state_left == SRS_UNRESOLVABLE) + { + result = SRS_UNRESOLVABLE; + goto exit; + } - result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right); - if (!result) goto exit; + state_right = g_scan_expression_reduce(expr->right, ctx, scope, &new_right); + if (state_right == SRS_UNRESOLVABLE) + { + result = SRS_UNRESOLVABLE; + goto exit; + } /* Construction d'une réduction locale ? */ - if (G_IS_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right)) + if (G_IS_SCAN_LITERAL_EXPRESSION(new_left) && G_IS_SCAN_LITERAL_EXPRESSION(new_right)) { - op_left = G_LITERAL_EXPRESSION(new_left); - op_right = G_LITERAL_EXPRESSION(new_right); + op_left = G_SCAN_LITERAL_EXPRESSION(new_left); + op_right = G_SCAN_LITERAL_EXPRESSION(new_right); + + if (!g_scan_literal_expression_get_string_value(op_left, &strings[0])) + { + result = SRS_UNRESOLVABLE; + goto exit; + } - result = g_literal_expression_get_string_value(op_left, &strings[0]); - if (!result) goto exit; + result = SRS_REDUCED; switch (expr->type) { case SOT_CONTAINS: - result = g_literal_expression_get_string_value(op_right, &strings[1]); - if (!result) goto exit; + if (!g_scan_literal_expression_get_string_value(op_right, &strings[1])) + { + result = SRS_UNRESOLVABLE; + goto exit; + } if (expr->case_sensitive) found = memmem(strings[0]->data, strings[0]->len, strings[1]->data, strings[1]->len); @@ -359,13 +328,16 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx, 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 }); + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { found != NULL }); break; case SOT_STARTSWITH: - result = g_literal_expression_get_string_value(op_right, &strings[1]); - if (!result) goto exit; + if (!g_scan_literal_expression_get_string_value(op_right, &strings[1])) + { + result = SRS_UNRESOLVABLE; + goto exit; + } if (strings[0]->len < strings[1]->len) status = false; @@ -381,13 +353,16 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx, } - result = g_literal_expression_new(EVT_BOOLEAN, &status); + *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status); break; case SOT_ENDSWITH: - result = g_literal_expression_get_string_value(op_right, &strings[1]); - if (!result) goto exit; + if (!g_scan_literal_expression_get_string_value(op_right, &strings[1])) + { + result = SRS_UNRESOLVABLE; + goto exit; + } if (strings[0]->len < strings[1]->len) status = false; @@ -405,23 +380,29 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx, } - result = g_literal_expression_new(EVT_BOOLEAN, &status); + *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status); break; case SOT_MATCHES: - result = g_literal_expression_get_regex_value(op_right, &preg); - if (!result) goto exit; + if (!g_scan_literal_expression_get_regex_value(op_right, &preg)) + { + result = SRS_UNRESOLVABLE; + goto exit; + } ret = regexec(preg, strings[0]->data, 0, NULL, 0); - *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret != REG_NOMATCH }); + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { ret != REG_NOMATCH }); break; case SOT_IEQUALS: - result = g_literal_expression_get_string_value(op_right, &strings[1]); - if (!result) goto exit; + if (!g_scan_literal_expression_get_string_value(op_right, &strings[1])) + { + result = SRS_UNRESOLVABLE; + goto exit; + } if (strings[0]->len != strings[1]->len) status = false; @@ -432,7 +413,7 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx, status = (ret == 0); } - result = g_literal_expression_new(EVT_BOOLEAN, &status); + *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status); break; } @@ -441,24 +422,26 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx, /* Mise à jour de la progression ? */ - else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right)) + else if (state_left == SRS_WAIT_FOR_SCAN || state_right == SRS_WAIT_FOR_SCAN) { - if (new_left == NULL) - { - new_left = expr->left; - g_object_ref(G_OBJECT(new_left)); - } + if (new_left != expr->left || new_right != expr->right) + *out = g_scan_string_operation_new(expr->type, new_left, new_right, expr->case_sensitive); - if (new_right == NULL) - { - new_right = expr->right; - g_object_ref(G_OBJECT(new_right)); - } + result = SRS_WAIT_FOR_SCAN; - *out = g_string_operation_new(expr->type, new_left, new_right, expr->case_sensitive); + } + + /* Cas des situations où les expressions ne sont pas exploitables (!) */ + else + { + assert(state_left == SRS_REDUCED && state_right == SRS_REDUCED); + + result = SRS_UNRESOLVABLE; } + /* Sortie propre */ + exit: g_clear_object(&new_left); diff --git a/src/analysis/scan/exprs/strop.h b/src/analysis/scan/exprs/strop.h index c7c0813..0a32269 100644 --- a/src/analysis/scan/exprs/strop.h +++ b/src/analysis/scan/exprs/strop.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * strop.h - prototypes pour la gestion des opérations booléennes * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -29,19 +29,19 @@ -#define G_TYPE_STRING_OPERATION g_string_operation_get_type() -#define G_STRING_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_STRING_OPERATION, GStringOperation)) -#define G_IS_STRING_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_STRING_OPERATION)) -#define G_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_STRING_OPERATION, GStringOperationClass)) -#define G_IS_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_STRING_OPERATION)) -#define G_STRING_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_STRING_OPERATION, GStringOperationClass)) +#define G_TYPE_SCAN_STRING_OPERATION g_scan_string_operation_get_type() +#define G_SCAN_STRING_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_STRING_OPERATION, GScanStringOperation)) +#define G_IS_SCAN_STRING_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_STRING_OPERATION)) +#define G_SCAN_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_STRING_OPERATION, GScanStringOperationClass)) +#define G_IS_SCAN_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_STRING_OPERATION)) +#define G_SCAN_STRING_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_STRING_OPERATION, GScanStringOperationClass)) /* Opération booléenne avec un ou deux opérandes (instance) */ -typedef struct _GStringOperation GStringOperation; +typedef struct _GScanStringOperation GScanStringOperation; /* Opération booléenne avec un ou deux opérandes (classe) */ -typedef struct _GStringOperationClass GStringOperationClass; +typedef struct _GScanStringOperationClass GScanStringOperationClass; /* Types d'opérations booléennes supportées */ @@ -57,10 +57,10 @@ typedef enum _StringOperationType /* Indique le type défini pour une opération traitant une chaîne de caractères. */ -GType g_string_operation_get_type(void); +GType g_scan_string_operation_get_type(void); /* Organise un appel de fonction avec ses arguments. */ -GScanExpression *g_string_operation_new(StringOperationType, GScanExpression *, GScanExpression *, bool); +GScanExpression *g_scan_string_operation_new(StringOperationType, GScanExpression *, GScanExpression *, bool); |