diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2023-08-06 16:54:57 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2023-08-06 16:54:57 (GMT) |
commit | 4fcc35a52ccb025b6d803d85e017931cd2452960 (patch) | |
tree | e95920f16c273e41f9cae1ea2f02571c221a514e /src/analysis/scan/context.c | |
parent | 74d062d4ec55d7ac3914bbf64b8b6c5ab52227df (diff) |
Extend the ROST grammar with a first batch of new features.
Diffstat (limited to 'src/analysis/scan/context.c')
-rw-r--r-- | src/analysis/scan/context.c | 325 |
1 files changed, 302 insertions, 23 deletions
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) { |