diff options
Diffstat (limited to 'src/analysis')
75 files changed, 7299 insertions, 1380 deletions
diff --git a/src/analysis/scan/context-int.h b/src/analysis/scan/context-int.h index 94302bf..3a971b8 100644 --- a/src/analysis/scan/context-int.h +++ b/src/analysis/scan/context-int.h @@ -29,9 +29,12 @@  #include "expr.h" +#include "../../common/fnv1a.h" +#define ALLOCATION_STEP 10 +  /* Mémorisation des correspondances partielles */  typedef struct _atom_match_tracker_t  { @@ -41,12 +44,22 @@ typedef struct _atom_match_tracker_t  } atom_match_tracker_t; -#define ALLOCATION_STEP 10 +/* Mémorisation des correspondances complètes, par motif */ +typedef struct _full_match_tracker_t +{ +    GSearchPattern *pattern;                /* Motif commun aux trouvailles*/ + +    GScanMatch **matches;                   /* Correspondances confirmées  */ +    size_t allocated;                       /* Taille du talbeau préparé   */ +    size_t used;                            /* Nombre d'éléments présents  */ + +} full_match_tracker_t;  /* Condition définissant une règle de correspondance */  typedef struct _rule_condition_t  {      char *name;                             /* Désignation de la règle     */ +    fnv64_t name_hash;                      /* Empreinte de la désignation */      GScanExpression *expr;                  /* Condition de correspondance */      bool final_reduced;                     /* Réduction finale tentée ?   */ @@ -66,9 +79,8 @@ struct _GScanContext      atom_match_tracker_t *atom_trackers;    /* Correspondances partielles  */ -    GScanMatch **full_matches;              /* Correspondances confirmées  */ -    size_t full_allocated;                  /* Taille du talbeau préparé   */ -    size_t full_used;                       /* Nombre d'éléments présents  */ +    full_match_tracker_t **full_trackers;   /* Correspondances confirmées  */ +    size_t full_count;                      /* Quantité de correspondances */      rule_condition_t *conditions;           /* Ensemble de règles suivies  */      size_t cond_count;                      /* Quantité de ces conditions  */ diff --git a/src/analysis/scan/context.c b/src/analysis/scan/context.c index c19b76c..1f9c38e 100644 --- a/src/analysis/scan/context.c +++ b/src/analysis/scan/context.c @@ -25,11 +25,36 @@  #include <assert.h> +#include <malloc.h> +#include <stdlib.h>  #include <string.h>  #include "context-int.h"  #include "exprs/literal.h" +#include "../../common/sort.h" + + + + + +/* ------------------- ADMINISTRATION DES CORRESPONDANCES TOTALES ------------------- */ + + +/* Initialise un suivi de trouvailles pour un premier motif. */ +static full_match_tracker_t *create_full_match_tracker(GSearchPattern *); + +/* Termine le suivi de trouvailles pour un motif. */ +static void delete_full_match_tracker(full_match_tracker_t *); + +/* Etablit la comparaison entre deux structures de suivi. */ +static int compare_full_match_trackers(const full_match_tracker_t **, const full_match_tracker_t **); + +/* Note l'existence d'une nouvelle correspondance pour un motif. */ +static void add_match_to_full_match_tracker(full_match_tracker_t *, GScanMatch *); + + + @@ -47,6 +72,131 @@ static void g_scan_context_finalize(GScanContext *); + + + + +/* ---------------------------------------------------------------------------------- */ +/*                     ADMINISTRATION DES CORRESPONDANCES TOTALES                     */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : pattern = motif de recherche trouvé.                         * +*                                                                             * +*  Description : Initialise un suivi de trouvailles pour un premier motif.    * +*                                                                             * +*  Retour      : Structure de suivi mise en place.                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static full_match_tracker_t *create_full_match_tracker(GSearchPattern *pattern) +{ +    full_match_tracker_t *result;           /* Structure à retourner       */ + +    result = malloc(sizeof(full_match_tracker_t)); + +    result->pattern = pattern; +    g_object_ref(G_OBJECT(pattern)); + +    result->matches = malloc(ALLOCATION_STEP * sizeof(GScanMatch *)); +    result->allocated = ALLOCATION_STEP; +    result->used = 0; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : tracker = structure de gestion à manipuler.                  * +*                                                                             * +*  Description : Termine le suivi de trouvailles pour un motif.               * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void delete_full_match_tracker(full_match_tracker_t *tracker) +{ +    size_t i;                               /* Boucle de parcours          */ + +    g_object_unref(G_OBJECT(tracker->pattern)); + +    for (i = 0; i < tracker->used; i++) +        g_object_unref(G_OBJECT(tracker->matches[i])); + +    free(tracker->matches); + +    free(tracker); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : a = première structure de suivi à consulter.                 * +*                b = seconde structure de suivi à consulter.                  * +*                                                                             * +*  Description : Etablit la comparaison entre deux structures de suivi.       * +*                                                                             * +*  Retour      : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b).                 * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int compare_full_match_trackers(const full_match_tracker_t **a, const full_match_tracker_t **b) +{ +    int result;                             /* Bilan à renvoyer            */ + +    result = sort_unsigned_long((unsigned long)(*a)->pattern, (unsigned long)(*b)->pattern); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : tracker = structure de gestion à manipuler.                  * +*                match   = correspondance complète établie.                   * +*                                                                             * +*  Description : Note l'existence d'une nouvelle correspondance pour un motif.* +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void add_match_to_full_match_tracker(full_match_tracker_t *tracker, GScanMatch *match) +{ +    if (tracker->used == tracker->allocated) +    { +        tracker->allocated += ALLOCATION_STEP; +        tracker->matches = realloc(tracker->matches, tracker->allocated * sizeof(GScanMatch *)); +    } + +    tracker->matches[tracker->used++] = match; +    g_object_ref(G_OBJECT(match)); + +} + + + + + + + + +  /* Indique le type défini pour un contexte de suivi d'analyse. */  G_DEFINE_TYPE(GScanContext, g_scan_context, G_TYPE_OBJECT); @@ -97,9 +247,8 @@ static void g_scan_context_init(GScanContext *context)      context->atom_trackers = NULL; -    context->full_matches = NULL; -    context->full_allocated = 0; -    context->full_used = 0; +    context->full_trackers = NULL; +    context->full_count = 0;      context->conditions = NULL;      context->cond_count = 0; @@ -127,8 +276,12 @@ static void g_scan_context_dispose(GScanContext *context)      g_clear_object(&context->content); -    for (i = 0; i < context->full_used; i++) -        g_clear_object(&context->full_matches[i]); +    for (i = 0; i < context->full_count; i++) +        if (context->full_trackers[i] != NULL) +        { +            delete_full_match_tracker(context->full_trackers[i]); +            context->full_trackers[i] = NULL; +        }      for (i = 0; i < context->cond_count; i++)          g_clear_object(&context->conditions[i].expr); @@ -170,8 +323,8 @@ static void g_scan_context_finalize(GScanContext *context)      } -    if (context->full_matches != NULL) -        free(context->full_matches); +    if (context->full_trackers != NULL) +        free(context->full_trackers);      if (context->conditions != NULL)      { @@ -387,14 +540,75 @@ const phys_t *g_scan_context_get_atom_matches(const GScanContext *context, patid  void g_scan_context_register_full_match(GScanContext *context, GScanMatch *match)  { -    if (context->full_used == context->full_allocated) +    GSearchPattern *pattern;                /* Clef d'un suivi             */ +    full_match_tracker_t key;               /* Modèle d'identification     */ +    full_match_tracker_t **found;           /* Structure à actualiser      */ +    full_match_tracker_t *tracker;          /* Nouveau suivi à intégrer    */ + +    pattern = g_scan_match_get_source(match); + +    key.pattern = pattern; + +    found = bsearch((full_match_tracker_t *[]) { &key }, context->full_trackers, context->full_count, +                    sizeof(full_match_tracker_t *), (__compar_fn_t)compare_full_match_trackers); + +    if (found == NULL)      { -        context->full_allocated += ALLOCATION_STEP; -        context->full_matches = realloc(context->full_matches, context->full_allocated * sizeof(GScanMatch *)); +        tracker = create_full_match_tracker(pattern); + +        context->full_trackers = qinsert(context->full_trackers, &context->full_count, +                                         sizeof(full_match_tracker_t *), +                                         (__compar_fn_t)compare_full_match_trackers, &tracker); +      } +    else +        tracker = *found; -    context->full_matches[context->full_used++] = match; -    g_object_ref(G_OBJECT(match)); +    add_match_to_full_match_tracker(tracker, match); + +    g_object_unref(G_OBJECT(pattern)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = instance à mettre à jour.                          * +*                pattern = motif dont des correspondances sont à retrouver.   * +*                count   = quantité de correspondances enregistrées. [OUT]    * +*                                                                             * +*  Description : Fournit la liste de toutes les correspondances d'un motif.   * +*                                                                             * +*  Retour      : Liste courante de correspondances établies.                  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +const GScanMatch **g_scan_context_get_full_matches(const GScanContext *context, const GSearchPattern *pattern, size_t *count) +{ +    GScanMatch **result;                    /* Correspondance à renvoyer   */ +    full_match_tracker_t key;               /* Modèle d'identification     */ +    full_match_tracker_t **found;           /* Structure à actualiser      */ + +    key.pattern = pattern; + +    found = bsearch((full_match_tracker_t *[]) { &key }, context->full_trackers, context->full_count, +                    sizeof(full_match_tracker_t *), (__compar_fn_t)compare_full_match_trackers); + +    if (found == NULL) +    { +        result = NULL; +        count = 0; +    } + +    else +    { +        result = (*found)->matches; +        *count = (*found)->used; +    } + +    return result;  } @@ -411,12 +625,25 @@ void g_scan_context_register_full_match(GScanContext *context, GScanMatch *match  *                                                                             *  ******************************************************************************/ -void g_scan_context_display(const GScanContext *context) +void g_scan_context_display(GScanContext *context)  {      size_t i;                               /* Boucle de parcours          */ +    const rule_condition_t *cond;           /* Conditions de orrespondance */ +    /* +      FIXME : ordre      for (i = 0; i < context->full_used; i++)          g_scan_match_display(context->full_matches[i]); +    */ + +    for (i = 0; i < context->cond_count; i++) +    { +        cond = &context->conditions[i]; + +        if (g_scan_context_has_match_for_rule(context, cond->name)) +            fprintf(stderr, "Rule '%s' has matched!\n", cond->name); + +    }  } @@ -445,7 +672,7 @@ bool g_scan_context_set_rule_condition(GScanContext *context, const char *name,      /* Recherche d'antécédent */ -    for (i = 0; context->cond_count; i++) +    for (i = 0; i < context->cond_count; i++)          if (strcmp(name, context->conditions[i].name) == 0)          {              result = false; @@ -461,8 +688,10 @@ bool g_scan_context_set_rule_condition(GScanContext *context, const char *name,          new = &context->conditions[context->cond_count - 1];          new->name = strdup(name); +        new->name_hash = fnv_64a_hash(name); -        new->expr = g_scan_expression_duplicate(expr); +        new->expr = expr;//g_scan_expression_duplicate(expr); +        g_object_ref(G_OBJECT(expr)); // FIXME => REMME dup()          new->final_reduced = false;      } @@ -477,6 +706,50 @@ bool g_scan_context_set_rule_condition(GScanContext *context, const char *name,  *  Paramètres  : context = mémoire de résultats d'analyse à consulter.        *  *                name    = désignation de la règle ciblée.                    *  *                                                                             * +*  Description : Indique si un nom donné correspond à une règle.              * +*                                                                             * +*  Retour      : Bilan de la présence d'une règle désignée.                   * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_scan_context_has_rule_for_name(const GScanContext *context, const char *name) +{ +    bool result;                            /* Bilan à retourner           */ +    fnv64_t hash;                           /* Empreinte du nom à retrouver*/ +    size_t i;                               /* Boucle de parcours          */ +    const rule_condition_t *cond;           /* Condition connue du contexte*/ + +    result = false; + +    hash = fnv_64a_hash(name); + +    for (i = 0; i < context->cond_count; i++) +    { +        cond = context->conditions + i; + +        if (cond->name_hash != hash) +            continue; + +        if (strcmp(cond->name, name) == 0) +        { +            result = true; +            break; +        } + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = mémoire de résultats d'analyse à consulter.        * +*                name    = désignation de la règle ciblée.                    * +*                                                                             *  *  Description : Indique si une correspondance globale a pu être établie.     *  *                                                                             *  *  Retour      : Bilan final d'une analyse (false par défaut).                * @@ -513,21 +786,27 @@ bool g_scan_context_has_match_for_rule(GScanContext *context, const char *name)      if (!cond->final_reduced)      { -        cond->final_reduced = g_scan_expression_reduce(cond->expr, context, NULL, &new); +        valid = g_scan_expression_reduce(cond->expr, context, NULL, &new); +        if (!valid || new == NULL) goto exit; -        if (cond->final_reduced && new != NULL) -        { -            g_object_unref(G_OBJECT(cond->expr)); -            cond->expr = new; -        } +        g_object_unref(G_OBJECT(cond->expr)); +        cond->expr = new; + +        valid = g_scan_expression_reduce_to_boolean(cond->expr, context, NULL, &new); +        if (!valid || new == NULL) goto exit; + +        g_object_unref(G_OBJECT(cond->expr)); +        cond->expr = new; + +        cond->final_reduced = true;      }      /* Tentative de récupération d'un bilan final */ -    if (G_IS_LITERAL_EXPRESSION(cond->expr)) +    if (cond->final_reduced)      { -        valid = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(cond->expr), &result); +        valid = g_scan_literal_expression_get_boolean_value(G_SCAN_LITERAL_EXPRESSION(cond->expr), &result);          if (!valid)          { diff --git a/src/analysis/scan/context.h b/src/analysis/scan/context.h index 92522f8..563a53e 100644 --- a/src/analysis/scan/context.h +++ b/src/analysis/scan/context.h @@ -86,12 +86,18 @@ const phys_t *g_scan_context_get_atom_matches(const GScanContext *, patid_t, siz  /* Enregistre une correspondance complète avec un contenu. */  void g_scan_context_register_full_match(GScanContext *, GScanMatch *); +/* Fournit la liste de toutes les correspondances d'un motif. */ +const GScanMatch **g_scan_context_get_full_matches(const GScanContext *, const GSearchPattern *, size_t *); +  /* Affiche les correspondances identifiées. */ -void g_scan_context_display(const GScanContext *); +void g_scan_context_display(GScanContext *);  /* Intègre une condition de correspondance pour règle. */  bool g_scan_context_set_rule_condition(GScanContext *, const char *, const GScanExpression *); +/* Indique si un nom donné correspond à une règle. */ +bool g_scan_context_has_rule_for_name(const GScanContext *, const char *); +  /* Indique si une correspondance globale a pu être établie. */  bool g_scan_context_has_match_for_rule(GScanContext *, const char *); diff --git a/src/analysis/scan/core.c b/src/analysis/scan/core.c index aef9abd..d940ab5 100644 --- a/src/analysis/scan/core.c +++ b/src/analysis/scan/core.c @@ -24,8 +24,20 @@  #include "core.h" +#include <config.h> + + +#include "items/count.h"  #include "items/datasize.h"  #include "items/uint.h" +#include "items/console/log.h" +#ifdef HAVE_MAGIC_SUPPORT +#   include "items/magic/type.h" +#   include "items/magic/mime-encoding.h" +#   include "items/magic/mime-type.h" +#endif +#include "items/time/make.h" +#include "items/time/now.h" @@ -43,25 +55,83 @@  bool populate_main_scan_namespace(GScanNamespace *space)  { -    bool result; +    bool result;                            /* Bilan à retourner           */ +    GScanNamespace *ns;                     /* Nouvel espace de noms       */      result = true; -#define REGISTER_FUNC(s, f)                                                 \ -    ({                                                                      \ -        bool __result;                                                      \ -        __result = g_scan_namespace_register_item(s, G_REGISTERED_ITEM(f)); \ -        g_object_unref(G_OBJECT(f));                                        \ -        __result;                                                           \ +#define REGISTER_FUNC(s, f)                                 \ +    ({                                                      \ +        bool __result;                                      \ +        __result = g_scan_namespace_register_item(s, f);    \ +        g_object_unref(G_OBJECT(f));                        \ +        __result;                                           \      }) -    if (result) result = REGISTER_FUNC(space, g_datasize_function_new()); -    //if (result) result = REGISTER_FUNC(space, g_datasize_function_new(), "filesize"); /* Alias */ +    if (result) result = REGISTER_FUNC(space, g_scan_count_function_new()); +    if (result) result = REGISTER_FUNC(space, g_scan_datasize_function_new()); + +    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_8_BITS_SIGNED, SRE_LITTLE)); +    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_8_BITS_UNSIGNED, SRE_LITTLE)); + +    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_16_BITS_SIGNED, SRE_LITTLE)); +    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_16_BITS_SIGNED, SRE_BIG)); +    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_16_BITS_UNSIGNED, SRE_LITTLE)); +    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_16_BITS_UNSIGNED, SRE_BIG)); + +    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_32_BITS_SIGNED, SRE_LITTLE)); +    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_32_BITS_SIGNED, SRE_BIG)); +    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_32_BITS_UNSIGNED, SRE_LITTLE)); +    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_32_BITS_UNSIGNED, SRE_BIG)); + +    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_64_BITS_SIGNED, SRE_LITTLE)); +    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_64_BITS_SIGNED, SRE_BIG)); +    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_64_BITS_UNSIGNED, SRE_LITTLE)); +    if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_64_BITS_UNSIGNED, SRE_BIG)); + +    /* Console */ + +    if (result) +    { +        ns = g_scan_namespace_new("console"); +        result = g_scan_namespace_register_item(space, G_REGISTERED_ITEM(ns)); + +        if (result) result = REGISTER_FUNC(ns, g_scan_console_log_function_new()); + +        g_object_unref(G_OBJECT(ns)); + +    } + +    /* Magic */ + +#ifdef HAVE_MAGIC_SUPPORT +    if (result) +    { +        ns = g_scan_namespace_new("magic"); +        result = g_scan_namespace_register_item(space, G_REGISTERED_ITEM(ns)); + +        if (result) result = REGISTER_FUNC(ns, g_scan_magic_type_function_new()); +        if (result) result = REGISTER_FUNC(ns, g_scan_mime_encoding_function_new()); +        if (result) result = REGISTER_FUNC(ns, g_scan_mime_type_function_new()); + +        g_object_unref(G_OBJECT(ns)); + +    } +#endif + +    /* Time */ + +    if (result) +    { +        ns = g_scan_namespace_new("time"); +        result = g_scan_namespace_register_item(space, G_REGISTERED_ITEM(ns)); + +        if (result) result = REGISTER_FUNC(ns, g_scan_time_make_function_new()); +        if (result) result = REGISTER_FUNC(ns, g_scan_time_now_function_new()); + +        g_object_unref(G_OBJECT(ns)); -    if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_8_BITS_UNSIGNED)); -    if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_16_BITS_UNSIGNED)); -    if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_32_BITS_UNSIGNED)); -    if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_64_BITS_UNSIGNED)); +    }      return result; diff --git a/src/analysis/scan/expr-int.h b/src/analysis/scan/expr-int.h index dbfea6e..48668b5 100644 --- a/src/analysis/scan/expr-int.h +++ b/src/analysis/scan/expr-int.h @@ -39,16 +39,28 @@  typedef bool (* compare_expr_rich_fc) (const GScanExpression *, const GScanExpression *, RichCmpOperation, bool *);  /* Vérifie la validité d'une expression. */ -typedef bool (* check_expr_validity_fc) (const GScanExpression *); +typedef bool (* check_expr_validity_fc) (const GScanExpression *);    // REMME ?  /* Reproduit une expression en place dans une nouvelle instance. */ -typedef GScanExpression * (* dup_expr_fc) (const GScanExpression *); +typedef GScanExpression * (* dup_expr_fc) (const GScanExpression *);    // REMME ?  /* Reproduit une expression en place dans une nouvelle instance. */  typedef void (* copy_expr_fc) (GScanExpression *, const GScanExpression *);  /* Réduit une expression à une forme plus simple. */ -typedef bool (* reduce_expr_fc) (GScanExpression *, GScanContext *, GScanScope *, GScanExpression **); +typedef ScanReductionState (* reduce_expr_fc) (GScanExpression *, GScanContext *, GScanScope *, GScanExpression **); + +/* Réduit une expression à une forme booléenne. */ +typedef bool (* reduce_expr_to_bool_fc) (GScanExpression *, GScanContext *, GScanScope *, GScanExpression **); + +/* Dénombre les éléments portés par une expression. */ +typedef bool (* count_scan_expr_fc) (const GScanExpression *, size_t *); + +/* Fournit un élément donné issu d'un ensemble constitué. */ +typedef bool (* get_scan_expr_fc) (const GScanExpression *, size_t, GScanExpression **); + +/* Réalise l'intersection entre deux ensembles. */ +typedef GScanExpression * (* intersect_scan_expr_fc) (GScanExpression *, const GScanExpression *, GScanContext *, GScanScope *);  /* Expression d'évaluation généraliste (instance) */ @@ -56,6 +68,8 @@ struct _GScanExpression  {      GObject parent;                         /* A laisser en premier        */ +    ScanReductionState state;               /* Etat synthétisé de l'élément*/ +      ExprValueType value_type;               /* Type de valeur portée       */  }; @@ -67,9 +81,15 @@ struct _GScanExpressionClass      compare_expr_rich_fc cmp_rich;          /* Comparaison de façon précise*/      check_expr_validity_fc check;           /* Validation de la cohérence  */ -    copy_expr_fc copy;                      /* Reproduction d'expression   */ +    copy_expr_fc copyXXX;                      /* Reproduction d'expression   */      dup_expr_fc dup;                        /* Reproduction d'expression   */ +      reduce_expr_fc reduce;                  /* Simplification d'expression */ +    reduce_expr_to_bool_fc reduce_to_bool;  /* Conversion en booléen       */ + +    count_scan_expr_fc count;               /* Décompte d'éléments         */ +    get_scan_expr_fc get;                   /* Extraction d'un élément     */ +    intersect_scan_expr_fc intersect;       /* Intersection entre ensembles*/  }; diff --git a/src/analysis/scan/expr.c b/src/analysis/scan/expr.c index 52d2c42..808b14f 100644 --- a/src/analysis/scan/expr.c +++ b/src/analysis/scan/expr.c @@ -28,6 +28,8 @@  #include "expr-int.h" +#include "exprs/literal.h" +#include "exprs/set.h" @@ -52,6 +54,9 @@ static void g_scan_expression_finalize(GScanExpression *);  /* Reproduit une expression en place dans une nouvelle instance. */  static void g_scan_expression_copy(GScanExpression *, const GScanExpression *); +/* Réalise l'intersection entre deux ensembles. */ +static GScanExpression *_g_scan_expression_intersect(GScanExpression *, const GScanExpression *, GScanContext *, GScanScope *); +  /* ----------------------- INTERFACE OFFRANT DES COMPARAISONS ----------------------- */ @@ -93,7 +98,8 @@ static void g_scan_expression_class_init(GScanExpressionClass *klass)      object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_expression_dispose;      object->finalize = (GObjectFinalizeFunc)g_scan_expression_finalize; -    klass->copy = g_scan_expression_copy; +    //klass->copy = g_scan_expression_copy; +    klass->intersect = _g_scan_expression_intersect;  } @@ -112,6 +118,7 @@ static void g_scan_expression_class_init(GScanExpressionClass *klass)  static void g_scan_expression_init(GScanExpression *expr)  { +    expr->state = SRS_PENDING;  } @@ -292,7 +299,7 @@ GScanExpression *g_scan_expression_duplicate(const GScanExpression *expr)      class = G_SCAN_EXPRESSION_GET_CLASS(expr); -    class->copy(result, expr); +    //class->copy(result, expr);      return result; @@ -314,7 +321,200 @@ GScanExpression *g_scan_expression_duplicate(const GScanExpression *expr)  *                                                                             *  ******************************************************************************/ -bool g_scan_expression_reduce(GScanExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +ScanReductionState g_scan_expression_reduce(GScanExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +{ +    GScanExpressionClass *class;            /* Classe à activer            */ + +    if (expr->state == SRS_REDUCED) +    { +        *out = expr; +        g_object_ref(G_OBJECT(expr)); +    } + +    else +    { +        *out = NULL; + +        class = G_SCAN_EXPRESSION_GET_CLASS(expr); + +        if (class->reduce != NULL) +        { +            expr->state = class->reduce(expr, ctx, scope, out); + +            if (expr->state != SRS_UNRESOLVABLE && *out == NULL) +            { +                *out = expr; +                g_object_ref(G_OBJECT(expr)); +            } + +        } + +        else +            expr->state = SRS_UNRESOLVABLE; + +#ifndef NDEBUG +        if (*out != NULL) +            assert(expr->state != SRS_UNRESOLVABLE); +#endif + +    } + +    assert(expr->state != SRS_PENDING); + + +    return expr->state; + +} + + +/****************************************************************************** +*                                                                             * +*  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   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_scan_expression_reduce_to_boolean(GScanExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +{ +    bool result;                            /* Bilan à retourner           */ +    GScanExpression *inter;                 /* Expression intermédiaire    */ +    GScanExpressionClass *class;            /* Classe à activer            */ + +    *out = NULL; + +    result = g_scan_expression_reduce(expr, ctx, scope, &inter); +    if (!result) goto exit; + +    if (inter != NULL) +    { +        class = G_SCAN_EXPRESSION_GET_CLASS(inter); + +        if (class->reduce_to_bool != NULL) +            result = class->reduce_to_bool(inter, ctx, scope, out); +        else +            result = false; + +        g_object_unref(G_OBJECT(inter)); + +        /* Validation d'un type booléen */ +        if (result && *out != NULL) +        { +            if (!G_IS_SCAN_LITERAL_EXPRESSION(*out)) +            { +                g_clear_object(out); +                result = false; +            } + +            if (g_scan_literal_expression_get_value_type(G_SCAN_LITERAL_EXPRESSION(*out)) != LVT_BOOLEAN) +            { +                g_clear_object(out); +                result = false; +            } + +        } + +    } + + exit: + +#ifndef NDEBUG +    if (*out != NULL) +        assert(result); +#endif + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : expr = expression à consulter.                               * +*                                                                             * +*  Description : Détermine si l'expression peut représenter un ensemble.      * +*                                                                             * +*  Retour      : Bilan de la consultation.                                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_scan_expression_handle_set_features(const GScanExpression *expr) +{ +    bool result;                            /* Bilan à retourner           */ +    GScanExpressionClass *class;            /* Classe à activer            */ + +    class = G_SCAN_EXPRESSION_GET_CLASS(expr); + +    result = (class->count != NULL); + +    assert((result && (class->get != NULL)) || (!result && (class->get == NULL))); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : expr  = expression à consulter.                              * +*                count = quantité d'éléments déterminée. [OUT]                * +*                                                                             * +*  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.  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_scan_expression_count_items(const GScanExpression *expr, size_t *count) +{ +    bool result;                            /* Bilan à retourner           */ +    GScanExpressionClass *class;            /* Classe à activer            */ + +    *count = -1; + +    class = G_SCAN_EXPRESSION_GET_CLASS(expr); + +    if (class->count != NULL) +        result = class->count(expr, count); +    else +        result = false; + +#ifndef NDEBUG +    if (*count != -1) +        assert(result); +#endif + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  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   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_scan_expression_get_item(const GScanExpression *expr, size_t index, GScanExpression **out)  {      bool result;                            /* Bilan à retourner           */      GScanExpressionClass *class;            /* Classe à activer            */ @@ -323,7 +523,17 @@ bool g_scan_expression_reduce(GScanExpression *expr, GScanContext *ctx, GScanSco      class = G_SCAN_EXPRESSION_GET_CLASS(expr); -    result = class->reduce(expr, ctx, scope, out); +    if (class->get != NULL) +    { +        result = class->get(expr, index, out); + +        if (*out != NULL) +            g_object_ref(G_OBJECT(*out)); + +    } + +    else +        result = false;  #ifndef NDEBUG      if (*out != NULL) @@ -335,6 +545,133 @@ bool g_scan_expression_reduce(GScanExpression *expr, GScanContext *ctx, GScanSco  } +/****************************************************************************** +*                                                                             * +*  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_expression_intersect(GScanExpression *expr, const GScanExpression *other, GScanContext *ctx, GScanScope *scope) +{ +    GScanExpression *result;                /* Instance à retourner        */ +    size_t other_count;                     /* Taille du second ensemble   */ +    bool valid;                             /* Bilan de validité           */ +    size_t expr_count;                      /* Taille du premier ensemble  */ +    size_t k;                               /* Boucle de parcours #1       */ +    GComparableItem *comparable;            /* Premier élément à comparer  */ +    size_t i;                               /* Boucle de parcours #2       */ +    GScanExpression *item;                  /* Elément à comparer          */ +    bool status;                            /* Bilan d'une comparaison     */ + +    result = NULL; + +    valid = g_scan_expression_count_items(other, &other_count); +    if (!valid) goto done; + +    /* Intersection entre deux ensembles ? */ +    if (g_scan_expression_handle_set_features(expr)) +    { +        valid = g_scan_expression_count_items(expr, &expr_count); +        if (!valid) goto done; + +        result = g_scan_generic_set_new(); + +        for (k = 0; k < expr_count; k++) +        { +            valid = g_scan_expression_get_item(expr, k, &item); +            if (!valid) break; + +            comparable = G_COMPARABLE_ITEM(item); + +            for (i = 0; i < other_count; i++) +            { +                valid = g_scan_expression_get_item(other, i, &item); +                if (!valid) break; + +                valid = g_comparable_item_compare_rich(comparable, G_COMPARABLE_ITEM(item), RCO_EQ, &status); + +                if (valid && status) +                    g_scan_generic_set_add_item(G_SCAN_GENERIC_SET(result), item); + +                g_object_unref(G_OBJECT(item)); + +            } + +            g_object_unref(G_OBJECT(comparable)); + +        } + +    } + +    /* Intersection entre un élément et un ensemble */ +    else +    { +        comparable = G_COMPARABLE_ITEM(expr); + +        for (i = 0; i < other_count && result == NULL; i++) +        { +            valid = g_scan_expression_get_item(other, i, &item); +            if (!valid) break; + +            valid = g_comparable_item_compare_rich(comparable, G_COMPARABLE_ITEM(item), RCO_EQ, &status); + +            if (valid && status) +                result = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { true }); + +            g_object_unref(G_OBJECT(item)); + +        } + +        if (result && result == NULL) +            result = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { false }); + +    } + + done: + +    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   : -                                                            * +*                                                                             * +******************************************************************************/ + +GScanExpression *g_scan_expression_intersect(GScanExpression *expr, const GScanExpression *other, GScanContext *ctx, GScanScope *scope) +{ +    GScanExpression *result;                /* Instance à retourner        */ +    GScanExpressionClass *class;            /* Classe à activer            */ + +    class = G_SCAN_EXPRESSION_GET_CLASS(expr); + +    result = class->intersect(expr, other, ctx, scope); + +    return result; + +} + +  /* ---------------------------------------------------------------------------------- */  /*                         INTERFACE OFFRANT DES COMPARAISONS                         */ @@ -364,7 +701,14 @@ static bool g_scan_expression_compare_rich(const GScanExpression *item, const GS      class = G_SCAN_EXPRESSION_GET_CLASS(item);      if (class->cmp_rich != NULL) -        result = class->cmp_rich(item, other, op, status); +    { +        result = (G_TYPE_FROM_INSTANCE(item) == G_TYPE_FROM_INSTANCE(other));   // FIXME : subtype ? cf. literal ? + +        if (result) +            result = class->cmp_rich(item, other, op, status); + +    } +      else          result = false; diff --git a/src/analysis/scan/expr.h b/src/analysis/scan/expr.h index d596222..dd4bc3f 100644 --- a/src/analysis/scan/expr.h +++ b/src/analysis/scan/expr.h @@ -64,6 +64,16 @@ typedef enum _ExprValueType  } ExprValueType; +/* Etat de l'expression vis à vis des réductions */ +typedef enum _ScanReductionState +{ +    SRS_PENDING,                            /* Nature à déterminer         */ +    SRS_REDUCED,                            /* Nature compacte finale      */ +    SRS_WAIT_FOR_SCAN,                      /* Nature vouée à évoluer      */ +    SRS_UNRESOLVABLE,                       /* Nature indéterminable       */ + +} ScanReductionState; +  /* Indique le type défini pour une expression de validation. */  GType g_scan_expression_get_type(void); @@ -78,7 +88,22 @@ bool g_scan_expression_check_validity(const GScanExpression *);  GScanExpression *g_scan_expression_duplicate(const GScanExpression *);  /* Réduit une expression à une forme plus simple. */ -bool g_scan_expression_reduce(GScanExpression *, GScanContext *, GScanScope *, GScanExpression **); +ScanReductionState g_scan_expression_reduce(GScanExpression *, GScanContext *, GScanScope *, GScanExpression **); + +/* Réduit une expression à une forme booléenne. */ +bool g_scan_expression_reduce_to_boolean(GScanExpression *, GScanContext *, GScanScope *, GScanExpression **); + +/* Détermine si l'expression peut représenter un ensemble. */ +bool g_scan_expression_handle_set_features(const GScanExpression *); + +/* Dénombre les éléments portés par une expression. */ +bool g_scan_expression_count_items(const GScanExpression *, size_t *); + +/* Fournit un élément donné issu d'un ensemble constitué. */ +bool g_scan_expression_get_item(const GScanExpression *, size_t, GScanExpression **); + +/* Réalise l'intersection entre deux ensembles. */ +GScanExpression *g_scan_expression_intersect(GScanExpression *, const GScanExpression *, GScanContext *, GScanScope *); 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); diff --git a/src/analysis/scan/grammar.y b/src/analysis/scan/grammar.y index 525c5d1..19a4257 100644 --- a/src/analysis/scan/grammar.y +++ b/src/analysis/scan/grammar.y @@ -18,12 +18,15 @@ typedef void *yyscan_t;  #include "scanner.h"  #include "exprs/access.h" -#include "exprs/arithmop.h" -#include "exprs/boolop.h" +#include "exprs/arithmetic.h"  #include "exprs/call.h" +#include "exprs/counter.h" +#include "exprs/intersect.h"  #include "exprs/literal.h" +#include "exprs/logical.h" +#include "exprs/set.h" +#include "exprs/relational.h"  #include "exprs/strop.h" -#include "exprs/relop.h"  #include "patterns/tokens/plain.h" @@ -48,13 +51,12 @@ typedef void *yyscan_t;      unsigned long long unsigned_integer;    /* Valeur entière #1           */      signed long long signed_integer;        /* Valeur entière #2           */ -    double floating_number;                 /* Valeur à virgule flottante  */ +    //double floating_number;                 /* Valeur à virgule flottante  */      sized_string_t sized_cstring;           /* Chaîne de caractères        */ -    char byte;                              /* Octet unique                */ +    //char byte;                              /* Octet unique                */ -    unsigned long long integer;             /* Valeur entière              */      GScanRule *rule;                        /* Nouvelle règle à intégrer   */ @@ -89,11 +91,17 @@ YY_DECL;  } +%token INCLUDE          "include" +  %token RAW_RULE  %token RULE_NAME  %token STRINGS CONDITION  %token IDENTIFIER +%token BYTES_ID +%token BYTES_ID_COUNTER +%token BYTES_ID_LOCATION +%token BYTES_ID_LENGTH  %token NAME  %token BRACE_IN BRACE_OUT ASSIGN COLON @@ -104,7 +112,8 @@ YY_DECL;  %token TRUE_            "true"  %token FALSE_           "false" -%token INTEGER +%token SIGNED_INTEGER +%token UNSIGNED_INTEGER  %token STRING  %token KB MB GB @@ -132,7 +141,7 @@ YY_DECL;  %token PLUS             "+"  %token MINUS            "-"  %token MUL              "*" -%token DIV              "\\" +%token DIV              "/"  %token MOD              "%"  %token PAREN_O          "(" @@ -145,16 +154,18 @@ YY_DECL;  %token ALL              "all"  %token OF               "of"  %token THEM             "them" +%token IN               "in"  %type <sized_cstring> RULE_NAME -%type <sized_cstring> IDENTIFIER +%type <sized_cstring> IDENTIFIER BYTES_ID_COUNTER  %type <sized_cstring> NAME -%type <integer> INTEGER +%type <signed_integer> SIGNED_INTEGER +%type <unsigned_integer> UNSIGNED_INTEGER  %type <sized_cstring> STRING  %type <rule> rule @@ -162,16 +173,19 @@ YY_DECL;  %type <sized_cstring> PLAIN_STRING  %type <pattern> MASKED_STRING -%type <expr> cexpression +%type <expr> cexpression _cexpression +%type <expr> pattern_match  %type <expr> literal  %type <expr> item_chain  %type <args_list> call_args -%type <expr> bool_expr -%type <expr> rel_expr -%type <expr> str_expr +%type <expr> logical_expr +%type <expr> relational_expr +%type <expr> string_op  %type <expr> arithm_expr  %type <expr> set_counter - +%type <expr> set +%type <expr> set_items +%type <expr> intersection  %left OR @@ -181,11 +195,11 @@ YY_DECL;  %left LT LE GT GE  %left PLUS MINUS  %left MUL DIV MOD +%left IN  %right NOT -  %destructor { printf("-------- Discarding symbol %p.\n", $$); } <rule> @@ -207,12 +221,24 @@ YY_DECL;  rules : /* empty */ +      | external rules        | rule rules { g_content_scanner_add_rule(scanner, $1); }          //rule : RAW_RULE RULE_NAME { printf("RULE %s\n", $2); } RAW_BLOCK { printf("BLOCK: %s\n", $4); } + +external : "include" STRING +         { +             bool __status; +             __status = g_content_scanner_include_resource(scanner, $2.data); +             if (!__status) +                 YYERROR; +         } + +  rule : RAW_RULE RULE_NAME       { +         //printf("--------built rule '%s'\n", $2.data);           *built_rule = g_scan_rule_new($2.data);           $<rule>$ = *built_rule;       } @@ -220,6 +246,7 @@ rule : RAW_RULE RULE_NAME       {           $$ = $<rule>3;           //printf("RULE %s -> %p\n", $2, $$); +         //printf("end of rule\n");       }  @@ -274,16 +301,18 @@ string_decl : IDENTIFIER ASSIGN PLAIN_STRING              }              ; -condition : /* empty */ -          | CONDITION COLON cexpression -          { -              g_scan_rule_set_match_condition(*built_rule, $3); -              g_object_ref(G_OBJECT($3)); -          } -          ; +      condition : /* empty */ +                | CONDITION COLON cexpression +                { +                    g_scan_rule_set_match_condition(*built_rule, $3); +                    g_object_unref(G_OBJECT($3)); +                } +                ; -cexpression : IDENTIFIER -            { +    cexpression : _cexpression { $$ = $1; if ($$ == NULL) { printf("ERROR !!!\n"); YYERROR; } } + +   _cexpression : IDENTIFIER +                {                  printf("named var: %s\n", "$1");                  /*                     GSearchPattern *__pat; @@ -297,112 +326,223 @@ cexpression : IDENTIFIER                         g_object_unref(G_OBJECT(__pat));                     }                  */ -            } -            | literal { $$ = $1; } -            | item_chain { $$ = $1; } -            | bool_expr { $$ = $1; } -            | rel_expr { $$ = $1; } -            | str_expr { $$ = $1; } -            | arithm_expr { $$ = $1; } -            | set_counter { $$ = $1; } -            | "(" cexpression ")" { $$ = $2; } +                } +                | literal { $$ = $1; } +                | pattern_match { $$ = $1; } +                | item_chain { $$ = $1; } +                | logical_expr { $$ = $1; } +                | relational_expr { $$ = $1; } +                | string_op { $$ = $1; } +                | arithm_expr { $$ = $1; } +                | set_counter { $$ = $1; } +                | set { $$ = $1; } +                | intersection { $$ = $1; } +                | "(" cexpression ")" { $$ = $2; } +                ; + +  pattern_match : BYTES_ID_COUNTER +                { +                    GSearchPattern *__pat; +                    __pat = g_scan_rule_get_local_variable(*built_rule, $1.data); +                    $$ = g_scan_match_counter_new(__pat); +                    g_object_unref(G_OBJECT(__pat)); +                } +                ; + +        literal : "true" +                { +                    $$ = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ true }); +                } +                | "false" +                { +                    $$ = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ false }); +                } +                | SIGNED_INTEGER +                { +                    $$ = g_scan_literal_expression_new(LVT_SIGNED_INTEGER, &$1); +                } +                | UNSIGNED_INTEGER +                { +                    $$ = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &$1); +                } +                | UNSIGNED_INTEGER KB +                { +                 unsigned long long __converted; +                 __converted = $1 * 1024; +                    $$ = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &__converted); +                } +                | UNSIGNED_INTEGER MB +                { +                 unsigned long long __converted; +                 __converted = $1 * 1048576; +                    $$ = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &__converted); +                } +                | UNSIGNED_INTEGER GB +                { +                 unsigned long long __converted; +                 __converted = $1 * 1073741824; +                    $$ = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &__converted); +                } +                | STRING +                { +                    $$ = g_scan_literal_expression_new(LVT_STRING, &$1); +                } +                ; + +     item_chain : NAME { $$ = g_scan_named_access_new(&$1); } +                | NAME "(" ")" { $$ = g_scan_pending_call_new(&$1, NULL, 0); } +                | NAME "(" call_args ")" +                { +                    size_t __i; +                    $$ = g_scan_pending_call_new(&$1, $3.args, $3.count); +                    for (__i = 0; __i < $3.count; __i++) +                        g_object_unref(G_OBJECT($3.args[__i])); +                    free($3.args); +                } +                | item_chain "." NAME +                { +                    GScanExpression *__next; +                    __next = g_scan_named_access_new(&$3); +                    g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS($1), G_SCAN_NAMED_ACCESS(__next)); +                    $$ = $1; +                } +                | item_chain "." NAME "(" ")" +                { +                    GScanExpression *__next; +                    __next = g_scan_pending_call_new(&$3, NULL, 0); +                    g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS($1), G_SCAN_NAMED_ACCESS(__next)); +                    $$ = $1; +                } +                | item_chain "." NAME "(" call_args ")" +                { +                    GScanExpression *__next; +                    size_t __i; +                    __next = g_scan_pending_call_new(&$3, $5.args, $5.count); +                    for (__i = 0; __i < $5.count; __i++) +                        g_object_unref(G_OBJECT($5.args[__i])); +                    free($5.args); +                    g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS($1), G_SCAN_NAMED_ACCESS(__next)); +                    $$ = $1; +                } +                ; + +      call_args : cexpression +                { +                    $$.count = 1; +                    $$.args = malloc(sizeof(GScanExpression *)); +                    $$.args[0] = $1; +                } +                | call_args "," cexpression +                { +                    $1.count++; +                    $1.args = realloc($1.args, $1.count * sizeof(GScanExpression *)); +                    $1.args[$1.count - 1] = $3; +                    $$ = $1; +                } +                ; + +   logical_expr : cexpression "and" cexpression { $$ = g_scan_logical_operation_new(BOT_AND, $1, $3); } +                | cexpression "or" cexpression  { $$ = g_scan_logical_operation_new(BOT_OR, $1, $3); } +                | "not" "(" cexpression ")"     { $$ = g_scan_logical_operation_new(BOT_NOT, $3, NULL); } +                ; + +relational_expr : cexpression "<" cexpression  { $$ = g_scan_relational_operation_new(RCO_LT, $1, $3); } +                | cexpression "<=" cexpression { $$ = g_scan_relational_operation_new(RCO_LE, $1, $3); } +                | cexpression "==" cexpression { $$ = g_scan_relational_operation_new(RCO_EQ, $1, $3); } +                | cexpression "!=" cexpression { $$ = g_scan_relational_operation_new(RCO_NE, $1, $3); } +                | cexpression ">" cexpression  { $$ = g_scan_relational_operation_new(RCO_GT, $1, $3); } +                | cexpression ">=" cexpression { $$ = g_scan_relational_operation_new(RCO_GE, $1, $3); } +                ; + +      string_op : cexpression "contains" cexpression +                { +                    $$ = g_scan_string_operation_new(SOT_CONTAINS, $1, $3, true); +                } +                | cexpression "startswith" cexpression +                { +                    $$ = g_scan_string_operation_new(SOT_STARTSWITH, $1, $3, true); +                } +                | cexpression "endswith" cexpression +                { +                    $$ = g_scan_string_operation_new(SOT_ENDSWITH, $1, $3, true); +                } +                | cexpression "matches" cexpression +                { +                    $$ = g_scan_string_operation_new(SOT_MATCHES, $1, $3, true); +                } +                | cexpression "icontains" cexpression +                { +                    $$ = g_scan_string_operation_new(SOT_CONTAINS, $1, $3, false); +                } +                | cexpression "istartswith" cexpression +                { +                    $$ = g_scan_string_operation_new(SOT_STARTSWITH, $1, $3, false); +                } +                | cexpression "iendswith" cexpression +                { +                    $$ = g_scan_string_operation_new(SOT_ENDSWITH, $1, $3, false); +                } +                | cexpression "iequals" cexpression +                { +                    $$ = g_scan_string_operation_new(SOT_IEQUALS, $1, $3, false); +                } +                ; + +    arithm_expr : cexpression "+" cexpression  { $$ = g_scan_arithmetic_operation_new(AEO_PLUS, $1, $3); } +                | cexpression "-" cexpression  { $$ = g_scan_arithmetic_operation_new(AEO_MINUS, $1, $3); } +                | cexpression "*" cexpression  { $$ = g_scan_arithmetic_operation_new(AEO_MUL, $1, $3); } +                | cexpression "/" cexpression { $$ = g_scan_arithmetic_operation_new(AEO_DIV, $1, $3); } +                | cexpression "%" cexpression  { $$ = g_scan_arithmetic_operation_new(AEO_MOD, $1, $3); } +                ; + +set_counter : "none" "of" "them"  { $$ = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ true }); } +            | "any" "of" "them"  { $$ = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ true }); } +            | "all" "of" "them"  { $$ = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ true }); }              ; -literal : "true" { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ true }); } -        | "false" { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ false }); } -        | INTEGER { $$ = g_literal_expression_new(EVT_INTEGER, &$1); } -        | INTEGER KB { $$ = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ $1 * 1024 }); } -        | INTEGER MB { $$ = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ $1 * 1048576 }); } -        | INTEGER GB { $$ = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ $1 * 1073741824 }); } -        | STRING { $$ = g_literal_expression_new(EVT_STRING, &$1); } -        ; -item_chain : NAME { $$ = g_named_access_new(&$1); } -         | NAME "(" ")" { $$ = g_pending_call_new(&$1, NULL, 0); } -         | NAME "(" call_args ")" -         { -             size_t __i; -             $$ = g_pending_call_new(&$1, $3.args, $3.count); -             for (__i = 0; __i < $3.count; __i++) -                 g_object_unref(G_OBJECT($3.args[__i])); -             free($3.args); -         } -         | item_chain "." NAME -         { -             GScanExpression *__next; -             __next = g_named_access_new(&$3); -             g_named_access_attach_next(G_NAMED_ACCESS($1), G_NAMED_ACCESS(__next)); -             $$ = $1; -         } -         | item_chain "." NAME "(" ")" -         { -             GScanExpression *__next; -             __next = g_pending_call_new(&$3, NULL, 0); -             g_named_access_attach_next(G_NAMED_ACCESS($1), G_NAMED_ACCESS(__next)); -             $$ = $1; -         } -         | item_chain "." NAME "(" call_args ")" -         { -             GScanExpression *__next; -             size_t __i; -             __next = g_pending_call_new(&$3, $5.args, $5.count); -             for (__i = 0; __i < $5.count; __i++) -                 g_object_unref(G_OBJECT($5.args[__i])); -             free($5.args); -             g_named_access_attach_next(G_NAMED_ACCESS($1), G_NAMED_ACCESS(__next)); -             $$ = $1; -         } -         ; - -call_args : cexpression -          { -              $$.count = 1; -              $$.args = malloc(sizeof(GScanExpression *)); -              $$.args[0] = $1; -          } -          | call_args "," cexpression -          { -              $1.count++; -              $1.args = realloc($1.args, $1.count * sizeof(GScanExpression *)); -              $1.args[$1.count - 1] = $3; -              $$ = $1; -          } -          ; - -bool_expr : cexpression "and" cexpression { $$ = g_boolean_operation_new(BOT_AND, $1, $3); } -          | cexpression "or" cexpression  { $$ = g_boolean_operation_new(BOT_OR, $1, $3); } -          | "not" "(" cexpression ")"     { $$ = g_boolean_operation_new(BOT_NOT, $3, NULL); } -          ; - -rel_expr : cexpression "<" cexpression  { $$ = g_relational_operation_new(RCO_LT, $1, $3); } -         | cexpression "<=" cexpression { $$ = g_relational_operation_new(RCO_LE, $1, $3); } -         | cexpression "==" cexpression { $$ = g_relational_operation_new(RCO_EQ, $1, $3); } -         | cexpression "!=" cexpression { $$ = g_relational_operation_new(RCO_NE, $1, $3); } -         | cexpression ">" cexpression  { $$ = g_relational_operation_new(RCO_GT, $1, $3); } -         | cexpression ">=" cexpression { $$ = g_relational_operation_new(RCO_GT, $1, $3); } -         ; - -str_expr : cexpression "contains" cexpression    { $$ = g_string_operation_new(SOT_CONTAINS, $1, $3, true); } -         | cexpression "startswith" cexpression  { $$ = g_string_operation_new(SOT_STARTSWITH, $1, $3, true); } -         | cexpression "endswith" cexpression    { $$ = g_string_operation_new(SOT_ENDSWITH, $1, $3, true); } -         | cexpression "matches" cexpression     { $$ = g_string_operation_new(SOT_MATCHES, $1, $3, true); } -         | cexpression "icontains" cexpression   { $$ = g_string_operation_new(SOT_CONTAINS, $1, $3, false); } -         | cexpression "istartswith" cexpression { $$ = g_string_operation_new(SOT_STARTSWITH, $1, $3, false); } -         | cexpression "iendswith" cexpression   { $$ = g_string_operation_new(SOT_ENDSWITH, $1, $3, false); } -         | cexpression "iequals" cexpression     { $$ = g_string_operation_new(SOT_IEQUALS, $1, $3, false); } -         ; - -arithm_expr : cexpression "+" cexpression  { $$ = g_arithmetic_operation_new(AEO_PLUS, $1, $3); } -            | cexpression "-" cexpression  { $$ = g_arithmetic_operation_new(AEO_MINUS, $1, $3); } -            | cexpression "*" cexpression  { $$ = g_arithmetic_operation_new(AEO_MUL, $1, $3); } -            | cexpression "\\" cexpression { $$ = g_arithmetic_operation_new(AEO_DIV, $1, $3); } -            | cexpression "%" cexpression  { $$ = g_arithmetic_operation_new(AEO_MOD, $1, $3); } -            ; +            set : "(" ")" +                { +                    $$ = g_scan_generic_set_new(); +                } +                | "(" cexpression "," ")" +                { +                    $$ = g_scan_generic_set_new(); +                    g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $2); +                    g_object_unref(G_OBJECT($2)); +                } +                | "(" set_items ")" +                { +                    $$ = $2; +                } +                ; + +      set_items : cexpression "," cexpression +                { +                    $$ = g_scan_generic_set_new(); +                    g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $1); +                    g_object_unref(G_OBJECT($1)); +                    g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $3); +                    g_object_unref(G_OBJECT($3)); +                } +                | set_items "," cexpression +                { +                    $$ = $1; +                    g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $3); +                    g_object_unref(G_OBJECT($3)); +                } +                ; + +   intersection : cexpression "in" cexpression +                { +                    $$ = g_scan_sets_intersection_new($1, $3); +                    g_object_unref(G_OBJECT($1)); +                    g_object_unref(G_OBJECT($3)); +                } +                ; + + -set_counter : "none" "of" "them"  { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ true }); } -            | "any" "of" "them"  { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ true }); } -            | "all" "of" "them"  { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ true }); } -            ;  %% diff --git a/src/analysis/scan/items/Makefile.am b/src/analysis/scan/items/Makefile.am index 3a6bb62..ce39cad 100644 --- a/src/analysis/scan/items/Makefile.am +++ b/src/analysis/scan/items/Makefile.am @@ -2,14 +2,32 @@  noinst_LTLIBRARIES  = libanalysisscanitems.la +if BUILD_MAGIC_SUPPORT + +MAGIC_LIBADD = magic/libanalysisscanitemsmagic.la + +MAGIC_SUBDIRS = magic + +endif + +  libanalysisscanitems_la_SOURCES =			\ +	count.h count.c							\  	datasize.h datasize.c					\  	uint-int.h								\  	uint.h uint.c +libanalysisscanitems_la_LIBADD = 			\ +	console/libanalysisscanitemsconsole.la	\ +	$(MAGIC_LIBADD)							\ +	time/libanalysisscanitemstime.la +  libanalysisscanitems_la_CFLAGS = $(LIBGOBJ_CFLAGS)  devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)  dev_HEADERS = $(libanalysisscanitems_la_SOURCES:%c=) + + +SUBDIRS = console $(MAGIC_SUBDIRS) time diff --git a/src/analysis/scan/items/console/Makefile.am b/src/analysis/scan/items/console/Makefile.am new file mode 100644 index 0000000..4433789 --- /dev/null +++ b/src/analysis/scan/items/console/Makefile.am @@ -0,0 +1,13 @@ + +noinst_LTLIBRARIES  = libanalysisscanitemsconsole.la + + +libanalysisscanitemsconsole_la_SOURCES =	\ +	log.h log.c + +libanalysisscanitemsconsole_la_CFLAGS = $(LIBGOBJ_CFLAGS) + + +devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) + +dev_HEADERS = $(libanalysisscanitemsconsole_la_SOURCES:%c=) diff --git a/src/analysis/scan/items/console/log.c b/src/analysis/scan/items/console/log.c new file mode 100644 index 0000000..f4031c7 --- /dev/null +++ b/src/analysis/scan/items/console/log.c @@ -0,0 +1,303 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * log.c - affichage de message à partir des conditions d'une règle + * + * 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 "log.h" + + +#include <ctype.h> + + +#include "../../item-int.h" +#include "../../exprs/literal.h" + + + +/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */ + + +/* Initialise la classe des affichages de messages. */ +static void g_scan_console_log_function_class_init(GScanConsoleLogFunctionClass *); + +/* Initialise une instance d'affichage de message. */ +static void g_scan_console_log_function_init(GScanConsoleLogFunction *); + +/* Supprime toutes les références externes. */ +static void g_scan_console_log_function_dispose(GScanConsoleLogFunction *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_console_log_function_finalize(GScanConsoleLogFunction *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Indique le nom associé à une expression d'évaluation. */ +static char *g_scan_console_log_function_get_name(const GScanConsoleLogFunction *); + +/* Réduit une expression à une forme plus simple. */ +static bool g_scan_console_log_function_run_call(GScanConsoleLogFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); + + + +/* ---------------------------------------------------------------------------------- */ +/*                        INTRODUCTION D'UNE NOUVELLE FONCTION                        */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un afficheur de messages arbitraires. */ +G_DEFINE_TYPE(GScanConsoleLogFunction, g_scan_console_log_function, G_TYPE_REGISTERED_ITEM); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des affichages de messages.             * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_console_log_function_class_init(GScanConsoleLogFunctionClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GRegisteredItemClass *registered;       /* Version de classe parente   */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_console_log_function_dispose; +    object->finalize = (GObjectFinalizeFunc)g_scan_console_log_function_finalize; + +    registered = G_REGISTERED_ITEM_CLASS(klass); + +    registered->get_name = (get_registered_item_name_fc)g_scan_console_log_function_get_name; +    registered->run_call = (run_registered_item_call_fc)g_scan_console_log_function_run_call; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance à initialiser.                               * +*                                                                             * +*  Description : Initialise une instance d'affichage de message.              * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_console_log_function_init(GScanConsoleLogFunction *func) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_console_log_function_dispose(GScanConsoleLogFunction *func) +{ +    G_OBJECT_CLASS(g_scan_console_log_function_parent_class)->dispose(G_OBJECT(func)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_console_log_function_finalize(GScanConsoleLogFunction *func) +{ +    G_OBJECT_CLASS(g_scan_console_log_function_parent_class)->finalize(G_OBJECT(func)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Constitue une fonction d'affichage de messages quelconques.  * +*                                                                             * +*  Retour      : Fonction mise en place.                                      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GScanConsoleLogFunction *g_scan_console_log_function_new(void) +{ +    GScanConsoleLogFunction *result;              /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_SCAN_CONSOLE_LOG_FUNCTION, NULL); + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item = élément d'appel à consulter.                          * +*                                                                             * +*  Description : Indique le nom associé à une expression d'évaluation.        * +*                                                                             * +*  Retour      : Désignation humaine de l'expression d'évaluation.            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char *g_scan_console_log_function_get_name(const GScanConsoleLogFunction *item) +{ +    char *result;                           /* Désignation à retourner     */ + +    result = strdup("log"); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item  = élément d'appel à consulter.                         * +*                args  = liste d'éventuels arguments fournis.                 * +*                count = taille de cette liste.                               * +*                ctx   = contexte de suivi de l'analyse courante.             * +*                scope = portée courante des variables locales.               * +*                out   = zone d'enregistrement de la résolution opérée. [OUT] * +*                                                                             * +*  Description : Réduit une expression à une forme plus simple.               * +*                                                                             * +*  Retour      : Réduction correspondante, expression déjà réduite, ou NULL.  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_scan_console_log_function_run_call(GScanConsoleLogFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out) +{ +    bool result;                            /* Bilan à retourner           */ +    size_t i;                               /* Boucle de parcours #1       */ +    LiteralValueType vtype;                 /* Type de valeur portée       */ +    GScanLiteralExpression *literal;        /* Version plus accessible     */ +    bool boolean;                           /* Valeur booléenne            */ +    long long sinteger;                     /* Valeur entière signée   */ +    unsigned long long uinteger;            /* Valeur entière non signée   */ +    const sized_string_t *string;           /* Description du chaîne       */ +    size_t k;                               /* Boucle de parcours #2       */ + +    result = true; + +    if (count == 0) +        goto done; + +    for (i = 0; i < count && result; i++) +        result = G_IS_SCAN_LITERAL_EXPRESSION(args[i]); + +    if (!result) +        goto done; + +    for (i = 0; i < count; i++) +    { +        literal = G_SCAN_LITERAL_EXPRESSION(args[i]); + +        vtype = g_scan_literal_expression_get_value_type(literal); + +        switch (vtype) +        { +            case LVT_BOOLEAN: +                result = g_scan_literal_expression_get_boolean_value(literal, &boolean); +                if (result) +                    fprintf(stderr, "%s", boolean ? "true" : "false"); +                break; + +            case LVT_SIGNED_INTEGER: +                result = g_scan_literal_expression_get_signed_integer_value(literal, &sinteger); +                if (result) +                    fprintf(stderr, "0x%llx", sinteger); +                break; + +            case LVT_UNSIGNED_INTEGER: +                result = g_scan_literal_expression_get_unsigned_integer_value(literal, &uinteger); +                if (result) +                    fprintf(stderr, "0x%llx", uinteger); +                break; + +            case LVT_STRING: +                result = g_scan_literal_expression_get_string_value(literal, &string); +                for (k = 0; k < string->len; k++) +                { +                    if (isprint(string->data[k])) +                        fprintf(stderr, "%c", string->data[k]); +                    else +                        fprintf(stderr, "\\x%02hhx", string->data[k]); +                } +                break; + +            default: +                break; + +        } + +    } + +    fprintf(stderr, "\n"); + + done: + +    if (result) +        *out = G_OBJECT(g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ result })); + +    return result; + +} diff --git a/src/analysis/scan/items/console/log.h b/src/analysis/scan/items/console/log.h new file mode 100644 index 0000000..3e72ad8 --- /dev/null +++ b/src/analysis/scan/items/console/log.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * log.h - prototypes pour l'affichage de message à partir des conditions d'une règle + * + * 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_ITEMS_CONSOLE_LOG_H +#define _ANALYSIS_SCAN_ITEMS_CONSOLE_LOG_H + + +#include <glib-object.h> + + +#include "../../item.h" + + + +#define G_TYPE_SCAN_CONSOLE_LOG_FUNCTION            g_scan_console_log_function_get_type() +#define G_SCAN_CONSOLE_LOG_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_CONSOLE_LOG_FUNCTION, GScanConsoleLogFunction)) +#define G_IS_SCAN_CONSOLE_LOG_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_CONSOLE_LOG_FUNCTION)) +#define G_SCAN_CONSOLE_LOG_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_CONSOLE_LOG_FUNCTION, GScanConsoleLogFunctionClass)) +#define G_IS_SCAN_CONSOLE_LOG_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_CONSOLE_LOG_FUNCTION)) +#define G_SCAN_CONSOLE_LOG_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_CONSOLE_LOG_FUNCTION, GScanConsoleLogFunctionClass)) + + +/* Mesure de la quantité de données scannées (instance) */ +typedef GRegisteredItem GScanConsoleLogFunction; + +/* Mesure de la quantité de données scannées (classe) */ +typedef GRegisteredItemClass GScanConsoleLogFunctionClass; + + +/* Indique le type défini pour un afficheur de messages arbitraires. */ +GType g_scan_console_log_function_get_type(void); + +/* Constitue une fonction d'affichage de messages quelconques. */ +GScanConsoleLogFunction *g_scan_console_log_function_new(void); + + + +#endif  /* _ANALYSIS_SCAN_ITEMS_CONSOLE_LOG_H */ diff --git a/src/analysis/scan/items/count.c b/src/analysis/scan/items/count.c new file mode 100644 index 0000000..d87d33b --- /dev/null +++ b/src/analysis/scan/items/count.c @@ -0,0 +1,244 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * count.c - récupération de la taille du contenu scanné + * + * 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 "count.h" + + +#include "../item-int.h" +#include "../exprs/arithmetic.h" +#include "../exprs/literal.h" + + + +/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */ + + +/* Initialise la classe des décomptes d'ensemble homogène. */ +static void g_scan_count_function_class_init(GScanCountFunctionClass *); + +/* Initialise une instance de décompte d'ensemble homogène. */ +static void g_scan_count_function_init(GScanCountFunction *); + +/* Supprime toutes les références externes. */ +static void g_scan_count_function_dispose(GScanCountFunction *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_count_function_finalize(GScanCountFunction *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Indique le nom associé à une expression d'évaluation. */ +static char *g_scan_count_function_get_name(const GScanCountFunction *); + +/* Réduit une expression à une forme plus simple. */ +static bool g_scan_count_function_run_call(GScanCountFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); + + + +/* ---------------------------------------------------------------------------------- */ +/*                        INTRODUCTION D'UNE NOUVELLE FONCTION                        */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un décompte d'ensemble. */ +G_DEFINE_TYPE(GScanCountFunction, g_scan_count_function, G_TYPE_REGISTERED_ITEM); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des décomptes d'ensemble homogène.      * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_count_function_class_init(GScanCountFunctionClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GRegisteredItemClass *registered;       /* Version de classe parente   */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_count_function_dispose; +    object->finalize = (GObjectFinalizeFunc)g_scan_count_function_finalize; + +    registered = G_REGISTERED_ITEM_CLASS(klass); + +    registered->get_name = (get_registered_item_name_fc)g_scan_count_function_get_name; +    registered->run_call = (run_registered_item_call_fc)g_scan_count_function_run_call; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance à initialiser.                               * +*                                                                             * +*  Description : Initialise une instance de décompte d'ensemble homogène.     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_count_function_init(GScanCountFunction *func) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_count_function_dispose(GScanCountFunction *func) +{ +    G_OBJECT_CLASS(g_scan_count_function_parent_class)->dispose(G_OBJECT(func)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_count_function_finalize(GScanCountFunction *func) +{ +    G_OBJECT_CLASS(g_scan_count_function_parent_class)->finalize(G_OBJECT(func)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Constitue une fonction de décompte d'éléments d'un ensemble. * +*                                                                             * +*  Retour      : Fonction mise en place.                                      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GRegisteredItem *g_scan_count_function_new(void) +{ +    GScanCountFunction *result;              /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_SCAN_COUNT_FUNCTION, NULL); + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item = élément d'appel à consulter.                          * +*                                                                             * +*  Description : Indique le nom associé à une expression d'évaluation.        * +*                                                                             * +*  Retour      : Désignation humaine de l'expression d'évaluation.            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char *g_scan_count_function_get_name(const GScanCountFunction *item) +{ +    char *result;                           /* Désignation à retourner     */ + +    result = strdup("count"); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item  = élément d'appel à consulter.                         * +*                args  = liste d'éventuels arguments fournis.                 * +*                count = taille de cette liste.                               * +*                ctx   = contexte de suivi de l'analyse courante.             * +*                scope = portée courante des variables locales.               * +*                out   = zone d'enregistrement de la résolution opérée. [OUT] * +*                                                                             * +*  Description : Réduit une expression à une forme plus simple.               * +*                                                                             * +*  Retour      : Réduction correspondante, expression déjà réduite, ou NULL.  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_scan_count_function_run_call(GScanCountFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out) +{ +    bool result;                            /* Bilan à retourner           */ +    size_t value;                           /* Nouveau décompte            */ + +    if (count != 1) +        result = false; + +    else +    { +        result = g_scan_expression_count_items(args[0], &value); + +        if (result) +            *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ value })); + +    } + +    return result; + +} diff --git a/src/analysis/scan/items/count.h b/src/analysis/scan/items/count.h new file mode 100644 index 0000000..2429e40 --- /dev/null +++ b/src/analysis/scan/items/count.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * count.h - prototypes pour la récupération de la taille du contenu scanné + * + * 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_ITEMS_COUNT_H +#define _ANALYSIS_SCAN_ITEMS_COUNT_H + + +#include <glib-object.h> + + +#include "../item.h" + + + +#define G_TYPE_SCAN_COUNT_FUNCTION            g_scan_count_function_get_type() +#define G_SCAN_COUNT_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_COUNT_FUNCTION, GScanCountFunction)) +#define G_IS_SCAN_COUNT_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_COUNT_FUNCTION)) +#define G_SCAN_COUNT_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_COUNT_FUNCTION, GScanCountFunctionClass)) +#define G_IS_SCAN_COUNT_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_COUNT_FUNCTION)) +#define G_SCAN_COUNT_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_COUNT_FUNCTION, GScanCountFunctionClass)) + + +/* Mesure de la quantité de données scannées (instance) */ +typedef GRegisteredItem GScanCountFunction; + +/* Mesure de la quantité de données scannées (classe) */ +typedef GRegisteredItemClass GScanCountFunctionClass; + + +/* Indique le type défini pour un décompte d'ensemble. */ +GType g_scan_count_function_get_type(void); + +/* Constitue une fonction de décompte d'éléments d'un ensemble. */ +GRegisteredItem *g_scan_count_function_new(void); + + + +#endif  /* _ANALYSIS_SCAN_ITEMS_COUNT_H */ diff --git a/src/analysis/scan/items/datasize.c b/src/analysis/scan/items/datasize.c index 618d0c3..55e2d3b 100644 --- a/src/analysis/scan/items/datasize.c +++ b/src/analysis/scan/items/datasize.c @@ -2,7 +2,7 @@  /* Chrysalide - Outil d'analyse de fichiers binaires   * datasize.c - récupération de la taille du contenu scanné   * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard   *   *  This file is part of Chrysalide.   * @@ -33,16 +33,16 @@  /* Initialise la classe des mesures de quantité de données. */ -static void g_datasize_function_class_init(GDatasizeFunctionClass *); +static void g_scan_datasize_function_class_init(GScanDatasizeFunctionClass *);  /* Initialise une instance de mesure de quantité de données. */ -static void g_datasize_function_init(GDatasizeFunction *); +static void g_scan_datasize_function_init(GScanDatasizeFunction *);  /* Supprime toutes les références externes. */ -static void g_datasize_function_dispose(GDatasizeFunction *); +static void g_scan_datasize_function_dispose(GScanDatasizeFunction *);  /* Procède à la libération totale de la mémoire. */ -static void g_datasize_function_finalize(GDatasizeFunction *); +static void g_scan_datasize_function_finalize(GScanDatasizeFunction *); @@ -50,13 +50,13 @@ static void g_datasize_function_finalize(GDatasizeFunction *);  /* Indique le nom associé à une expression d'évaluation. */ -static char *g_datasize_function_get_name(const GDatasizeFunction *); +static char *g_scan_datasize_function_get_name(const GScanDatasizeFunction *);  /* Réduit une expression à une forme plus simple. */ -static bool g_datasize_function_reduce(GDatasizeFunction *, GScanContext *, GScanScope *, GScanExpression **); +static bool g_scan_datasize_function_reduce(GScanDatasizeFunction *, GScanContext *, GScanScope *, GScanExpression **);  /* Réduit une expression à une forme plus simple. */ -static bool g_datasize_function_run_call(GDatasizeFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); +static bool g_scan_datasize_function_run_call(GScanDatasizeFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); @@ -66,7 +66,7 @@ static bool g_datasize_function_run_call(GDatasizeFunction *, GScanExpression **  /* Indique le type défini pour une mesure de quantité de données scannées. */ -G_DEFINE_TYPE(GDatasizeFunction, g_datasize_function, G_TYPE_REGISTERED_ITEM); +G_DEFINE_TYPE(GScanDatasizeFunction, g_scan_datasize_function, G_TYPE_REGISTERED_ITEM);  /****************************************************************************** @@ -81,21 +81,21 @@ G_DEFINE_TYPE(GDatasizeFunction, g_datasize_function, G_TYPE_REGISTERED_ITEM);  *                                                                             *  ******************************************************************************/ -static void g_datasize_function_class_init(GDatasizeFunctionClass *klass) +static void g_scan_datasize_function_class_init(GScanDatasizeFunctionClass *klass)  {      GObjectClass *object;                   /* Autre version de la classe  */      GRegisteredItemClass *registered;       /* Version de classe parente   */      object = G_OBJECT_CLASS(klass); -    object->dispose = (GObjectFinalizeFunc/* ! */)g_datasize_function_dispose; -    object->finalize = (GObjectFinalizeFunc)g_datasize_function_finalize; +    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_datasize_function_dispose; +    object->finalize = (GObjectFinalizeFunc)g_scan_datasize_function_finalize;      registered = G_REGISTERED_ITEM_CLASS(klass); -    registered->get_name = (get_registered_item_name_fc)g_datasize_function_get_name; -    registered->reduce = (reduce_registered_item_fc)g_datasize_function_reduce; -    registered->run_call = (run_registered_item_call_fc)g_datasize_function_run_call; +    registered->get_name = (get_registered_item_name_fc)g_scan_datasize_function_get_name; +    registered->reduce = (reduce_registered_item_fc)g_scan_datasize_function_reduce; +    registered->run_call = (run_registered_item_call_fc)g_scan_datasize_function_run_call;  } @@ -112,7 +112,7 @@ static void g_datasize_function_class_init(GDatasizeFunctionClass *klass)  *                                                                             *  ******************************************************************************/ -static void g_datasize_function_init(GDatasizeFunction *func) +static void g_scan_datasize_function_init(GScanDatasizeFunction *func)  {  } @@ -130,9 +130,9 @@ static void g_datasize_function_init(GDatasizeFunction *func)  *                                                                             *  ******************************************************************************/ -static void g_datasize_function_dispose(GDatasizeFunction *func) +static void g_scan_datasize_function_dispose(GScanDatasizeFunction *func)  { -    G_OBJECT_CLASS(g_datasize_function_parent_class)->dispose(G_OBJECT(func)); +    G_OBJECT_CLASS(g_scan_datasize_function_parent_class)->dispose(G_OBJECT(func));  } @@ -149,9 +149,9 @@ static void g_datasize_function_dispose(GDatasizeFunction *func)  *                                                                             *  ******************************************************************************/ -static void g_datasize_function_finalize(GDatasizeFunction *func) +static void g_scan_datasize_function_finalize(GScanDatasizeFunction *func)  { -    G_OBJECT_CLASS(g_datasize_function_parent_class)->finalize(G_OBJECT(func)); +    G_OBJECT_CLASS(g_scan_datasize_function_parent_class)->finalize(G_OBJECT(func));  } @@ -168,11 +168,11 @@ static void g_datasize_function_finalize(GDatasizeFunction *func)  *                                                                             *  ******************************************************************************/ -GDatasizeFunction *g_datasize_function_new(void) +GRegisteredItem *g_scan_datasize_function_new(void)  { -    GDatasizeFunction *result;              /* Structure à retourner       */ +    GScanDatasizeFunction *result;              /* Structure à retourner       */ -    result = g_object_new(G_TYPE_DATASIZE_FUNCTION, NULL); +    result = g_object_new(G_TYPE_SCAN_DATASIZE_FUNCTION, NULL);      return result; @@ -197,7 +197,7 @@ GDatasizeFunction *g_datasize_function_new(void)  *                                                                             *  ******************************************************************************/ -static char *g_datasize_function_get_name(const GDatasizeFunction *item) +static char *g_scan_datasize_function_get_name(const GScanDatasizeFunction *item)  {      char *result;                           /* Désignation à retourner     */ @@ -223,7 +223,7 @@ static char *g_datasize_function_get_name(const GDatasizeFunction *item)  *                                                                             *  ******************************************************************************/ -static bool g_datasize_function_reduce(GDatasizeFunction *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +static bool g_scan_datasize_function_reduce(GScanDatasizeFunction *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out)  {      bool result;                            /* Bilan à retourner           */      GBinContent *content;                   /* Contenu à manipuler         */ @@ -235,7 +235,7 @@ static bool g_datasize_function_reduce(GDatasizeFunction *item, GScanContext *ct      size = g_binary_content_compute_size(content); -    *out = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ size }); +    *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ size });      g_object_unref(G_OBJECT(content)); @@ -261,11 +261,11 @@ static bool g_datasize_function_reduce(GDatasizeFunction *item, GScanContext *ct  *                                                                             *  ******************************************************************************/ -static bool g_datasize_function_run_call(GDatasizeFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out) +static bool g_scan_datasize_function_run_call(GScanDatasizeFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)  {      bool result;                            /* Bilan à retourner           */ -    result = g_datasize_function_reduce(item, ctx, scope, (GScanExpression **)out); +    result = g_scan_datasize_function_reduce(item, ctx, scope, (GScanExpression **)out);      return result; diff --git a/src/analysis/scan/items/datasize.h b/src/analysis/scan/items/datasize.h index bd8e185..476df2d 100644 --- a/src/analysis/scan/items/datasize.h +++ b/src/analysis/scan/items/datasize.h @@ -2,7 +2,7 @@  /* Chrysalide - Outil d'analyse de fichiers binaires   * datasize.h - prototypes pour la récupération de la taille du contenu scanné   * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard   *   *  This file is part of Chrysalide.   * @@ -32,26 +32,26 @@ -#define G_TYPE_DATASIZE_FUNCTION            g_datasize_function_get_type() -#define G_DATASIZE_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DATASIZE_FUNCTION, GDatasizeFunction)) -#define G_IS_DATASIZE_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DATASIZE_FUNCTION)) -#define G_DATASIZE_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DATASIZE_FUNCTION, GDatasizeFunctionClass)) -#define G_IS_DATASIZE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DATASIZE_FUNCTION)) -#define G_DATASIZE_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DATASIZE_FUNCTION, GDatasizeFunctionClass)) +#define G_TYPE_SCAN_DATASIZE_FUNCTION            g_scan_datasize_function_get_type() +#define G_SCAN_DATASIZE_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_DATASIZE_FUNCTION, GScanDatasizeFunction)) +#define G_IS_SCAN_DATASIZE_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_DATASIZE_FUNCTION)) +#define G_SCAN_DATASIZE_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_DATASIZE_FUNCTION, GScanDatasizeFunctionClass)) +#define G_IS_SCAN_DATASIZE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_DATASIZE_FUNCTION)) +#define G_SCAN_DATASIZE_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_DATASIZE_FUNCTION, GScanDatasizeFunctionClass))  /* Mesure de la quantité de données scannées (instance) */ -typedef GRegisteredItem GDatasizeFunction; +typedef GRegisteredItem GScanDatasizeFunction;  /* Mesure de la quantité de données scannées (classe) */ -typedef GRegisteredItemClass GDatasizeFunctionClass; +typedef GRegisteredItemClass GScanDatasizeFunctionClass;  /* Indique le type défini pour une mesure de quantité de données scannées. */ -GType g_datasize_function_get_type(void); +GType g_scan_datasize_function_get_type(void);  /* Constitue une fonction de récupération de taille de données. */ -GDatasizeFunction *g_datasize_function_new(void); +GRegisteredItem *g_scan_datasize_function_new(void); diff --git a/src/analysis/scan/items/magic/Makefile.am b/src/analysis/scan/items/magic/Makefile.am new file mode 100644 index 0000000..1d741ff --- /dev/null +++ b/src/analysis/scan/items/magic/Makefile.am @@ -0,0 +1,16 @@ + +noinst_LTLIBRARIES  = libanalysisscanitemsmagic.la + + +libanalysisscanitemsmagic_la_SOURCES =		\ +	cookie.h cookie.c						\ +	mime-encoding.h mime-encoding.c			\ +	mime-type.h mime-type.c					\ +	type.h type.c + +libanalysisscanitemsmagic_la_CFLAGS = $(LIBGOBJ_CFLAGS) $(LIBMAGIC_CFLAGS) + + +devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) + +dev_HEADERS = $(libanalysisscanitemsmagic_la_SOURCES:%c=) diff --git a/src/analysis/scan/items/magic/cookie.c b/src/analysis/scan/items/magic/cookie.c new file mode 100644 index 0000000..41f26a0 --- /dev/null +++ b/src/analysis/scan/items/magic/cookie.c @@ -0,0 +1,122 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * cookie.c - chargement des motifs de reconnaissance de contenus + * + * 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 "cookie.h" + + +#include <assert.h> + + +#include <i18n.h> + + +#include "../../../../core/logs.h" + + + +/* Référence des bibliothèques de reconnaissance */ +static magic_t __magic_cookie = 0; + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Charge les motifs de reconnaissance de contenus.             * +*                                                                             * +*  Retour      : Bilan de l'opération de chargemement.                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool init_magic_cookie(void) +{ +    bool result;                            /* Bilan à retourner           */ +    int ret;                                /* Bilan d'une opération       */ + +    __magic_cookie = magic_open(0); + +    ret = magic_load(__magic_cookie, NULL); +    result = (ret != -1); + +    if (!result) +        log_variadic_message(LMT_EXT_ERROR, _("cannot load magic database: %s"), magic_error(__magic_cookie)); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Décharge les motifs de reconnaissance de contenus.           * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void exit_magic_cookie(void) +{ +    magic_close(__magic_cookie); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : flags = forme de reconnaissance à préparer.                  * +*                                                                             * +*  Description : Fournit la référence aux mécanismes de reconnaissance.       * +*                                                                             * +*  Retour      : Cookie prêt à emploi.                                        *  +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +magic_t get_magic_cookie(int flags) +{ +    magic_t result;                         /* Référence à retourner       */ +#ifndef NDEBUG +    int ret;                                /* Bilan de la préparation     */ +#endif + +    result = __magic_cookie; +    assert(result != 0); + +#ifndef NDEBUG +    ret = magic_setflags(result, flags); +    assert(ret != -1); +#else +    magic_setflags(result, flags); +#endif + +    return result; + +} diff --git a/src/analysis/scan/items/magic/cookie.h b/src/analysis/scan/items/magic/cookie.h new file mode 100644 index 0000000..0ee2274 --- /dev/null +++ b/src/analysis/scan/items/magic/cookie.h @@ -0,0 +1,44 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * cookie.h - prototypes pour le chargement des motifs de reconnaissance de contenus + * + * 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_ITEMS_MAGIC_COOKIE_H +#define _ANALYSIS_SCAN_ITEMS_MAGIC_COOKIE_H + + +#include <magic.h> +#include <stdbool.h> + + + +/* Charge les motifs de reconnaissance de contenus. */ +bool init_magic_cookie(void); + +/* Décharge les motifs de reconnaissance de contenus. */ +void exit_magic_cookie(void); + +/* Fournit la référence aux mécanismes de reconnaissance. */ +magic_t get_magic_cookie(int); + + + +#endif  /* _ANALYSIS_SCAN_ITEMS_MAGIC_COOKIE_H */ diff --git a/src/analysis/scan/items/magic/mime-encoding.c b/src/analysis/scan/items/magic/mime-encoding.c new file mode 100644 index 0000000..935515d --- /dev/null +++ b/src/analysis/scan/items/magic/mime-encoding.c @@ -0,0 +1,270 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * mime-encoding.c - reconnaissance de l'encodage d'un contenu + * + * 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 "mime-encoding.h" + + +#include "cookie.h" +#include "../../item-int.h" +#include "../../exprs/literal.h" + + + +/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */ + + +/* Initialise la classe des reconnaissances de contenus. */ +static void g_scan_mime_encoding_function_class_init(GScanMimeEncodingFunctionClass *); + +/* Initialise une instance de reconnaissance de contenus. */ +static void g_scan_mime_encoding_function_init(GScanMimeEncodingFunction *); + +/* Supprime toutes les références externes. */ +static void g_scan_mime_encoding_function_dispose(GScanMimeEncodingFunction *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_mime_encoding_function_finalize(GScanMimeEncodingFunction *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Indique le nom associé à une expression d'évaluation. */ +static char *g_scan_mime_encoding_function_get_name(const GScanMimeEncodingFunction *); + +/* Réduit une expression à une forme plus simple. */ +static bool g_scan_mime_encoding_function_run_call(GScanMimeEncodingFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); + + + +/* ---------------------------------------------------------------------------------- */ +/*                        INTRODUCTION D'UNE NOUVELLE FONCTION                        */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une reconnaissance d'encodages de contenus. */ +G_DEFINE_TYPE(GScanMimeEncodingFunction, g_scan_mime_encoding_function, G_TYPE_REGISTERED_ITEM); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des reconnaissances de contenus.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_mime_encoding_function_class_init(GScanMimeEncodingFunctionClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GRegisteredItemClass *registered;       /* Version de classe parente   */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_mime_encoding_function_dispose; +    object->finalize = (GObjectFinalizeFunc)g_scan_mime_encoding_function_finalize; + +    registered = G_REGISTERED_ITEM_CLASS(klass); + +    registered->get_name = (get_registered_item_name_fc)g_scan_mime_encoding_function_get_name; +    registered->run_call = (run_registered_item_call_fc)g_scan_mime_encoding_function_run_call; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance à initialiser.                               * +*                                                                             * +*  Description : Initialise une instance de reconnaissance de contenus.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_mime_encoding_function_init(GScanMimeEncodingFunction *func) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_mime_encoding_function_dispose(GScanMimeEncodingFunction *func) +{ +    G_OBJECT_CLASS(g_scan_mime_encoding_function_parent_class)->dispose(G_OBJECT(func)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_mime_encoding_function_finalize(GScanMimeEncodingFunction *func) +{ +    G_OBJECT_CLASS(g_scan_mime_encoding_function_parent_class)->finalize(G_OBJECT(func)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Constitue une fonction de cernement d'encodages de contenus. * +*                                                                             * +*  Retour      : Fonction mise en place.                                      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GRegisteredItem *g_scan_mime_encoding_function_new(void) +{ +    GRegisteredItem *result;                /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_SCAN_MIME_ENCODING_FUNCTION, NULL); + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item = élément d'appel à consulter.                          * +*                                                                             * +*  Description : Indique le nom associé à une expression d'évaluation.        * +*                                                                             * +*  Retour      : Désignation humaine de l'expression d'évaluation.            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char *g_scan_mime_encoding_function_get_name(const GScanMimeEncodingFunction *item) +{ +    char *result;                           /* Désignation à retourner     */ + +    result = strdup("mime_encoding"); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item  = élément d'appel à consulter.                         * +*                args  = liste d'éventuels arguments fournis.                 * +*                count = taille de cette liste.                               * +*                ctx   = contexte de suivi de l'analyse courante.             * +*                scope = portée courante des variables locales.               * +*                out   = zone d'enregistrement de la résolution opérée. [OUT] * +*                                                                             * +*  Description : Réduit une expression à une forme plus simple.               * +*                                                                             * +*  Retour      : Réduction correspondante, expression déjà réduite, ou NULL.  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_scan_mime_encoding_function_run_call(GScanMimeEncodingFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out) +{ +    bool result;                            /* Bilan à retourner           */ +    magic_t cookie;                         /* Référence des bibliothèques */ +    GBinContent *content;                   /* Contenu à manipuler         */ +    vmpa2t pos;                             /* Tête de lecture             */ +    phys_t size;                            /* Quantité de données dispos. */ +    const bin_t *data;                      /* Accès à des données         */ +    const char *desc;                       /* Description du contenu      */ +    sized_string_t string;                  /* Description à diffuser      */ + +    result = (count == 0); +    if (!result) goto exit; + +    cookie = get_magic_cookie(MAGIC_MIME_ENCODING); + +    content = g_scan_context_get_content(ctx); + +    g_binary_content_compute_start_pos(content, &pos); + +    size = g_binary_content_compute_size(content); + +    data = g_binary_content_get_raw_access(content, &pos, size); + +    desc = magic_buffer(cookie, data, size); + +    if (desc != NULL) +    { +        string.data = (char *)desc; +        string.len = strlen(desc); +    } +    else +    { +        string.data = ""; +        string.len = 0; +    } + +    *out = G_OBJECT(g_scan_literal_expression_new(LVT_STRING, &string)); + +    g_object_unref(G_OBJECT(content)); + + exit: + +    return result; + +} diff --git a/src/analysis/scan/items/magic/mime-encoding.h b/src/analysis/scan/items/magic/mime-encoding.h new file mode 100644 index 0000000..9349d55 --- /dev/null +++ b/src/analysis/scan/items/magic/mime-encoding.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * mime-encoding.h - prototypes pour la reconnaissance de l'encodage d'un contenu + * + * 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_ITEMS_MAGIC_MIME_ENCODING_H +#define _ANALYSIS_SCAN_ITEMS_MAGIC_MIME_ENCODING_H + + +#include <glib-object.h> + + +#include "../../item.h" + + + +#define G_TYPE_SCAN_MIME_ENCODING_FUNCTION            g_scan_mime_encoding_function_get_type() +#define G_SCAN_MIME_ENCODING_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MIME_ENCODING_FUNCTION, GScanMimeEncodingFunction)) +#define G_IS_SCAN_MIME_ENCODING_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MIME_ENCODING_FUNCTION)) +#define G_SCAN_MIME_ENCODING_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MIME_ENCODING_FUNCTION, GScanMimeEncodingFunctionClass)) +#define G_IS_SCAN_MIME_ENCODING_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MIME_ENCODING_FUNCTION)) +#define G_SCAN_MIME_ENCODING_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MIME_ENCODING_FUNCTION, GScanMimeEncodingFunctionClass)) + + +/* Reconnaissance d'encodages de contenus (instance) */ +typedef GRegisteredItem GScanMimeEncodingFunction; + +/* Reconnaissance d'encodages de contenus (classe) */ +typedef GRegisteredItemClass GScanMimeEncodingFunctionClass; + + +/* Indique le type défini pour une reconnaissance d'encodages de contenus. */ +GType g_scan_mime_encoding_function_get_type(void); + +/* Constitue une fonction de cernement d'encodages de contenus. */ +GRegisteredItem *g_scan_mime_encoding_function_new(void); + + + +#endif  /* _ANALYSIS_SCAN_ITEMS_MAGIC_MIME_ENCODING_H */ diff --git a/src/analysis/scan/items/magic/mime-type.c b/src/analysis/scan/items/magic/mime-type.c new file mode 100644 index 0000000..95e441d --- /dev/null +++ b/src/analysis/scan/items/magic/mime-type.c @@ -0,0 +1,270 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * type.c - reconnaissance du type MIME d'un contenu + * + * 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 "mime-type.h" + + +#include "cookie.h" +#include "../../item-int.h" +#include "../../exprs/literal.h" + + + +/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */ + + +/* Initialise la classe des reconnaissances de contenus. */ +static void g_scan_mime_type_function_class_init(GScanMimeTypeFunctionClass *); + +/* Initialise une instance de reconnaissance de contenus. */ +static void g_scan_mime_type_function_init(GScanMimeTypeFunction *); + +/* Supprime toutes les références externes. */ +static void g_scan_mime_type_function_dispose(GScanMimeTypeFunction *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_mime_type_function_finalize(GScanMimeTypeFunction *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Indique le nom associé à une expression d'évaluation. */ +static char *g_scan_mime_type_function_get_name(const GScanMimeTypeFunction *); + +/* Réduit une expression à une forme plus simple. */ +static bool g_scan_mime_type_function_run_call(GScanMimeTypeFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); + + + +/* ---------------------------------------------------------------------------------- */ +/*                        INTRODUCTION D'UNE NOUVELLE FONCTION                        */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une reconnaissance de types de contenus. */ +G_DEFINE_TYPE(GScanMimeTypeFunction, g_scan_mime_type_function, G_TYPE_REGISTERED_ITEM); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des reconnaissances de contenus.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_mime_type_function_class_init(GScanMimeTypeFunctionClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GRegisteredItemClass *registered;       /* Version de classe parente   */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_mime_type_function_dispose; +    object->finalize = (GObjectFinalizeFunc)g_scan_mime_type_function_finalize; + +    registered = G_REGISTERED_ITEM_CLASS(klass); + +    registered->get_name = (get_registered_item_name_fc)g_scan_mime_type_function_get_name; +    registered->run_call = (run_registered_item_call_fc)g_scan_mime_type_function_run_call; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance à initialiser.                               * +*                                                                             * +*  Description : Initialise une instance de reconnaissance de contenus.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_mime_type_function_init(GScanMimeTypeFunction *func) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_mime_type_function_dispose(GScanMimeTypeFunction *func) +{ +    G_OBJECT_CLASS(g_scan_mime_type_function_parent_class)->dispose(G_OBJECT(func)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_mime_type_function_finalize(GScanMimeTypeFunction *func) +{ +    G_OBJECT_CLASS(g_scan_mime_type_function_parent_class)->finalize(G_OBJECT(func)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Constitue une fonction d'identification de types de contenus.* +*                                                                             * +*  Retour      : Fonction mise en place.                                      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GRegisteredItem *g_scan_mime_type_function_new(void) +{ +    GRegisteredItem *result;                /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_SCAN_MIME_TYPE_FUNCTION, NULL); + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item = élément d'appel à consulter.                          * +*                                                                             * +*  Description : Indique le nom associé à une expression d'évaluation.        * +*                                                                             * +*  Retour      : Désignation humaine de l'expression d'évaluation.            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char *g_scan_mime_type_function_get_name(const GScanMimeTypeFunction *item) +{ +    char *result;                           /* Désignation à retourner     */ + +    result = strdup("mime_type"); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item  = élément d'appel à consulter.                         * +*                args  = liste d'éventuels arguments fournis.                 * +*                count = taille de cette liste.                               * +*                ctx   = contexte de suivi de l'analyse courante.             * +*                scope = portée courante des variables locales.               * +*                out   = zone d'enregistrement de la résolution opérée. [OUT] * +*                                                                             * +*  Description : Réduit une expression à une forme plus simple.               * +*                                                                             * +*  Retour      : Réduction correspondante, expression déjà réduite, ou NULL.  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_scan_mime_type_function_run_call(GScanMimeTypeFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out) +{ +    bool result;                            /* Bilan à retourner           */ +    magic_t cookie;                         /* Référence des bibliothèques */ +    GBinContent *content;                   /* Contenu à manipuler         */ +    vmpa2t pos;                             /* Tête de lecture             */ +    phys_t size;                            /* Quantité de données dispos. */ +    const bin_t *data;                      /* Accès à des données         */ +    const char *desc;                       /* Description du contenu      */ +    sized_string_t string;                  /* Description à diffuser      */ + +    result = (count == 0); +    if (!result) goto exit; + +    cookie = get_magic_cookie(MAGIC_MIME_TYPE); + +    content = g_scan_context_get_content(ctx); + +    g_binary_content_compute_start_pos(content, &pos); + +    size = g_binary_content_compute_size(content); + +    data = g_binary_content_get_raw_access(content, &pos, size); + +    desc = magic_buffer(cookie, data, size); + +    if (desc != NULL) +    { +        string.data = (char *)desc; +        string.len = strlen(desc); +    } +    else +    { +        string.data = ""; +        string.len = 0; +    } + +    *out = G_OBJECT(g_scan_literal_expression_new(LVT_STRING, &string)); + +    g_object_unref(G_OBJECT(content)); + + exit: + +    return result; + +} diff --git a/src/analysis/scan/items/magic/mime-type.h b/src/analysis/scan/items/magic/mime-type.h new file mode 100644 index 0000000..e02ce0f --- /dev/null +++ b/src/analysis/scan/items/magic/mime-type.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * mime-type.h - prototypes pour la reconnaissance du type MIME d'un contenu + * + * 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_ITEMS_MAGIC_MIME_TYPE_H +#define _ANALYSIS_SCAN_ITEMS_MAGIC_MIME_TYPE_H + + +#include <glib-object.h> + + +#include "../../item.h" + + + +#define G_TYPE_SCAN_MIME_TYPE_FUNCTION            g_scan_mime_type_function_get_type() +#define G_SCAN_MIME_TYPE_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MIME_TYPE_FUNCTION, GScanMimeTypeFunction)) +#define G_IS_SCAN_MIME_TYPE_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MIME_TYPE_FUNCTION)) +#define G_SCAN_MIME_TYPE_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MIME_TYPE_FUNCTION, GScanMimeTypeFunctionClass)) +#define G_IS_SCAN_MIME_TYPE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MIME_TYPE_FUNCTION)) +#define G_SCAN_MIME_TYPE_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MIME_TYPE_FUNCTION, GScanMimeTypeFunctionClass)) + + +/* Reconnaissance de types de contenus (instance) */ +typedef GRegisteredItem GScanMimeTypeFunction; + +/* Reconnaissance de types de contenus (classe) */ +typedef GRegisteredItemClass GScanMimeTypeFunctionClass; + + +/* Indique le type défini pour une reconnaissance de types de contenus. */ +GType g_scan_mime_type_function_get_type(void); + +/* Constitue une fonction d'identification de types de contenus. */ +GRegisteredItem *g_scan_mime_type_function_new(void); + + + +#endif  /* _ANALYSIS_SCAN_ITEMS_MAGIC_MIME_TYPE_H */ diff --git a/src/analysis/scan/items/magic/type.c b/src/analysis/scan/items/magic/type.c new file mode 100644 index 0000000..f87c34a --- /dev/null +++ b/src/analysis/scan/items/magic/type.c @@ -0,0 +1,270 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * type.c - reconnaissance du type d'un contenu + * + * 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 "type.h" + + +#include "cookie.h" +#include "../../item-int.h" +#include "../../exprs/literal.h" + + + +/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */ + + +/* Initialise la classe des reconnaissances de contenus. */ +static void g_scan_magic_type_function_class_init(GScanMagicTypeFunctionClass *); + +/* Initialise une instance de reconnaissance de contenus. */ +static void g_scan_magic_type_function_init(GScanMagicTypeFunction *); + +/* Supprime toutes les références externes. */ +static void g_scan_magic_type_function_dispose(GScanMagicTypeFunction *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_magic_type_function_finalize(GScanMagicTypeFunction *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Indique le nom associé à une expression d'évaluation. */ +static char *g_scan_magic_type_function_get_name(const GScanMagicTypeFunction *); + +/* Réduit une expression à une forme plus simple. */ +static bool g_scan_magic_type_function_run_call(GScanMagicTypeFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); + + + +/* ---------------------------------------------------------------------------------- */ +/*                        INTRODUCTION D'UNE NOUVELLE FONCTION                        */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une reconnaissance de types de contenus. */ +G_DEFINE_TYPE(GScanMagicTypeFunction, g_scan_magic_type_function, G_TYPE_REGISTERED_ITEM); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des reconnaissances de contenus.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_magic_type_function_class_init(GScanMagicTypeFunctionClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GRegisteredItemClass *registered;       /* Version de classe parente   */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_magic_type_function_dispose; +    object->finalize = (GObjectFinalizeFunc)g_scan_magic_type_function_finalize; + +    registered = G_REGISTERED_ITEM_CLASS(klass); + +    registered->get_name = (get_registered_item_name_fc)g_scan_magic_type_function_get_name; +    registered->run_call = (run_registered_item_call_fc)g_scan_magic_type_function_run_call; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance à initialiser.                               * +*                                                                             * +*  Description : Initialise une instance de reconnaissance de contenus.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_magic_type_function_init(GScanMagicTypeFunction *func) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_magic_type_function_dispose(GScanMagicTypeFunction *func) +{ +    G_OBJECT_CLASS(g_scan_magic_type_function_parent_class)->dispose(G_OBJECT(func)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_magic_type_function_finalize(GScanMagicTypeFunction *func) +{ +    G_OBJECT_CLASS(g_scan_magic_type_function_parent_class)->finalize(G_OBJECT(func)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Constitue une fonction d'identification de types de contenus.* +*                                                                             * +*  Retour      : Fonction mise en place.                                      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GRegisteredItem *g_scan_magic_type_function_new(void) +{ +    GRegisteredItem *result;                /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_SCAN_MAGIC_TYPE_FUNCTION, NULL); + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item = élément d'appel à consulter.                          * +*                                                                             * +*  Description : Indique le nom associé à une expression d'évaluation.        * +*                                                                             * +*  Retour      : Désignation humaine de l'expression d'évaluation.            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char *g_scan_magic_type_function_get_name(const GScanMagicTypeFunction *item) +{ +    char *result;                           /* Désignation à retourner     */ + +    result = strdup("type"); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item  = élément d'appel à consulter.                         * +*                args  = liste d'éventuels arguments fournis.                 * +*                count = taille de cette liste.                               * +*                ctx   = contexte de suivi de l'analyse courante.             * +*                scope = portée courante des variables locales.               * +*                out   = zone d'enregistrement de la résolution opérée. [OUT] * +*                                                                             * +*  Description : Réduit une expression à une forme plus simple.               * +*                                                                             * +*  Retour      : Réduction correspondante, expression déjà réduite, ou NULL.  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_scan_magic_type_function_run_call(GScanMagicTypeFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out) +{ +    bool result;                            /* Bilan à retourner           */ +    magic_t cookie;                         /* Référence des bibliothèques */ +    GBinContent *content;                   /* Contenu à manipuler         */ +    vmpa2t pos;                             /* Tête de lecture             */ +    phys_t size;                            /* Quantité de données dispos. */ +    const bin_t *data;                      /* Accès à des données         */ +    const char *desc;                       /* Description du contenu      */ +    sized_string_t string;                  /* Description à diffuser      */ + +    result = (count == 0); +    if (!result) goto exit; + +    cookie = get_magic_cookie(MAGIC_NONE); + +    content = g_scan_context_get_content(ctx); + +    g_binary_content_compute_start_pos(content, &pos); + +    size = g_binary_content_compute_size(content); + +    data = g_binary_content_get_raw_access(content, &pos, size); + +    desc = magic_buffer(cookie, data, size); + +    if (desc != NULL) +    { +        string.data = (char *)desc; +        string.len = strlen(desc); +    } +    else +    { +        string.data = ""; +        string.len = 0; +    } + +    *out = G_OBJECT(g_scan_literal_expression_new(LVT_STRING, &string)); + +    g_object_unref(G_OBJECT(content)); + + exit: + +    return result; + +} diff --git a/src/analysis/scan/items/magic/type.h b/src/analysis/scan/items/magic/type.h new file mode 100644 index 0000000..bfad213 --- /dev/null +++ b/src/analysis/scan/items/magic/type.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * type.h - prototypes pour la reconnaissance du type d'un contenu + * + * 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_ITEMS_MAGIC_TYPE_H +#define _ANALYSIS_SCAN_ITEMS_MAGIC_TYPE_H + + +#include <glib-object.h> + + +#include "../../item.h" + + + +#define G_TYPE_SCAN_MAGIC_TYPE_FUNCTION            g_scan_magic_type_function_get_type() +#define G_SCAN_MAGIC_TYPE_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MAGIC_TYPE_FUNCTION, GScanMagicTypeFunction)) +#define G_IS_SCAN_MAGIC_TYPE_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MAGIC_TYPE_FUNCTION)) +#define G_SCAN_MAGIC_TYPE_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MAGIC_TYPE_FUNCTION, GScanMagicTypeFunctionClass)) +#define G_IS_SCAN_MAGIC_TYPE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MAGIC_TYPE_FUNCTION)) +#define G_SCAN_MAGIC_TYPE_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MAGIC_TYPE_FUNCTION, GScanMagicTypeFunctionClass)) + + +/* Reconnaissance de types de contenus (instance) */ +typedef GRegisteredItem GScanMagicTypeFunction; + +/* Reconnaissance de types de contenus (classe) */ +typedef GRegisteredItemClass GScanMagicTypeFunctionClass; + + +/* Indique le type défini pour une reconnaissance de types de contenus. */ +GType g_scan_magic_type_function_get_type(void); + +/* Constitue une fonction d'identification de types de contenus. */ +GRegisteredItem *g_scan_magic_type_function_new(void); + + + +#endif  /* _ANALYSIS_SCAN_ITEMS_MAGIC_TYPE_H */ diff --git a/src/analysis/scan/items/time/Makefile.am b/src/analysis/scan/items/time/Makefile.am new file mode 100644 index 0000000..e5330be --- /dev/null +++ b/src/analysis/scan/items/time/Makefile.am @@ -0,0 +1,14 @@ + +noinst_LTLIBRARIES  = libanalysisscanitemstime.la + + +libanalysisscanitemstime_la_SOURCES =		\ +	make.h make.c							\ +	now.h now.c + +libanalysisscanitemstime_la_CFLAGS = $(LIBGOBJ_CFLAGS) + + +devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) + +dev_HEADERS = $(libanalysisscanitemstime_la_SOURCES:%c=) diff --git a/src/analysis/scan/items/time/make.c b/src/analysis/scan/items/time/make.c new file mode 100644 index 0000000..477a77c --- /dev/null +++ b/src/analysis/scan/items/time/make.c @@ -0,0 +1,350 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * make.c - construction de volume de secondes à partir d'une date + * + * 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 "make.h" + + +#include <assert.h> +#include <time.h> + + +#include "../../item-int.h" +#include "../../exprs/literal.h" + + + +/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */ + + +/* Initialise la classe des conversions de dates en secondes. */ +static void g_scan_time_make_function_class_init(GScanTimeMakeFunctionClass *); + +/* Initialise une instance de convertisseur de date en secondes. */ +static void g_scan_time_make_function_init(GScanTimeMakeFunction *); + +/* Supprime toutes les références externes. */ +static void g_scan_time_make_function_dispose(GScanTimeMakeFunction *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_time_make_function_finalize(GScanTimeMakeFunction *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Indique le nom associé à une expression d'évaluation. */ +static char *g_scan_time_make_function_get_name(const GScanTimeMakeFunction *); + +/* Réduit une expression à une forme plus simple. */ +static bool g_scan_time_make_function_run_call(GScanTimeMakeFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); + + + +/* ---------------------------------------------------------------------------------- */ +/*                        INTRODUCTION D'UNE NOUVELLE FONCTION                        */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une conversion de date en nombre de secondes. */ +G_DEFINE_TYPE(GScanTimeMakeFunction, g_scan_time_make_function, G_TYPE_REGISTERED_ITEM); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des conversions de dates en secondes.   * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_time_make_function_class_init(GScanTimeMakeFunctionClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GRegisteredItemClass *registered;       /* Version de classe parente   */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_time_make_function_dispose; +    object->finalize = (GObjectFinalizeFunc)g_scan_time_make_function_finalize; + +    registered = G_REGISTERED_ITEM_CLASS(klass); + +    registered->get_name = (get_registered_item_name_fc)g_scan_time_make_function_get_name; +    registered->run_call = (run_registered_item_call_fc)g_scan_time_make_function_run_call; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance à initialiser.                               * +*                                                                             * +*  Description : Initialise une instance de convertisseur de date en secondes.* +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_time_make_function_init(GScanTimeMakeFunction *func) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_time_make_function_dispose(GScanTimeMakeFunction *func) +{ +    G_OBJECT_CLASS(g_scan_time_make_function_parent_class)->dispose(G_OBJECT(func)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_time_make_function_finalize(GScanTimeMakeFunction *func) +{ +    G_OBJECT_CLASS(g_scan_time_make_function_parent_class)->finalize(G_OBJECT(func)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Constitue une fonction de décompte du temps écoulé.          * +*                                                                             * +*  Retour      : Fonction mise en place.                                      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GRegisteredItem *g_scan_time_make_function_new(void) +{ +    GRegisteredItem *result;                /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_SCAN_TIME_MAKE_FUNCTION, NULL); + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item = élément d'appel à consulter.                          * +*                                                                             * +*  Description : Indique le nom associé à une expression d'évaluation.        * +*                                                                             * +*  Retour      : Désignation humaine de l'expression d'évaluation.            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char *g_scan_time_make_function_get_name(const GScanTimeMakeFunction *item) +{ +    char *result;                           /* Désignation à retourner     */ + +    result = strdup("make"); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item  = élément d'appel à consulter.                         * +*                args  = liste d'éventuels arguments fournis.                 * +*                count = taille de cette liste.                               * +*                ctx   = contexte de suivi de l'analyse courante.             * +*                scope = portée courante des variables locales.               * +*                out   = zone d'enregistrement de la résolution opérée. [OUT] * +*                                                                             * +*  Description : Réduit une expression à une forme plus simple.               * +*                                                                             * +*  Retour      : Réduction correspondante, expression déjà réduite, ou NULL.  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_scan_time_make_function_run_call(GScanTimeMakeFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out) +{ +    bool result;                            /* Bilan à retourner           */ +    bool status;                            /* Possibilité de construction */ +    size_t i;                               /* Boucle de parcours          */ +    LiteralValueType vtype;                 /* Type de valeur portée       */ +    struct tm date;                         /* Date à mettre en place      */ +    unsigned long long value;               /* Valeur entière à utiliser   */ +    time_t computed;                        /* Nombre de secondes déterminé*/ + +    /* Validation des arguments */ + +    result = (count == 3 || count == 6); +    if (!result) goto exit; + +    status = true; + +    for (i = 0; i < count && status; i++) +    { +        status = G_IS_SCAN_LITERAL_EXPRESSION(args[i]); +        if (!status) break; + +        vtype = g_scan_literal_expression_get_value_type(G_SCAN_LITERAL_EXPRESSION(args[i])); + +        status = (vtype == LVT_UNSIGNED_INTEGER); +        if (!status) break; + +    } + +    if (!status) goto exit; + +    /* Lecture des arguments */ + +    memset(&date, 0, sizeof(struct tm)); + +    status = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[0]), &value); +    assert(status); +    if (!status) goto exit; + +    if (value < 1900) +    { +        result = false; +        goto exit; +    } + +    date.tm_year = value - 1900; + +    status = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[1]), &value); +    assert(status); +    if (!status) goto exit; + +    if (value > 12) +    { +        result = false; +        goto exit; +    } + +    date.tm_mon = value - 1; + +    status = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[2]), &value); +    assert(status); +    if (!status) goto exit; + +    if (value < 1 || value > 31) +    { +        result = false; +        goto exit; +    } + +    date.tm_mday = value; + +    if (count == 6) +    { +        status = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[3]), &value); +        assert(status); +        if (!status) goto exit; + +        if (value >= 24) +        { +            result = false; +            goto exit; +        } + +        date.tm_hour = value; + +        status = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[4]), &value); +        assert(status); +        if (!status) goto exit; + +        if (value >= 60) +        { +            result = false; +            goto exit; +        } + +        date.tm_min = value; + +        status = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[5]), &value); +        assert(status); +        if (!status) goto exit; + +        if (value >= 60) +        { +            result = false; +            goto exit; +        } + +        date.tm_sec = value; + +    } + +    /* Construction de la valeur finale */ + +    computed = timegm(&date); + +    if (computed != (time_t)-1) +        *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ computed })); + + exit: + +    return result; + +} diff --git a/src/analysis/scan/items/time/make.h b/src/analysis/scan/items/time/make.h new file mode 100644 index 0000000..958a392 --- /dev/null +++ b/src/analysis/scan/items/time/make.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * make.h - prototypes pour une construction de volume de secondes à partir d'une date + * + * 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_ITEMS_TIME_MAKE_H +#define _ANALYSIS_SCAN_ITEMS_TIME_MAKE_H + + +#include <glib-object.h> + + +#include "../../item.h" + + + +#define G_TYPE_SCAN_TIME_MAKE_FUNCTION            g_scan_time_make_function_get_type() +#define G_SCAN_TIME_MAKE_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TIME_MAKE_FUNCTION, GScanTimeMakeFunction)) +#define G_IS_SCAN_TIME_MAKE_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TIME_MAKE_FUNCTION)) +#define G_SCAN_TIME_MAKE_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TIME_MAKE_FUNCTION, GScanTimeMakeFunctionClass)) +#define G_IS_SCAN_TIME_MAKE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TIME_MAKE_FUNCTION)) +#define G_SCAN_TIME_MAKE_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TIME_MAKE_FUNCTION, GScanTimeMakeFunctionClass)) + + +/* Convertisseur de date en nombre de secondes depuis le 01/01/1970 (instance) */ +typedef GRegisteredItem GScanTimeMakeFunction; + +/* Convertisseur de date en nombre de secondes depuis le 01/01/1970 (classe) */ +typedef GRegisteredItemClass GScanTimeMakeFunctionClass; + + +/* Indique le type défini pour une conversion de date en nombre de secondes. */ +GType g_scan_time_make_function_get_type(void); + +/* Constitue une fonction de décompte du temps écoulé. */ +GRegisteredItem *g_scan_time_make_function_new(void); + + + +#endif  /* _ANALYSIS_SCAN_ITEMS_TIME_MAKE_H */ diff --git a/src/analysis/scan/items/time/now.c b/src/analysis/scan/items/time/now.c new file mode 100644 index 0000000..16c4aef --- /dev/null +++ b/src/analysis/scan/items/time/now.c @@ -0,0 +1,243 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * now.c - décompte du temps écoulé depuis Epoch + * + * 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 "now.h" + + +#include <time.h> + + +#include "../../item-int.h" +#include "../../exprs/literal.h" + + + +/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */ + + +/* Initialise la classe des décomptes de temps écoulé. */ +static void g_scan_time_now_function_class_init(GScanTimeNowFunctionClass *); + +/* Initialise une instance de décompte de temps écoulé. */ +static void g_scan_time_now_function_init(GScanTimeNowFunction *); + +/* Supprime toutes les références externes. */ +static void g_scan_time_now_function_dispose(GScanTimeNowFunction *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_time_now_function_finalize(GScanTimeNowFunction *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Indique le nom associé à une expression d'évaluation. */ +static char *g_scan_time_now_function_get_name(const GScanTimeNowFunction *); + +/* Réduit une expression à une forme plus simple. */ +static bool g_scan_time_now_function_run_call(GScanTimeNowFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); + + + +/* ---------------------------------------------------------------------------------- */ +/*                        INTRODUCTION D'UNE NOUVELLE FONCTION                        */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un décompte de secondes écoulées depuis le 01/01/1970. */ +G_DEFINE_TYPE(GScanTimeNowFunction, g_scan_time_now_function, G_TYPE_REGISTERED_ITEM); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des décomptes de temps écoulé.          * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_time_now_function_class_init(GScanTimeNowFunctionClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GRegisteredItemClass *registered;       /* Version de classe parente   */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_time_now_function_dispose; +    object->finalize = (GObjectFinalizeFunc)g_scan_time_now_function_finalize; + +    registered = G_REGISTERED_ITEM_CLASS(klass); + +    registered->get_name = (get_registered_item_name_fc)g_scan_time_now_function_get_name; +    registered->run_call = (run_registered_item_call_fc)g_scan_time_now_function_run_call; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance à initialiser.                               * +*                                                                             * +*  Description : Initialise une instance de décompte de temps écoulé.         * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_time_now_function_init(GScanTimeNowFunction *func) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_time_now_function_dispose(GScanTimeNowFunction *func) +{ +    G_OBJECT_CLASS(g_scan_time_now_function_parent_class)->dispose(G_OBJECT(func)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_time_now_function_finalize(GScanTimeNowFunction *func) +{ +    G_OBJECT_CLASS(g_scan_time_now_function_parent_class)->finalize(G_OBJECT(func)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Constitue une fonction de décompte du temps écoulé.          * +*                                                                             * +*  Retour      : Fonction mise en place.                                      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GRegisteredItem *g_scan_time_now_function_new(void) +{ +    GRegisteredItem *result;                /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_SCAN_TIME_NOW_FUNCTION, NULL); + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item = élément d'appel à consulter.                          * +*                                                                             * +*  Description : Indique le nom associé à une expression d'évaluation.        * +*                                                                             * +*  Retour      : Désignation humaine de l'expression d'évaluation.            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char *g_scan_time_now_function_get_name(const GScanTimeNowFunction *item) +{ +    char *result;                           /* Désignation à retourner     */ + +    result = strdup("now"); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item  = élément d'appel à consulter.                         * +*                args  = liste d'éventuels arguments fournis.                 * +*                count = taille de cette liste.                               * +*                ctx   = contexte de suivi de l'analyse courante.             * +*                scope = portée courante des variables locales.               * +*                out   = zone d'enregistrement de la résolution opérée. [OUT] * +*                                                                             * +*  Description : Réduit une expression à une forme plus simple.               * +*                                                                             * +*  Retour      : Réduction correspondante, expression déjà réduite, ou NULL.  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_scan_time_now_function_run_call(GScanTimeNowFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out) +{ +    bool result;                            /* Bilan à retourner           */ +    time_t now;                             /* Date relative courante      */ + +    result = (count == 0); +    if (!result) goto exit; + +    now = time(NULL); + +    *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ now })); + + exit: + +    return result; + +} diff --git a/src/analysis/scan/items/time/now.h b/src/analysis/scan/items/time/now.h new file mode 100644 index 0000000..6b3faa2 --- /dev/null +++ b/src/analysis/scan/items/time/now.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * now.h - prototypes pour le décompte du temps écoulé depuis Epoch + * + * 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_ITEMS_TIME_NOW_H +#define _ANALYSIS_SCAN_ITEMS_TIME_NOW_H + + +#include <glib-object.h> + + +#include "../../item.h" + + + +#define G_TYPE_SCAN_TIME_NOW_FUNCTION            g_scan_time_now_function_get_type() +#define G_SCAN_TIME_NOW_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TIME_NOW_FUNCTION, GScanTimeNowFunction)) +#define G_IS_SCAN_TIME_NOW_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TIME_NOW_FUNCTION)) +#define G_SCAN_TIME_NOW_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TIME_NOW_FUNCTION, GScanTimeNowFunctionClass)) +#define G_IS_SCAN_TIME_NOW_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TIME_NOW_FUNCTION)) +#define G_SCAN_TIME_NOW_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TIME_NOW_FUNCTION, GScanTimeNowFunctionClass)) + + +/* Décompte du nombre de seccondes écoulées depuis le 01/01/1970 (instance) */ +typedef GRegisteredItem GScanTimeNowFunction; + +/* Décompte du nombre de seccondes écoulées depuis le 01/01/1970 (classe) */ +typedef GRegisteredItemClass GScanTimeNowFunctionClass; + + +/* Indique le type défini pour un décompte de secondes écoulées depuis le 01/01/1970. */ +GType g_scan_time_now_function_get_type(void); + +/* Constitue une fonction de décompte du temps écoulé. */ +GRegisteredItem *g_scan_time_now_function_new(void); + + + +#endif  /* _ANALYSIS_SCAN_ITEMS_TIME_NOW_H */ diff --git a/src/analysis/scan/items/uint-int.h b/src/analysis/scan/items/uint-int.h index 1fa83c5..972d7a0 100644 --- a/src/analysis/scan/items/uint-int.h +++ b/src/analysis/scan/items/uint-int.h @@ -2,7 +2,7 @@  /* Chrysalide - Outil d'analyse de fichiers binaires   * uint-int.h - prototypes internes pour la lecture d'un mot à partir de données binaires   * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard   *   *  This file is part of Chrysalide.   * @@ -33,7 +33,7 @@  /* Fonction conduisant à la lecture d'un mot (instance) */ -struct _GUintFunction +struct _GScanUintFunction  {      GRegisteredItem parent;                 /* A laisser en premier        */ @@ -43,7 +43,7 @@ struct _GUintFunction  };  /* Fonction conduisant à la lecture d'un mot (classe) */ -struct _GUintFunctionClass +struct _GScanUintFunctionClass  {      GRegisteredItemClass parent;            /* A laisser en premier        */ @@ -51,7 +51,7 @@ struct _GUintFunctionClass  /* Met en place un nouvelle fonction de lecture d'entiers. */ -bool g_uint_function_create(GUintFunction *, MemoryDataSize); +bool g_scan_uint_function_create(GScanUintFunction *, MemoryDataSize, SourceEndian); diff --git a/src/analysis/scan/items/uint.c b/src/analysis/scan/items/uint.c index 4fea494..66c7fa9 100644 --- a/src/analysis/scan/items/uint.c +++ b/src/analysis/scan/items/uint.c @@ -2,7 +2,7 @@  /* Chrysalide - Outil d'analyse de fichiers binaires   * uint.c - lecture d'un mot à partir de données binaires   * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard   *   *  This file is part of Chrysalide.   * @@ -29,6 +29,7 @@  #include "uint-int.h"  #include "../exprs/literal.h" +#include "../../../common/extstr.h" @@ -36,16 +37,16 @@  /* Initialise la classe des lectures de valeurs entières. */ -static void g_uint_function_class_init(GUintFunctionClass *); +static void g_scan_uint_function_class_init(GScanUintFunctionClass *);  /* Initialise une instance de lecture de valeur entière. */ -static void g_uint_function_init(GUintFunction *); +static void g_scan_uint_function_init(GScanUintFunction *);  /* Supprime toutes les références externes. */ -static void g_uint_function_dispose(GUintFunction *); +static void g_scan_uint_function_dispose(GScanUintFunction *);  /* Procède à la libération totale de la mémoire. */ -static void g_uint_function_finalize(GUintFunction *); +static void g_scan_uint_function_finalize(GScanUintFunction *); @@ -53,10 +54,10 @@ static void g_uint_function_finalize(GUintFunction *);  /* Indique le nom associé à une expression d'évaluation. */ -static char *g_uint_function_get_name(const GUintFunction *); +static char *g_scan_uint_function_get_name(const GScanUintFunction *);  /* Réduit une expression à une forme plus simple. */ -static bool g_uint_function_run_call(GUintFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); +static bool g_scan_uint_function_run_call(GScanUintFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); @@ -66,7 +67,7 @@ static bool g_uint_function_run_call(GUintFunction *, GScanExpression **, size_t  /* Indique le type défini pour une lecture de mot à partir de données binaires. */ -G_DEFINE_TYPE(GUintFunction, g_uint_function, G_TYPE_REGISTERED_ITEM); +G_DEFINE_TYPE(GScanUintFunction, g_scan_uint_function, G_TYPE_REGISTERED_ITEM);  /****************************************************************************** @@ -81,20 +82,20 @@ G_DEFINE_TYPE(GUintFunction, g_uint_function, G_TYPE_REGISTERED_ITEM);  *                                                                             *  ******************************************************************************/ -static void g_uint_function_class_init(GUintFunctionClass *klass) +static void g_scan_uint_function_class_init(GScanUintFunctionClass *klass)  {      GObjectClass *object;                   /* Autre version de la classe  */      GRegisteredItemClass *registered;       /* Version de classe parente   */      object = G_OBJECT_CLASS(klass); -    object->dispose = (GObjectFinalizeFunc/* ! */)g_uint_function_dispose; -    object->finalize = (GObjectFinalizeFunc)g_uint_function_finalize; +    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_uint_function_dispose; +    object->finalize = (GObjectFinalizeFunc)g_scan_uint_function_finalize;      registered = G_REGISTERED_ITEM_CLASS(klass); -    registered->get_name = (get_registered_item_name_fc)g_uint_function_get_name; -    registered->run_call = (run_registered_item_call_fc)g_uint_function_run_call; +    registered->get_name = (get_registered_item_name_fc)g_scan_uint_function_get_name; +    registered->run_call = (run_registered_item_call_fc)g_scan_uint_function_run_call;  } @@ -111,7 +112,7 @@ static void g_uint_function_class_init(GUintFunctionClass *klass)  *                                                                             *  ******************************************************************************/ -static void g_uint_function_init(GUintFunction *func) +static void g_scan_uint_function_init(GScanUintFunction *func)  {      func->size = MDS_UNDEFINED;      func->endian = SRE_LITTLE; @@ -131,9 +132,9 @@ static void g_uint_function_init(GUintFunction *func)  *                                                                             *  ******************************************************************************/ -static void g_uint_function_dispose(GUintFunction *func) +static void g_scan_uint_function_dispose(GScanUintFunction *func)  { -    G_OBJECT_CLASS(g_uint_function_parent_class)->dispose(G_OBJECT(func)); +    G_OBJECT_CLASS(g_scan_uint_function_parent_class)->dispose(G_OBJECT(func));  } @@ -150,9 +151,9 @@ static void g_uint_function_dispose(GUintFunction *func)  *                                                                             *  ******************************************************************************/ -static void g_uint_function_finalize(GUintFunction *func) +static void g_scan_uint_function_finalize(GScanUintFunction *func)  { -    G_OBJECT_CLASS(g_uint_function_parent_class)->finalize(G_OBJECT(func)); +    G_OBJECT_CLASS(g_scan_uint_function_parent_class)->finalize(G_OBJECT(func));  } @@ -169,13 +170,13 @@ static void g_uint_function_finalize(GUintFunction *func)  *                                                                             *  ******************************************************************************/ -GUintFunction *g_uint_function_new(MemoryDataSize size) +GRegisteredItem *g_scan_uint_function_new(MemoryDataSize size, SourceEndian endian)  { -    GUintFunction *result;                  /* Structure à retourner       */ +    GRegisteredItem *result;                /* Structure à retourner       */ -    result = g_object_new(G_TYPE_UINT_FUNCTION, NULL); +    result = g_object_new(G_TYPE_SCAN_UINT_FUNCTION, NULL); -    if (!g_uint_function_create(result, size)) +    if (!g_scan_uint_function_create(G_SCAN_UINT_FUNCTION(result), size, endian))          g_clear_object(&result);      return result; @@ -196,13 +197,14 @@ GUintFunction *g_uint_function_new(MemoryDataSize size)  *                                                                             *  ******************************************************************************/ -bool g_uint_function_create(GUintFunction *func, MemoryDataSize size) +bool g_scan_uint_function_create(GScanUintFunction *func, MemoryDataSize size, SourceEndian endian)  {      bool result;                            /* Bilan à retourner           */      result = true;      func->size = size; +    func->endian = endian;      return result; @@ -227,26 +229,26 @@ bool g_uint_function_create(GUintFunction *func, MemoryDataSize size)  *                                                                             *  ******************************************************************************/ -static char *g_uint_function_get_name(const GUintFunction *item) +static char *g_scan_uint_function_get_name(const GScanUintFunction *item)  {      char *result;                           /* Désignation à retourner     */ -    switch (item->size) +    switch (item->size & ~MDS_SIGN)      {          case MDS_8_BITS_UNSIGNED: -            result = strdup("uint8"); +            result = strdup("int8");              break;          case MDS_16_BITS_UNSIGNED: -            result = strdup("uint16"); +            result = strdup("int16");              break;          case MDS_32_BITS_UNSIGNED: -            result = strdup("uint32"); +            result = strdup("int32");              break;          case MDS_64_BITS_UNSIGNED: -            result = strdup("uint64"); +            result = strdup("int64");              break;          default: @@ -256,6 +258,16 @@ static char *g_uint_function_get_name(const GUintFunction *item)      } +    if (result) +    { +        if (!MDS_IS_SIGNED(item->size)) +            result = strprep(result, "u"); + +        if (item->endian == SRE_BIG) +            result = stradd(result, "be"); + +    } +      return result;  } @@ -278,21 +290,25 @@ static char *g_uint_function_get_name(const GUintFunction *item)  *                                                                             *  ******************************************************************************/ -static bool g_uint_function_run_call(GUintFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out) +static bool g_scan_uint_function_run_call(GScanUintFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)  {      bool result;                            /* Bilan à retourner           */      unsigned long long offset;              /* Position du mot ciblé       */      GBinContent *content;                   /* Contenu à manipuler         */      vmpa2t pos;                             /* Tête de lecture             */ -    uint8_t val_8;                          /* Valeur entière sur 8 bits   */ -    uint16_t val_16;                        /* Valeur entière sur 16 bits  */ -    uint32_t val_32;                        /* Valeur entière sur 32 bits  */ -    uint64_t val_64;                        /* Valeur entière sur 64 bits  */ - -    result = (count == 1 && G_IS_LITERAL_EXPRESSION(args[0])); +    uint8_t val_s8;                          /* Valeur entière sur 8 bits   */ +    uint8_t val_u8;                          /* Valeur entière sur 8 bits   */ +    uint16_t val_s16;                        /* Valeur entière sur 16 bits  */ +    uint16_t val_u16;                        /* Valeur entière sur 16 bits  */ +    uint32_t val_s32;                        /* Valeur entière sur 32 bits  */ +    uint32_t val_u32;                        /* Valeur entière sur 32 bits  */ +    uint64_t val_s64;                        /* Valeur entière sur 64 bits  */ +    uint64_t val_u64;                        /* Valeur entière sur 64 bits  */ + +    result = (count == 1 && G_IS_SCAN_LITERAL_EXPRESSION(args[0]));      if (!result) goto exit; -    result = g_literal_expression_get_integer_value(G_LITERAL_EXPRESSION(args[0]), &offset); +    result = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[0]), &offset);      if (!result) goto exit;      content = g_scan_context_get_content(ctx); @@ -302,29 +318,60 @@ static bool g_uint_function_run_call(GUintFunction *item, GScanExpression **args      switch (item->size)      { +        case MDS_8_BITS_SIGNED: +            result = g_binary_content_read_s8(content, &pos, &val_s8); +            if (result) +                *out = G_OBJECT(g_scan_literal_expression_new(LVT_SIGNED_INTEGER, +                                                              (long long []){ val_s8 })); +            break; +          case MDS_8_BITS_UNSIGNED: -            result = g_binary_content_read_u8(content, &pos, &val_8); +            result = g_binary_content_read_u8(content, &pos, &val_u8);              if (result) -                *out = G_OBJECT(g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_8 })); +                *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, +                                                              (unsigned long long []){ val_u8 })); +            break; + +        case MDS_16_BITS_SIGNED: +            result = g_binary_content_read_s16(content, &pos, item->endian, &val_s16); +            if (result) +                *out = G_OBJECT(g_scan_literal_expression_new(LVT_SIGNED_INTEGER, +                                                              (long long []){ val_s16 }));              break;          case MDS_16_BITS_UNSIGNED: -            result = g_binary_content_read_u16(content, &pos, item->endian, &val_16); +            result = g_binary_content_read_u16(content, &pos, item->endian, &val_u16);              if (result) -                *out = G_OBJECT(g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_16 })); +                *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, +                                                              (unsigned long long []){ val_u16 })); +            break; + +        case MDS_32_BITS_SIGNED: +            result = g_binary_content_read_s32(content, &pos, item->endian, &val_s32); +            if (result) +                *out = G_OBJECT(g_scan_literal_expression_new(LVT_SIGNED_INTEGER, +                                                              (long long []){ val_s32 }));              break;          case MDS_32_BITS_UNSIGNED: -            result = g_binary_content_read_u32(content, &pos, item->endian, &val_32); +            result = g_binary_content_read_u32(content, &pos, item->endian, &val_u32);              if (result) -                *out = G_OBJECT(g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_32 })); +                *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, +                                                              (unsigned long long []){ val_u32 }));              break; +        case MDS_64_BITS_SIGNED: +            result = g_binary_content_read_s64(content, &pos, item->endian, &val_s64); +            if (result) +                *out = G_OBJECT(g_scan_literal_expression_new(LVT_SIGNED_INTEGER, +                                                              (long long []){ val_s64 })); +            break;          case MDS_64_BITS_UNSIGNED: -            result = g_binary_content_read_u64(content, &pos, item->endian, &val_64); +            result = g_binary_content_read_u64(content, &pos, item->endian, &val_u64);              if (result) -                *out = G_OBJECT(g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_64 })); +                *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, +                                                              (unsigned long long []){ val_u64 }));              break;          default: diff --git a/src/analysis/scan/items/uint.h b/src/analysis/scan/items/uint.h index 60f2975..abc2231 100644 --- a/src/analysis/scan/items/uint.h +++ b/src/analysis/scan/items/uint.h @@ -2,7 +2,7 @@  /* Chrysalide - Outil d'analyse de fichiers binaires   * uint.h - prototypes pour la lecture d'un mot à partir de données binaires   * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard   *   *  This file is part of Chrysalide.   * @@ -28,30 +28,31 @@  #include <glib-object.h> +#include "../item.h"  #include "../../../arch/archbase.h" -#define G_TYPE_UINT_FUNCTION            g_uint_function_get_type() -#define G_UINT_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_UINT_FUNCTION, GUintFunction)) -#define G_IS_UINT_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_UINT_FUNCTION)) -#define G_UINT_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_UINT_FUNCTION, GUintFunctionClass)) -#define G_IS_UINT_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_UINT_FUNCTION)) -#define G_UINT_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_UINT_FUNCTION, GUintFunctionClass)) +#define G_TYPE_SCAN_UINT_FUNCTION            g_scan_uint_function_get_type() +#define G_SCAN_UINT_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_UINT_FUNCTION, GScanUintFunction)) +#define G_IS_SCAN_UINT_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_UINT_FUNCTION)) +#define G_SCAN_UINT_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_UINT_FUNCTION, GScanUintFunctionClass)) +#define G_IS_SCAN_UINT_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_UINT_FUNCTION)) +#define G_SCAN_UINT_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_UINT_FUNCTION, GScanUintFunctionClass))  /* Fonction conduisant à la lecture d'un mot (instance) */ -typedef struct _GUintFunction GUintFunction; +typedef struct _GScanUintFunction GScanUintFunction;  /* Fonction conduisant à la lecture d'un mot (classe) */ -typedef struct _GUintFunctionClass GUintFunctionClass; +typedef struct _GScanUintFunctionClass GScanUintFunctionClass;  /* Indique le type défini pour une lecture de mot à partir de données binaires. */ -GType g_uint_function_get_type(void); +GType g_scan_uint_function_get_type(void);  /* Constitue une fonction de lecture de valeur entière. */ -GUintFunction *g_uint_function_new(MemoryDataSize); +GRegisteredItem *g_scan_uint_function_new(MemoryDataSize, SourceEndian); diff --git a/src/analysis/scan/rule-int.h b/src/analysis/scan/rule-int.h index b43c20b..cc10b08 100644 --- a/src/analysis/scan/rule-int.h +++ b/src/analysis/scan/rule-int.h @@ -38,6 +38,7 @@ struct _GScanRule      GObject parent;                         /* A laisser en premier        */      char *name;                             /* Désignation de la règle     */ +    fnv64_t name_hash;                      /* Empreinte de la désignation */      GSearchPattern **data_locals;           /* Variables de données        */      size_t data_allocated;                  /* Taille allouée du tableau   */ diff --git a/src/analysis/scan/rule.c b/src/analysis/scan/rule.c index bf37585..6ca97ab 100644 --- a/src/analysis/scan/rule.c +++ b/src/analysis/scan/rule.c @@ -91,6 +91,7 @@ static void g_scan_rule_class_init(GScanRuleClass *klass)  static void g_scan_rule_init(GScanRule *rule)  {      rule->name = NULL; +    rule->name_hash = 0;      rule->data_locals = NULL;      rule->data_allocated = 0; @@ -168,6 +169,33 @@ GScanRule *g_scan_rule_new(const char *name)      result = g_object_new(G_TYPE_SCAN_RULE, NULL);      result->name = strdup(name); +    result->name_hash = fnv_64a_hash(name); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : rule = règle de détection à compléter.                       * +*                hash = empreinte précalculée associée au nom. [OUT]          * +*                                                                             * +*  Description : Indique le nom associé à une règle de détection.             * +*                                                                             * +*  Retour      : Désignation humaine associée à la règle.                     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +const char *g_scan_rule_get_name(const GScanRule *rule, fnv64_t *hash) +{ +    const char *result;                     /* Désignation à retourner     */ + +    result = rule->name; + +    *hash = rule->name_hash;      return result; diff --git a/src/analysis/scan/rule.h b/src/analysis/scan/rule.h index e240da9..12a435c 100644 --- a/src/analysis/scan/rule.h +++ b/src/analysis/scan/rule.h @@ -33,6 +33,7 @@  #include "pattern.h"  #include "expr.h"  #include "patterns/backend.h" +#include "../../common/fnv1a.h" @@ -57,6 +58,9 @@ GType g_scan_rule_get_type(void);  /* Crée une règle de détection statique à l'aide de motifs. */  GScanRule *g_scan_rule_new(const char *); +/* Indique le nom associé à une règle de détection. */ +const char *g_scan_rule_get_name(const GScanRule *, fnv64_t *); +  /* Intègre une nouvelle variable locale à une règle. */  void g_scan_rule_add_local_variable(GScanRule *, GSearchPattern *); diff --git a/src/analysis/scan/scanner-int.h b/src/analysis/scan/scanner-int.h index 54b4f62..4fcda87 100644 --- a/src/analysis/scan/scanner-int.h +++ b/src/analysis/scan/scanner-int.h @@ -37,6 +37,8 @@ struct _GContentScanner  {      GObject parent;                         /* A laisser en premier        */ +    char *filename;                         /* Eventuel fichier d'origine  */ +      GScanRule **rules;                      /* Règles de détection         */      size_t rule_count;                      /* Nombre de ces règles        */ diff --git a/src/analysis/scan/scanner.c b/src/analysis/scan/scanner.c index d52c0fc..ce8d677 100644 --- a/src/analysis/scan/scanner.c +++ b/src/analysis/scan/scanner.c @@ -25,11 +25,15 @@  #include <assert.h> +#include <libgen.h> +#include <malloc.h>  #include "decl.h"  #include "scanner-int.h"  #include "../contents/file.h" +#include "../../common/extstr.h" +#include "../../core/logs.h" @@ -45,6 +49,9 @@ static void g_content_scanner_dispose(GContentScanner *);  /* Procède à la libération totale de la mémoire. */  static void g_content_scanner_finalize(GContentScanner *); +/* Intègre une nouvelle règle de détection. */ +static bool _g_content_scanner_add_rule(GContentScanner *, GScanRule *); +  /* Indique le type défini pour une recherche dans du binaire. */ @@ -89,6 +96,8 @@ static void g_content_scanner_class_init(GContentScannerClass *klass)  static void g_content_scanner_init(GContentScanner *scanner)  { +    scanner->filename = NULL; +      scanner->rules = NULL;      scanner->rule_count = 0; @@ -137,6 +146,9 @@ static void g_content_scanner_dispose(GContentScanner *scanner)  static void g_content_scanner_finalize(GContentScanner *scanner)  { +    if (scanner->filename != NULL) +        free(scanner->filename); +      if (scanner->rules != NULL)          free(scanner->rules); @@ -250,6 +262,8 @@ bool g_content_scanner_create_from_file(GContentScanner *scanner, const char *fi      content = g_file_content_new(filename);      if (content == NULL) goto no_content; +    scanner->filename = strdup(filename); +      size = g_binary_content_compute_size(content);      g_binary_content_compute_start_pos(content, &start); @@ -268,25 +282,187 @@ bool g_content_scanner_create_from_file(GContentScanner *scanner, const char *fi  /******************************************************************************  *                                                                             * +*  Paramètres  : scanner = scanner de contenus à consulter.                   * +*                                                                             * +*  Description : Indique le chemin d'un éventuel fichier de source.           * +*                                                                             * +*  Retour      : Chemin d'un éventuel fichier de définitions ou NULL.         * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +const char *g_content_scanner_get_filename(const GContentScanner *scanner) +{ +    const char *result;                     /* Chemin à retourner          */ + +    result = scanner->filename; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : scanner = gestionnaire de recherche à compléter.             * +*                path    = chemin vers une définition de règles à intégrer.   * +*                                                                             * +*  Description : Inclut les définitions d'un fichier de règles externe.       * +*                                                                             * +*  Retour      : Bilan de l'inclusion à retourner.                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_content_scanner_include_resource(GContentScanner *scanner, const char *path) +{ +    bool result;                            /* Bilan à retourner           */ +    GContentScanner *included;              /* Définition à inclure        */ +    char *tmp;                              /* Copie de travail            */ +    char *filename;                         /* Chemin d'accès reconstruit  */ +    size_t i;                               /* Boucle de parcours          */ +    const char *inc_name;                   /* Nom de la nouvelle règle    */ + +    /* Cas le plus simple : un chemin absolu */ +    if (path[0] == '/') +        included = g_content_scanner_new_from_file(path); + +    /* Chemin relatif à l'emplacement de la définition courante ? */ +    else if (scanner->filename != NULL) +    { +        tmp = strdup(scanner->filename); + +        filename = strdup(dirname(tmp)); +        filename = stradd(filename, G_DIR_SEPARATOR_S); +        filename = stradd(filename, path); + +        included = g_content_scanner_new_from_file(filename); + +        free(filename); +        free(tmp); + +    } + +    else +        included = NULL; + +    /* Inclusion des règles chargées */ + +    result = (included != NULL); + +    if (result) +    { +        for (i = 0; i < included->rule_count && result; i++) +        { +            result = _g_content_scanner_add_rule(scanner, included->rules[i]); + +            if (!result) +            { +                inc_name = g_scan_rule_get_name(included->rules[i], (fnv64_t []) { 0 }); + +                log_variadic_message(LMT_ERROR, "Can not import from '%s': rule '%s' already exists!", +                                     path, inc_name); + +            } + +        } + +        g_object_unref(G_OBJECT(included)); + +    } + +    return result; + + + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : scanner = gestionnaire de recherche à compléter.             *  *                rule    = règle de détection à intégrer.                     *  *                                                                             *  *  Description : Intègre une nouvelle règle de détection.                     *  *                                                                             * -*  Retour      : -                                                            * +*  Retour      : Bilan de l'ajout à retourner.                                *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -void g_content_scanner_add_rule(GContentScanner *scanner, GScanRule *rule) +static bool _g_content_scanner_add_rule(GContentScanner *scanner, GScanRule *rule)  { +    bool result;                            /* Bilan à retourner           */ +    const char *inc_name;                   /* Nom de la nouvelle règle    */ +    fnv64_t inc_hash;                       /* Empreinte de ce nom         */ +    size_t i;                               /* Boucle de parcours          */ +    const char *cur_name;                   /* Nom d'une règle en place    */ +    fnv64_t cur_hash;                       /* Empreinte de ce nom         */ + +    result = false; + +    inc_name = g_scan_rule_get_name(rule, &inc_hash); + +    for (i = 0; i < scanner->rule_count; i++) +    { +        cur_name = g_scan_rule_get_name(scanner->rules[i], &cur_hash); + +        if (inc_hash != cur_hash) +            continue; + +        if (strcmp(inc_name, cur_name) == 0) +            goto exit_add; + +    } + +    result = true; +      scanner->rules = realloc(scanner->rules, ++scanner->rule_count * sizeof(GScanRule *));      scanner->rules[scanner->rule_count - 1] = rule;      g_object_ref(G_OBJECT(rule)); + exit_add: + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : scanner = gestionnaire de recherche à compléter.             * +*                rule    = règle de détection à intégrer.                     * +*                                                                             * +*  Description : Intègre une nouvelle règle de détection.                     * +*                                                                             * +*  Retour      : Bilan de l'ajout à retourner.                                * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_content_scanner_add_rule(GContentScanner *scanner, GScanRule *rule) +{ +    bool result;                            /* Bilan à retourner           */ +    const char *inc_name;                   /* Nom de la nouvelle règle    */ + +    result = _g_content_scanner_add_rule(scanner, rule); + +    if (!result) +    { +        inc_name = g_scan_rule_get_name(rule, (fnv64_t []) { 0 }); + +        log_variadic_message(LMT_ERROR, "Can not add rule: '%s' already exists!", inc_name); + +    } + +    return result; +  } diff --git a/src/analysis/scan/scanner.h b/src/analysis/scan/scanner.h index 8a3919a..f838344 100644 --- a/src/analysis/scan/scanner.h +++ b/src/analysis/scan/scanner.h @@ -59,19 +59,18 @@ GContentScanner *g_content_scanner_new_from_text(const char *);  /* Prépare une recherche de motifs dans du contenu binaire. */  GContentScanner *g_content_scanner_new_from_file(const char *); +/* Indique le chemin d'un éventuel fichier de source. */ +const char *g_content_scanner_get_filename(const GContentScanner *); + +/* Inclut les définitions d'un fichier de règles externe. */ +bool g_content_scanner_include_resource(GContentScanner *, const char *); +  /* Intègre une nouvelle règle de détection. */ -void g_content_scanner_add_rule(GContentScanner *, GScanRule *); +bool g_content_scanner_add_rule(GContentScanner *, GScanRule *);  /* Définit l'expression d'une correspondance recherchée. */  GScanContext *g_content_scanner_analyze(GContentScanner *, GScanOptions *, GBinContent *); - - -/* Lance une analyse d'un élément, fichier ou répertoire. */ -//void g_content_scanner_analyze(GContentScanner *, const char *); - - -  #endif  /* _ANALYSIS_SCAN_SCANNER_H */ diff --git a/src/analysis/scan/tokens.l b/src/analysis/scan/tokens.l index b541786..f3dbc79 100644 --- a/src/analysis/scan/tokens.l +++ b/src/analysis/scan/tokens.l @@ -82,6 +82,7 @@  %option yylineno  %option never-interactive +%x include_path  %x rule_intro  %x raw_block @@ -105,6 +106,14 @@ +"include"                       { PUSH_STATE(include_path); return INCLUDE; } + +<include_path>"\""              { +                                    POP_STATE; +                                    *used = 0; +                                    PUSH_STATE(strlit); +                                } +  "rule"                          { PUSH_STATE(rule_intro); return RAW_RULE; }  <rule_intro>[A-Za-z0-9_]+       { @@ -116,8 +125,8 @@  <rule_intro>[ \t]*              {  }  <rule_intro>"{"                 { POP_STATE; PUSH_STATE(raw_block); return BRACE_IN; } -<raw_block>"strings"            { PUSH_STATE(strings); PUSH_STATE(wait_for_colon); return STRINGS; } -<raw_block,strings>"condition"          { PUSH_STATE(condition); PUSH_STATE(wait_for_colon); return CONDITION; } +<raw_block>"strings"            { POP_STATE; PUSH_STATE(strings); PUSH_STATE(wait_for_colon); return STRINGS; } +<raw_block,strings>"condition"          { POP_STATE; PUSH_STATE(condition); PUSH_STATE(wait_for_colon); return CONDITION; } @@ -127,8 +136,11 @@  <condition>"true"               { return TRUE_; }  <condition>"false"              { return FALSE_; } -<condition>(0|[1-9][0-9]*)      { yylval->integer = strtoull(yytext, NULL, 10); return INTEGER; } -<condition>0x[0-9a-f]+          { yylval->integer = strtoull(yytext, NULL, 16); return INTEGER; } +<condition>-(0|[1-9][0-9]*)     { yylval->signed_integer = strtoll(yytext, NULL, 10); return SIGNED_INTEGER; } +<condition>-0x[0-9a-f]+         { yylval->signed_integer = strtoll(yytext, NULL, 16); return SIGNED_INTEGER; } + +<condition>(0|[1-9][0-9]*)      { yylval->unsigned_integer = strtoull(yytext, NULL, 10); return UNSIGNED_INTEGER; } +<condition>0x[0-9a-f]+          { yylval->unsigned_integer = strtoull(yytext, NULL, 16); return UNSIGNED_INTEGER; }  <condition>[kK][bB]             { return KB; }  <condition>[mM][bB]             { return MB; } @@ -141,8 +153,6 @@  <strlit>"\""                    {                                      POP_STATE;  -                                    EXTEND_BUFFER_IF_NEEDED(1); -                                    (*buf)[(*used)++] = '\0';                                      yylval->sized_cstring.data = *buf;                                      yylval->sized_cstring.len = *used;                                      return STRING; @@ -195,7 +205,7 @@  <condition>"+"                  { return PLUS; }  <condition>"-"                  { return MINUS; }  <condition>"*"                  { return MUL; } -<condition>"\\"                 { return DIV; } +<condition>"/"                  { return DIV; }  <condition>"%"                  { return MOD; }  <condition>"("                  { return PAREN_O; } @@ -208,6 +218,7 @@  <condition>"all"                { return ALL; }  <condition>"of"                 { return OF; }  <condition>"them"               { return THEM; } +<condition>"in"                 { return IN; }  <strings,condition>$[A-Za-z0-9_]* { @@ -215,6 +226,21 @@                                      yylval->sized_cstring.len = yyleng - 1;                                      return IDENTIFIER;                                  } + +<condition>$[A-Za-z_][A-Za-z0-9_]* { +                                    yylval->sized_cstring.data = yytext + 1; +                                    yylval->sized_cstring.len = yyleng - 1; +                                    return BYTES_ID; +                                } + +<condition>#[A-Za-z_][A-Za-z0-9_]* { +                                    yylval->sized_cstring.data = yytext + 1; +                                    yylval->sized_cstring.len = yyleng - 1; +                                    return BYTES_ID_COUNTER; +                                } + + +  <condition>[A-Za-z_][A-Za-z0-9_]* {                                      yylval->sized_cstring.data = yytext;                                      yylval->sized_cstring.len = yyleng;  | 
