summaryrefslogtreecommitdiff
path: root/src/analysis
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2024-01-21 22:36:47 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2024-01-21 22:36:47 (GMT)
commit0ff1e52622828663d01f98c97f2cd8eccb8facf8 (patch)
tree88b5fcf2412f863276876d0b8ad8db91903f3758 /src/analysis
parent0fac40d5a5752e8d7b92f57ea3cfa089f13a2d1f (diff)
Refactor the scan match storage.
Diffstat (limited to 'src/analysis')
-rw-r--r--src/analysis/scan/Makefile.am4
-rw-r--r--src/analysis/scan/context-int.h31
-rw-r--r--src/analysis/scan/context.c374
-rw-r--r--src/analysis/scan/context.h34
-rw-r--r--src/analysis/scan/exprs/handler.c55
-rw-r--r--src/analysis/scan/exprs/handler.h4
-rw-r--r--src/analysis/scan/exprs/setcounter.c15
-rw-r--r--src/analysis/scan/items/modpath.c7
-rw-r--r--src/analysis/scan/match.h71
-rw-r--r--src/analysis/scan/matches-int.h (renamed from src/analysis/scan/match-int.h)35
-rw-r--r--src/analysis/scan/matches.c (renamed from src/analysis/scan/match.c)145
-rw-r--r--src/analysis/scan/matches.h74
-rw-r--r--src/analysis/scan/matches/Makefile.am4
-rw-r--r--src/analysis/scan/matches/area.c57
-rw-r--r--src/analysis/scan/matches/area.h85
-rw-r--r--src/analysis/scan/matches/bytes-int.h31
-rw-r--r--src/analysis/scan/matches/bytes.c595
-rw-r--r--src/analysis/scan/matches/bytes.h58
-rw-r--r--src/analysis/scan/matches/pending.c150
-rw-r--r--src/analysis/scan/matches/pending.h11
-rw-r--r--src/analysis/scan/pattern.c2
-rw-r--r--src/analysis/scan/patterns/Makefile.am1
-rw-r--r--src/analysis/scan/patterns/backend-int.h14
-rw-r--r--src/analysis/scan/patterns/backend.c61
-rw-r--r--src/analysis/scan/patterns/backend.h8
-rw-r--r--src/analysis/scan/patterns/backends/acism-int.h13
-rw-r--r--src/analysis/scan/patterns/backends/acism.c174
-rw-r--r--src/analysis/scan/patterns/backends/bitap.c12
-rw-r--r--src/analysis/scan/patterns/patid.h36
-rw-r--r--src/analysis/scan/patterns/token.c176
-rw-r--r--src/analysis/scan/patterns/token.h9
-rw-r--r--src/analysis/scan/patterns/tokens/atom.c103
-rw-r--r--src/analysis/scan/patterns/tokens/atom.h27
-rw-r--r--src/analysis/scan/patterns/tokens/node-int.h33
-rw-r--r--src/analysis/scan/patterns/tokens/node.c195
-rw-r--r--src/analysis/scan/patterns/tokens/node.h55
-rw-r--r--src/analysis/scan/patterns/tokens/nodes/any.c461
-rw-r--r--src/analysis/scan/patterns/tokens/nodes/choice.c342
-rw-r--r--src/analysis/scan/patterns/tokens/nodes/masked-int.h5
-rw-r--r--src/analysis/scan/patterns/tokens/nodes/masked.c735
-rw-r--r--src/analysis/scan/patterns/tokens/nodes/masked.h9
-rw-r--r--src/analysis/scan/patterns/tokens/nodes/not.c98
-rw-r--r--src/analysis/scan/patterns/tokens/nodes/plain.c902
-rw-r--r--src/analysis/scan/patterns/tokens/nodes/sequence.c116
-rw-r--r--src/analysis/scan/patterns/tokens/offset.c86
-rw-r--r--src/analysis/scan/patterns/tokens/offset.h12
-rw-r--r--src/analysis/scan/rule.c80
-rw-r--r--src/analysis/scan/rule.h3
-rw-r--r--src/analysis/scan/scanner.c51
49 files changed, 3903 insertions, 1756 deletions
diff --git a/src/analysis/scan/Makefile.am b/src/analysis/scan/Makefile.am
index d24f4a8..ed4f8c7 100644
--- a/src/analysis/scan/Makefile.am
+++ b/src/analysis/scan/Makefile.am
@@ -26,8 +26,8 @@ libanalysisscan_la_SOURCES = \
expr.h expr.c \
item-int.h \
item.h item.c \
- match-int.h \
- match.h match.c \
+ matches-int.h \
+ matches.h matches.c \
options-int.h \
options.h options.c \
pattern-int.h \
diff --git a/src/analysis/scan/context-int.h b/src/analysis/scan/context-int.h
index 613ca73..efbd24e 100644
--- a/src/analysis/scan/context-int.h
+++ b/src/analysis/scan/context-int.h
@@ -33,28 +33,6 @@
-#define ALLOCATION_STEP 10
-
-/* Mémorisation des correspondances partielles */
-typedef struct _atom_match_tracker_t
-{
- phys_t *matches; /* Correspondances à confirmer */
- size_t allocated; /* Taille du talbeau préparé */
- size_t used; /* Nombre d'éléments présents */
-
-} atom_match_tracker_t;
-
-/* 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
{
@@ -76,13 +54,10 @@ struct _GScanContext
GBinContent *content; /* Contenu binaire traité */
bool scan_done; /* Phase d'analyse terminée ? */
- patid_t next_patid; /* Prochain indice utilisable */
-
- atom_match_tracker_t *atom_trackers; /* Correspondances partielles */
+ GUMemSlice **match_storages; /* Suivi de correspondances */
+ size_t storages_count; /* Quantité de ces suivis */
- full_match_tracker_t **full_trackers; /* Correspondances confirmées */
- size_t full_count; /* Quantité de correspondances */
- full_match_tracker_t *current_tracker; /* Dernier gestionnaire visé */
+ GHashTable *full_trackers; /* Correspondances confirmées */
bool global; /* Validation globale */
diff --git a/src/analysis/scan/context.c b/src/analysis/scan/context.c
index 94ea519..55311c4 100644
--- a/src/analysis/scan/context.c
+++ b/src/analysis/scan/context.c
@@ -32,32 +32,12 @@
#include "context-int.h"
#include "exprs/literal.h"
+#include "matches/area.h"
+#include "matches/bytes.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 **);
-
-/* Prépare l'intégration d'une série de correspondances. */
-static void prepare_full_match_tracker(full_match_tracker_t *, size_t);
-
-/* Note l'existence d'une nouvelle correspondance pour un motif. */
-static void add_match_to_full_match_tracker(full_match_tracker_t *, GScanMatch *);
-
-
-
/* --------------------- MEMORISATION DE PROGRESSIONS D'ANALYSE --------------------- */
@@ -76,145 +56,6 @@ 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. *
-* expected = quantité totale de correspondances attendue. *
-* *
-* Description : Prépare l'intégration d'une série de correspondances. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void prepare_full_match_tracker(full_match_tracker_t *tracker, size_t expected)
-{
- if ((tracker->used + expected) > tracker->allocated)
- {
- tracker->allocated += expected;
- tracker->matches = realloc(tracker->matches, tracker->allocated * sizeof(GScanMatch *));
- }
-
-}
-
-
-/******************************************************************************
-* *
-* 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));
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
/* MEMORISATION DE PROGRESSIONS D'ANALYSE */
/* ---------------------------------------------------------------------------------- */
@@ -266,13 +107,10 @@ static void g_scan_context_init(GScanContext *context)
context->content = NULL;
context->scan_done = false;
- context->next_patid = 0;
-
- context->atom_trackers = NULL;
+ context->match_storages = NULL;
+ context->storages_count = 0;
- context->full_trackers = NULL;
- context->full_count = 0;
- context->current_tracker = NULL;
+ context->full_trackers = g_hash_table_new_full(NULL, NULL, g_object_unref, g_object_unref);
context->global = true;
@@ -302,12 +140,14 @@ static void g_scan_context_dispose(GScanContext *context)
g_clear_object(&context->content);
- 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->storages_count; i++)
+ g_clear_object(&context->match_storages[i]);
+
+ if (context->full_trackers != NULL)
+ {
+ g_hash_table_destroy(context->full_trackers);
+ context->full_trackers = NULL;
+ }
for (i = 0; i < context->cond_count; i++)
g_clear_object(&context->conditions[i].expr);
@@ -332,25 +172,9 @@ static void g_scan_context_dispose(GScanContext *context)
static void g_scan_context_finalize(GScanContext *context)
{
size_t i; /* Boucle de parcours */
- atom_match_tracker_t *atracker; /* Conservateur à manipuler #1 */
- if (context->atom_trackers != NULL)
- {
- for (i = 0; i < context->next_patid; i++)
- {
- atracker = context->atom_trackers + i;
-
- if (atracker->matches != NULL)
- free(atracker->matches);
-
- }
-
- free(context->atom_trackers);
-
- }
-
- if (context->full_trackers != NULL)
- free(context->full_trackers);
+ if (context->match_storages != NULL)
+ free(context->match_storages);
if (context->conditions != NULL)
{
@@ -419,31 +243,9 @@ GScanOptions *g_scan_context_get_options(const GScanContext *context)
/******************************************************************************
* *
-* Paramètres : context = instance à consulter. *
-* *
-* Description : Fournit un identifiant unique pour un motif recherché. *
-* *
-* Retour : Identifiant nouveau à utiliser. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-patid_t g_scan_context_get_new_pattern_id(GScanContext *context)
-{
- patid_t result; /* Identifiant à retourner */
-
- result = context->next_patid++;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : context = instance à consulter. *
-* content = contenu binaire en cours d'analyse. *
+* Paramètres : context = instance à consulter. *
+* content = contenu binaire en cours d'analyse. *
+* ids_count = nombre d'identifiants enregistrés. *
* *
* Description : Définit le contenu principal à analyser. *
* *
@@ -453,15 +255,21 @@ patid_t g_scan_context_get_new_pattern_id(GScanContext *context)
* *
******************************************************************************/
-void g_scan_context_set_content(GScanContext *context, GBinContent *content)
+void g_scan_context_set_content(GScanContext *context, GBinContent *content, size_t ids_count)
{
+ size_t i; /* Boucle de parcours */
+
g_clear_object(&context->content);
context->content = content;
g_object_ref(G_OBJECT(content));
- context->atom_trackers = calloc(context->next_patid, sizeof(atom_match_tracker_t));
+ context->match_storages = calloc(ids_count, sizeof(GUMemSlice *));
+ context->storages_count = ids_count;
+
+ for (i = 0; i < ids_count; i++)
+ context->match_storages[i] = g_umem_slice_new(sizeof(match_area_t));
}
@@ -536,30 +344,25 @@ void g_scan_context_mark_scan_as_done(GScanContext *context)
/******************************************************************************
* *
* Paramètres : context = instance à mettre à jour. *
-* id = identifiant du motif trouvé. *
-* offset = localisation du motif au sein d'un contenu. *
+* count = nombre d'allocateurs en place. [OUT] *
* *
-* Description : Enregistre une correspondance partielle dans un contenu. *
+* Description : Fournit la liste des allocateurs mémorisant des emplacements.*
* *
-* Retour : - *
+* Retour : Liste des allocateurs assurant un suivi des correspondances. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_scan_context_register_atom_match(GScanContext *context, patid_t id, phys_t offset)
+GUMemSlice **g_scan_context_get_match_storages(GScanContext *context, size_t *count)
{
- atom_match_tracker_t *tracker; /* Gestionnaire concerné */
+ GUMemSlice **result; /* Allocateur à renvoyer */
- tracker = &context->atom_trackers[id];
+ result = context->match_storages;
- if (tracker->used == tracker->allocated)
- {
- tracker->allocated += ALLOCATION_STEP;
- tracker->matches = realloc(tracker->matches, tracker->allocated * sizeof(phys_t));
- }
+ *count = context->storages_count;
- tracker->matches[tracker->used++] = offset;
+ return result;
}
@@ -568,7 +371,6 @@ void g_scan_context_register_atom_match(GScanContext *context, patid_t id, phys_
* *
* Paramètres : context = instance à mettre à jour. *
* id = identifiant du motif trouvé. *
-* count = nombre de localisations renvoyées. [OUT] *
* *
* Description : Retourne tous les correspondances partielles notées. *
* *
@@ -578,15 +380,13 @@ void g_scan_context_register_atom_match(GScanContext *context, patid_t id, phys_
* *
******************************************************************************/
-const phys_t *g_scan_context_get_atom_matches(const GScanContext *context, patid_t id, size_t *count)
+GUMemSlice *g_scan_context_get_atom_matches(const GScanContext *context, patid_t id)
{
- const phys_t *result; /* Liste constituée à renvoyer */
- atom_match_tracker_t *tracker; /* Gestionnaire concerné */
+ GUMemSlice *result; /* Liste constituée à renvoyer */
- tracker = &context->atom_trackers[id];
+ result = context->match_storages[id];
- result = tracker->matches;
- *count = tracker->used;
+ g_object_ref(G_OBJECT(result));
return result;
@@ -595,11 +395,11 @@ const phys_t *g_scan_context_get_atom_matches(const GScanContext *context, patid
/******************************************************************************
* *
-* Paramètres : context = instance à mettre à jour. *
-* match = représentation d'une plein ecorrespondance. *
-* expected = quantité totale de correspondances attendue. *
+* Paramètres : context = instance à mettre à jour. *
+* pattern = definition initiale d'un motif recherché. *
+* matches = mémorisation de correspondances établies. *
* *
-* Description : Prépare les enregistrements de correspondances complètes. *
+* Description : Enregistre toutes les correspondances établies pour un motif.*
* *
* Retour : - *
* *
@@ -607,32 +407,28 @@ const phys_t *g_scan_context_get_atom_matches(const GScanContext *context, patid
* *
******************************************************************************/
-void g_scan_context_prepare_full_match_registration(GScanContext *context, GSearchPattern *pattern, size_t expected)
+void g_scan_context_register_full_matches(GScanContext *context, GSearchPattern *pattern, GScanMatches *matches)
{
- 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 */
+#ifndef NDEBUG
+ GSearchPattern *matches_pattern; /* Clef d'un suivi */
+#endif
- key.pattern = pattern;
+ assert(!g_hash_table_contains(context->full_trackers, 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);
+#ifndef NDEBUG
- if (found == NULL)
- {
- tracker = create_full_match_tracker(pattern);
+ matches_pattern = g_scan_matches_get_source(matches);
- context->full_trackers = qinsert(context->full_trackers, &context->full_count,
- sizeof(full_match_tracker_t *),
- (__compar_fn_t)compare_full_match_trackers, &tracker);
+ assert(matches_pattern == pattern);
- }
- else
- tracker = *found;
+ g_object_unref(G_OBJECT(matches_pattern));
- prepare_full_match_tracker(tracker, expected);
+#endif
- context->current_tracker = tracker;
+ g_object_ref(G_OBJECT(pattern));
+ g_object_ref(G_OBJECT(matches));
+
+ g_hash_table_insert(context->full_trackers, pattern, matches);
}
@@ -640,36 +436,26 @@ void g_scan_context_prepare_full_match_registration(GScanContext *context, GSear
/******************************************************************************
* *
* Paramètres : context = instance à mettre à jour. *
-* match = représentation d'une plein ecorrespondance. *
+* pattern = motif dont des correspondances sont à retrouver. *
* *
-* Description : Enregistre une correspondance complète avec un contenu. *
+* Description : Fournit la liste de toutes les correspondances pour un motif.*
* *
-* Retour : - *
+* Retour : Liste courante de correspondances établies. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_scan_context_register_full_match(GScanContext *context, GScanMatch *match)
+GScanMatches *g_scan_context_get_full_matches(const GScanContext *context, const GSearchPattern *pattern)
{
-#ifndef NDEBUG
- GSearchPattern *pattern; /* Clef d'un suivi */
-#endif
-
- assert(context->current_tracker != NULL);
-
-#ifndef NDEBUG
-
- pattern = g_scan_match_get_source(match);
+ GScanMatches *result; /* Correspondance à renvoyer */
- assert(context->current_tracker->pattern == pattern);
+ result = g_hash_table_lookup(context->full_trackers, pattern);
- g_object_unref(G_OBJECT(pattern));
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
-
-#endif
-
- add_match_to_full_match_tracker(context->current_tracker, match);
+ return result;
}
@@ -678,38 +464,26 @@ void g_scan_context_register_full_match(GScanContext *context, GScanMatch *match
* *
* 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. *
+* Description : Dénombre les correspondances associées à un motif. *
* *
-* Retour : Liste courante de correspondances établies. *
+* Retour : Quantité de correspondances établies pour un motif entier. *
* *
* Remarques : - *
* *
******************************************************************************/
-const GScanMatch **g_scan_context_get_full_matches(const GScanContext *context, const GSearchPattern *pattern, size_t *count)
+size_t g_scan_context_count_full_matches(const GScanContext *context, const GSearchPattern *pattern)
{
- GScanMatch **result; /* Correspondance à renvoyer */
- full_match_tracker_t key; /* Modèle d'identification */
- full_match_tracker_t **found; /* Structure à actualiser */
-
- key.pattern = pattern;
+ size_t result; /* Quantité à retourner */
+ GScanMatches *matches; /* Ensemble de Correspondances */
- 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;
- }
+ matches = g_hash_table_lookup(context->full_trackers, pattern);
+ if (matches != NULL)
+ result = g_scan_bytes_matches_count(matches);
else
- {
- result = (*found)->matches;
- *count = (*found)->used;
- }
+ result = 0;
return result;
diff --git a/src/analysis/scan/context.h b/src/analysis/scan/context.h
index 916c618..75190ce 100644
--- a/src/analysis/scan/context.h
+++ b/src/analysis/scan/context.h
@@ -28,9 +28,12 @@
#include <glib-object.h>
-#include "match.h"
+#include "matches.h"
#include "options.h"
+#include "matches/area.h"
+#include "patterns/patid.h"
#include "../content.h"
+#include "../../glibext/umemslice.h"
@@ -53,12 +56,6 @@ typedef struct _GScanContext GScanContext;
typedef struct _GScanContextClass GScanContextClass;
-/* Identifiant de motif intégré */
-typedef uint64_t patid_t;
-
-#define INVALID_PATTERN_ID 0xffffffffffffffff
-
-
/* Indique le type défini pour un contexte de suivi d'analyse. */
GType g_scan_context_get_type(void);
@@ -68,11 +65,8 @@ GScanContext *g_scan_context_new(GScanOptions *);
/* Fournit l'ensemble des options à respecter pour les analyses. */
GScanOptions *g_scan_context_get_options(const GScanContext *);
-/* Fournit un identifiant unique pour un motif recherché. */
-patid_t g_scan_context_get_new_pattern_id(GScanContext *);
-
/* Définit le contenu principal à analyser. */
-void g_scan_context_set_content(GScanContext *, GBinContent *);
+void g_scan_context_set_content(GScanContext *, GBinContent *, size_t);
/* Fournit une référence au contenu principal analysé. */
GBinContent *g_scan_context_get_content(const GScanContext *);
@@ -83,20 +77,20 @@ bool g_scan_context_is_scan_done(const GScanContext *);
/* Note que la phase d'analyse de contenu est terminée. */
void g_scan_context_mark_scan_as_done(GScanContext *);
-/* Enregistre une correspondance partielle dans un contenu. */
-void g_scan_context_register_atom_match(GScanContext *, patid_t, phys_t);
+/* Fournit la liste des allocateurs mémorisant des emplacements. */
+GUMemSlice **g_scan_context_get_match_storages(GScanContext *, size_t *);
/* Retourne tous les correspondances partielles notées. */
-const phys_t *g_scan_context_get_atom_matches(const GScanContext *, patid_t, size_t *);
+GUMemSlice *g_scan_context_get_atom_matches(const GScanContext *, patid_t);
-/* Prépare les enregistrements de correspondances complètes. */
-void g_scan_context_prepare_full_match_registration(GScanContext *, GSearchPattern *, size_t);
+/* Enregistre toutes les correspondances établies pour un motif. */
+void g_scan_context_register_full_matches(GScanContext *, GSearchPattern *, GScanMatches *);
-/* Enregistre une correspondance complète avec un contenu. */
-void g_scan_context_register_full_match(GScanContext *, GScanMatch *);
+/* Fournit la liste de toutes les correspondances pour un motif. */
+GScanMatches *g_scan_context_get_full_matches(const GScanContext *, const GSearchPattern *);
-/* Fournit la liste de toutes les correspondances d'un motif. */
-const GScanMatch **g_scan_context_get_full_matches(const GScanContext *, const GSearchPattern *, size_t *);
+/* Dénombre les correspondances associées à un motif. */
+size_t g_scan_context_count_full_matches(const GScanContext *, const GSearchPattern *);
/* Intègre une condition de correspondance pour règle. */
bool g_scan_context_set_rule_condition(GScanContext *, const char *, GScanExpression *);
diff --git a/src/analysis/scan/exprs/handler.c b/src/analysis/scan/exprs/handler.c
index ecc5a21..d40d00f 100644
--- a/src/analysis/scan/exprs/handler.c
+++ b/src/analysis/scan/exprs/handler.c
@@ -268,6 +268,8 @@ ScanHandlerType g_scan_pattern_handler_get_handler_type(const GScanPatternHandle
}
+#if 0 /* FIXME */
+
/******************************************************************************
* *
* Paramètres : handler = instance à initialiser pleinement. *
@@ -323,6 +325,7 @@ GScanMatch **g_scan_pattern_handler_get_all_matches(const GScanPatternHandler *h
return result;
}
+#endif
@@ -425,7 +428,6 @@ static bool g_scan_pattern_handler_reduce_to_boolean(const GScanPatternHandler *
static bool g_scan_pattern_handler_count_items(const GScanPatternHandler *expr, GScanContext *ctx, size_t *count)
{
bool result; /* Bilan à retourner */
- size_t partial; /* Décompte partiel */
size_t i; /* Boucle de parcours */
result = true;
@@ -435,10 +437,7 @@ static bool g_scan_pattern_handler_count_items(const GScanPatternHandler *expr,
*count = 0;
for (i = 0; i < expr->count; i++)
- {
- g_scan_context_get_full_matches(ctx, expr->patterns[i], &partial);
- *count += partial;
- }
+ *count += g_scan_context_count_full_matches(ctx, expr->patterns[i]);
return result;
@@ -465,11 +464,8 @@ static bool g_scan_pattern_handler_get_item(const GScanPatternHandler *expr, siz
bool result; /* Bilan à retourner */
size_t i; /* Boucle de parcours */
size_t count; /* Quantité de correspondances */
- const GScanMatch **matches; /* Correspondances en place */
- const GScanBytesMatch *match; /* Correspondance ciblée */
- phys_t start; /* Point de départ du motif */
- phys_t end; /* Point d'arrivée du motif */
- phys_t len; /* Taille du motif */
+ GScanBytesMatches *matches; /* Correspondances d'un motif */
+ const match_area_t *area; /* Zone de correspondance */
GBinContent *content; /* Contenu binaire à relire */
vmpa2t pos; /* Tête de lecture */
const bin_t *data; /* Accès aux données brutes */
@@ -483,7 +479,7 @@ static bool g_scan_pattern_handler_get_item(const GScanPatternHandler *expr, siz
for (i = 0; i < expr->count; i++)
{
- matches = g_scan_context_get_full_matches(ctx, expr->patterns[i], &count);
+ count = g_scan_context_count_full_matches(ctx, expr->patterns[i]);
if (index < count)
break;
@@ -494,51 +490,62 @@ static bool g_scan_pattern_handler_get_item(const GScanPatternHandler *expr, siz
if (i == expr->count) goto done;
- result = G_IS_SCAN_BYTES_MATCH(matches[index]);
- if (!result) goto done;
+ /* Identification de la correspondance concernée */
- match = G_SCAN_BYTES_MATCH(matches[index]);
+ matches = g_scan_context_get_full_matches(ctx, expr->patterns[i]);
+ if (matches == NULL) goto done;
- /* Traitement adapté de la requête */
+ area = g_scan_bytes_matches_get(matches, index);
+ if (area == NULL) goto done_with_matches;
- len = g_scan_bytes_match_get_location(match, &start, &end);
+ /* Traitement adapté de la requête */
switch (expr->type)
{
case SHT_RAW:
- content = g_scan_bytes_match_get_content(match);
+ content = g_scan_context_get_content(ctx);
- init_vmpa(&pos, start, VMPA_NO_VIRTUAL);
+ init_vmpa(&pos, area->start, VMPA_NO_VIRTUAL);
- data = g_binary_content_get_raw_access(content, &pos, len);
+ data = g_binary_content_get_raw_access(content, &pos, area->end - area->start);
binary.static_bin_data = data;
- binary.len = len;
+ binary.len = area->end - area->start;
*out = g_scan_literal_expression_new(LVT_STRING, &binary);
g_object_unref(G_OBJECT(content));
+ result = true;
break;
case SHT_COUNTER:
assert(false);
- result = false;
break;
case SHT_START:
- *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ start });
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER,
+ (unsigned long long []){ area->start });
+ result = true;
break;
case SHT_LENGTH:
- *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ len });
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER,
+ (unsigned long long []){ area->end - area->start });
+ result = true;
break;
case SHT_END:
- *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ end });
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER,
+ (unsigned long long []){ area->end });
+ result = true;
break;
}
+ done_with_matches:
+
+ g_object_unref(G_OBJECT(matches));
+
done:
return result;
diff --git a/src/analysis/scan/exprs/handler.h b/src/analysis/scan/exprs/handler.h
index 24c4e8f..96e9301 100644
--- a/src/analysis/scan/exprs/handler.h
+++ b/src/analysis/scan/exprs/handler.h
@@ -65,9 +65,13 @@ GScanExpression *g_scan_pattern_handler_new(GSearchPattern ** const, size_t, Sca
/* Indique le type de manipulation de correspondances spécifié. */
ScanHandlerType g_scan_pattern_handler_get_handler_type(const GScanPatternHandler *);
+#if 0 /* FIXME */
+
/* Fournit la liste de toutes les correspondances représentées. */
GScanMatch **g_scan_pattern_handler_get_all_matches(const GScanPatternHandler *, GScanContext *, size_t *);
+#endif
+
#endif /* _ANALYSIS_SCAN_EXPRS_HANDLER_H */
diff --git a/src/analysis/scan/exprs/setcounter.c b/src/analysis/scan/exprs/setcounter.c
index 14e7676..da37746 100644
--- a/src/analysis/scan/exprs/setcounter.c
+++ b/src/analysis/scan/exprs/setcounter.c
@@ -319,6 +319,7 @@ static ScanReductionState g_scan_set_match_counter_reduce(const GScanSetMatchCou
ScanReductionState result; /* Etat synthétisé à retourner */
size_t matched; /* Qté de motifs avec résultats*/
size_t i; /* Boucle de parcours */
+ GScanMatches *matches; /* Série de correspondances */
size_t count; /* Quantité de correspondances */
bool status; /* Bilan d'évaluation finale */
@@ -328,10 +329,18 @@ static ScanReductionState g_scan_set_match_counter_reduce(const GScanSetMatchCou
for (i = 0; i < expr->count; i++)
{
- g_scan_context_get_full_matches(ctx, expr->patterns[i], &count);
+ matches = g_scan_context_get_full_matches(ctx, expr->patterns[i]);
- if (count > 0)
- matched++;
+ if (matches != NULL)
+ {
+ count = g_scan_matches_count(matches);
+
+ if (count > 0)
+ matched++;
+
+ g_object_unref(G_OBJECT(matches));
+
+ }
}
diff --git a/src/analysis/scan/items/modpath.c b/src/analysis/scan/items/modpath.c
index 1f4d779..62d3387 100644
--- a/src/analysis/scan/items/modpath.c
+++ b/src/analysis/scan/items/modpath.c
@@ -228,6 +228,11 @@ static char *g_scan_modpath_function_get_name(const GScanModpathFunction *item)
static bool g_scan_modpath_function_run_call(GScanModpathFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
{
+
+ return false;
+
+#if 0 /* FIXME */
+
bool result; /* Bilan à retourner */
size_t i; /* Boucle de parcours #1 */
size_t mcount; /* Quantité de correspondances */
@@ -296,4 +301,6 @@ static bool g_scan_modpath_function_run_call(GScanModpathFunction *item, GScanEx
return result;
+#endif
+
}
diff --git a/src/analysis/scan/match.h b/src/analysis/scan/match.h
deleted file mode 100644
index e713b5d..0000000
--- a/src/analysis/scan/match.h
+++ /dev/null
@@ -1,71 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * match.h - prototypes pour la sauvegarde d'une correspondance identifiée de motif
- *
- * 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_MATCH_H
-#define _ANALYSIS_SCAN_MATCH_H
-
-
-#include <glib-object.h>
-
-
-#include "pattern.h"
-#include "../../common/szstr.h"
-
-
-
-#define G_TYPE_SCAN_MATCH g_scan_match_get_type()
-#define G_SCAN_MATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MATCH, GScanMatch))
-#define G_IS_SCAN_MATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MATCH))
-#define G_SCAN_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MATCH, GScanMatchClass))
-#define G_IS_SCAN_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MATCH))
-#define G_SCAN_MATCH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MATCH, GScanMatchClass))
-
-
-/* Correspondance trouvée avec un motif (instance) */
-typedef struct _GScanMatch GScanMatch;
-
-/* Correspondance trouvée avec un motif (classe) */
-typedef struct _GScanMatchClass GScanMatchClass;
-
-
-/* Indique le type défini pour un correspondance de motif identifiée. */
-GType g_scan_match_get_type(void);
-
-/* Indique la source du motif d'origine recherché. */
-GSearchPattern *g_scan_match_get_source(const GScanMatch *);
-
-/* Affiche une correspondance au format texte. */
-void g_scan_match_output_to_text(const GScanMatch *, int);
-
-/* Convertit une correspondance en texte. */
-void g_scan_match_convert_as_text(const GScanMatch *);
-
-/* Affiche une correspondance au format JSON. */
-void g_scan_match_output_to_json(const GScanMatch *, const sized_string_t *, unsigned int, int, bool);
-
-/* Convertit une correspondance en JSON. */
-void g_scan_match_convert_as_json(const GScanMatch *);
-
-
-
-#endif /* _ANALYSIS_SCAN_MATCH_H */
diff --git a/src/analysis/scan/match-int.h b/src/analysis/scan/matches-int.h
index cf774c4..674fe03 100644
--- a/src/analysis/scan/match-int.h
+++ b/src/analysis/scan/matches-int.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * match-int.h - prototypes internes pour la sauvegarde d'une correspondance identifiée de motif
+ * matches-int.h - prototypes internes pour la sauvegarde de correspondances de motif identifiées
*
* Copyright (C) 2022 Cyrille Bagard
*
@@ -21,23 +21,26 @@
*/
-#ifndef _ANALYSIS_SCAN_MATCH_INT_H
-#define _ANALYSIS_SCAN_MATCH_INT_H
+#ifndef _ANALYSIS_SCAN_MATCHES_INT_H
+#define _ANALYSIS_SCAN_MATCHES_INT_H
-#include "match.h"
+#include "matches.h"
-/* Affiche une correspondance au format texte. */
-typedef void (* output_scan_match_to_text_fc) (const GScanMatch *, int);
+/* Dénombre les correspondances enregistrées pour un motif. */
+typedef size_t (* count_scan_matches_fc) (const GScanMatches *);
-/* Affiche une correspondance au format JSON. */
-typedef void (* output_scan_match_to_json_fc) (const GScanMatch *, const sized_string_t *, unsigned int, int);
+/* Affiche une série de correspondances au format texte. */
+typedef void (* output_scan_matches_to_text_fc) (const GScanMatches *, int);
+/* Affiche une série de correspondances au format JSON. */
+typedef void (* output_scan_matches_to_json_fc) (const GScanMatches *, const sized_string_t *, unsigned int, int);
-/* Correspondance trouvée avec un motif (instance) */
-struct _GScanMatch
+
+/* Correspondances trouvées avec un motif (instance) */
+struct _GScanMatches
{
GObject parent; /* A laisser en premier */
@@ -45,16 +48,18 @@ struct _GScanMatch
};
-/* Correspondance trouvée avec un motif (classe) */
-struct _GScanMatchClass
+/* Correspondances trouvées avec un motif (classe) */
+struct _GScanMatchesClass
{
GObjectClass parent; /* A laisser en premier */
- output_scan_match_to_text_fc to_text; /* Impression au format texte */
- output_scan_match_to_json_fc to_json; /* Impression au format JSON */
+ count_scan_matches_fc count; /* Décompte des correspondances*/
+
+ output_scan_matches_to_text_fc to_text; /* Impression au format texte */
+ output_scan_matches_to_json_fc to_json; /* Impression au format JSON */
};
-#endif /* _ANALYSIS_SCAN_MATCH_INT_H */
+#endif /* _ANALYSIS_SCAN_MATCHES_INT_H */
diff --git a/src/analysis/scan/match.c b/src/analysis/scan/matches.c
index b0b4320..3dc15f9 100644
--- a/src/analysis/scan/match.c
+++ b/src/analysis/scan/matches.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * match.c - sauvegarde d'une correspondance identifiée de motif
+ * matches.c - sauvegarde de correspondances de motif identifiées
*
* Copyright (C) 2022 Cyrille Bagard
*
@@ -21,36 +21,36 @@
*/
-#include "match.h"
+#include "matches.h"
-#include "match-int.h"
+#include "matches-int.h"
-/* Initialise la classe des correspondances de motifs. */
-static void g_scan_match_class_init(GScanMatchClass *);
+/* Initialise la classe des séries de correspondances de motifs. */
+static void g_scan_matches_class_init(GScanMatchesClass *);
-/* Initialise une instance de correspondance de motif trouvée. */
-static void g_scan_match_init(GScanMatch *);
+/* Initialise une instance de série de correspondances trouvées. */
+static void g_scan_matches_init(GScanMatches *);
/* Supprime toutes les références externes. */
-static void g_scan_match_dispose(GScanMatch *);
+static void g_scan_matches_dispose(GScanMatches *);
/* Procède à la libération totale de la mémoire. */
-static void g_scan_match_finalize(GScanMatch *);
+static void g_scan_matches_finalize(GScanMatches *);
-/* Indique le type défini pour un correspondance de motif identifiée. */
-G_DEFINE_TYPE(GScanMatch, g_scan_match, G_TYPE_OBJECT);
+/* Indique le type défini pour une série de correspondances identifiées. */
+G_DEFINE_TYPE(GScanMatches, g_scan_matches, G_TYPE_OBJECT);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
-* Description : Initialise la classe des correspondances de motifs. *
+* Description : Initialise la classe des séries de correspondances de motifs.*
* *
* Retour : - *
* *
@@ -58,23 +58,23 @@ G_DEFINE_TYPE(GScanMatch, g_scan_match, G_TYPE_OBJECT);
* *
******************************************************************************/
-static void g_scan_match_class_init(GScanMatchClass *klass)
+static void g_scan_matches_class_init(GScanMatchesClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_match_dispose;
- object->finalize = (GObjectFinalizeFunc)g_scan_match_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_matches_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_matches_finalize;
}
/******************************************************************************
* *
-* Paramètres : match = instance à initialiser. *
+* Paramètres : matches = instance à initialiser. *
* *
-* Description : Initialise une instance de correspondance de motif trouvée. *
+* Description : Initialise une instance de série de correspondances trouvées.*
* *
* Retour : - *
* *
@@ -82,16 +82,16 @@ static void g_scan_match_class_init(GScanMatchClass *klass)
* *
******************************************************************************/
-static void g_scan_match_init(GScanMatch *match)
+static void g_scan_matches_init(GScanMatches *matches)
{
- match->source = NULL;
+ matches->source = NULL;
}
/******************************************************************************
* *
-* Paramètres : match = instance d'objet GLib à traiter. *
+* Paramètres : matches = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -101,18 +101,18 @@ static void g_scan_match_init(GScanMatch *match)
* *
******************************************************************************/
-static void g_scan_match_dispose(GScanMatch *match)
+static void g_scan_matches_dispose(GScanMatches *matches)
{
- g_clear_object(&match->source);
+ g_clear_object(&matches->source);
- G_OBJECT_CLASS(g_scan_match_parent_class)->dispose(G_OBJECT(match));
+ G_OBJECT_CLASS(g_scan_matches_parent_class)->dispose(G_OBJECT(matches));
}
/******************************************************************************
* *
-* Paramètres : match = instance d'objet GLib à traiter. *
+* Paramètres : matches = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -122,30 +122,30 @@ static void g_scan_match_dispose(GScanMatch *match)
* *
******************************************************************************/
-static void g_scan_match_finalize(GScanMatch *match)
+static void g_scan_matches_finalize(GScanMatches *matches)
{
- G_OBJECT_CLASS(g_scan_match_parent_class)->finalize(G_OBJECT(match));
+ G_OBJECT_CLASS(g_scan_matches_parent_class)->finalize(G_OBJECT(matches));
}
/******************************************************************************
* *
-* Paramètres : match = définition de correspondance à consulter. *
+* Paramètres : matches = définition de correspondance à consulter. *
* *
* Description : Indique la source du motif d'origine recherché. *
* *
-* Retour : - *
+* Retour : Motif à l'origine des correspondances. *
* *
* Remarques : - *
* *
******************************************************************************/
-GSearchPattern *g_scan_match_get_source(const GScanMatch *match)
+GSearchPattern *g_scan_matches_get_source(const GScanMatches *matches)
{
GSearchPattern *result; /* Source à retourner */
- result = match->source;
+ result = matches->source;
g_object_ref(G_OBJECT(result));
@@ -156,10 +156,36 @@ GSearchPattern *g_scan_match_get_source(const GScanMatch *match)
/******************************************************************************
* *
-* Paramètres : match = définition de correspondance à manipuler. *
-* fd = canal d'écriture. *
+* Paramètres : matches = définition de correspondance à consulter. *
+* *
+* Description : Dénombre les correspondances enregistrées pour un motif. *
+* *
+* Retour : Quantité de correspondances établies. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_scan_matches_count(const GScanMatches *matches)
+{
+ size_t result; /* Quantité à retourner */
+ GScanMatchesClass *class; /* Classe à activer */
+
+ class = G_SCAN_MATCHES_GET_CLASS(matches);
+
+ result = class->count(matches);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : matches = définition de correspondance à manipuler. *
+* fd = canal d'écriture. *
* *
-* Description : Affiche une correspondance au format texte. *
+* Description : Affiche une série de correspondances au format texte. *
* *
* Retour : - *
* *
@@ -167,22 +193,22 @@ GSearchPattern *g_scan_match_get_source(const GScanMatch *match)
* *
******************************************************************************/
-void g_scan_match_output_to_text(const GScanMatch *match, int fd)
+void g_scan_matches_output_to_text(const GScanMatches *matches, int fd)
{
- GScanMatchClass *class; /* Classe à activer */
+ GScanMatchesClass *class; /* Classe à activer */
- class = G_SCAN_MATCH_GET_CLASS(match);
+ class = G_SCAN_MATCHES_GET_CLASS(matches);
- class->to_text(match, fd);
+ class->to_text(matches, fd);
}
/******************************************************************************
* *
-* Paramètres : match = définition de correspondance à manipuler. *
+* Paramètres : matches = définition de correspondance à manipuler. *
* *
-* Description : Convertit une correspondance en texte. *
+* Description : Convertit une série de correspondances en texte. *
* *
* Retour : - *
* *
@@ -190,7 +216,7 @@ void g_scan_match_output_to_text(const GScanMatch *match, int fd)
* *
******************************************************************************/
-void g_scan_match_convert_as_text(const GScanMatch *match)
+void g_scan_matches_convert_as_text(const GScanMatches *matches)
{
/* TODO */
@@ -199,13 +225,12 @@ void g_scan_match_convert_as_text(const GScanMatch *match)
/******************************************************************************
* *
-* Paramètres : match = définition de correspondance à manipuler. *
+* Paramètres : matches = définition de correspondance à manipuler. *
* padding = éventuel bourrage initial à placer ou NULL. *
* level = profondeur actuelle. *
* fd = canal d'écriture. *
-* trailing = impose une virgule finale ? *
* *
-* Description : Affiche une correspondance au format JSON. *
+* Description : Affiche une série de correspondances au format JSON. *
* *
* Retour : - *
* *
@@ -213,42 +238,22 @@ void g_scan_match_convert_as_text(const GScanMatch *match)
* *
******************************************************************************/
-void g_scan_match_output_to_json(const GScanMatch *match, const sized_string_t *padding, unsigned int level, int fd, bool trailing)
+void g_scan_matches_output_to_json(const GScanMatches *matches, const sized_string_t *padding, unsigned int level, int fd)
{
- unsigned int i; /* Boucle de parcours */
- GScanMatchClass *class; /* Classe à activer */
-
- /* Introduction */
-
- for (i = 0; i < level; i++)
- write(fd, padding->data, padding->len);
-
- write(fd, "{\n", 2);
-
- /* Affichage du contenu */
-
- class = G_SCAN_MATCH_GET_CLASS(match);
-
- class->to_json(match, padding, level + 1, fd);
-
- /* Conclusion */
+ GScanMatchesClass *class; /* Classe à activer */
- for (i = 0; i < level; i++)
- write(fd, padding->data, padding->len);
+ class = G_SCAN_MATCHES_GET_CLASS(matches);
- if (trailing)
- write(fd, "},\n", 3);
- else
- write(fd, "}\n", 2);
+ class->to_json(matches, padding, level + 1, fd);
}
/******************************************************************************
* *
-* Paramètres : match = définition de correspondance à manipuler. *
+* Paramètres : matches = définition de correspondance à manipuler. *
* *
-* Description : Convertit une correspondance en JSON. *
+* Description : Convertit une série de correspondances en JSON. *
* *
* Retour : - *
* *
@@ -256,7 +261,7 @@ void g_scan_match_output_to_json(const GScanMatch *match, const sized_string_t *
* *
******************************************************************************/
-void g_scan_match_convert_as_json(const GScanMatch *match)
+void g_scan_matches_convert_as_json(const GScanMatches *matches)
{
/* TODO */
diff --git a/src/analysis/scan/matches.h b/src/analysis/scan/matches.h
new file mode 100644
index 0000000..345db96
--- /dev/null
+++ b/src/analysis/scan/matches.h
@@ -0,0 +1,74 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * matches.h - prototypes pour la sauvegarde de correspondances de motif identifiées
+ *
+ * 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_MATCHES_H
+#define _ANALYSIS_SCAN_MATCHES_H
+
+
+#include <glib-object.h>
+
+
+#include "pattern.h"
+#include "../../common/szstr.h"
+
+
+
+#define G_TYPE_SCAN_MATCHES g_scan_matches_get_type()
+#define G_SCAN_MATCHES(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MATCHES, GScanMatches))
+#define G_IS_SCAN_MATCHES(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MATCHES))
+#define G_SCAN_MATCHES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MATCHES, GScanMatchesClass))
+#define G_IS_SCAN_MATCHES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MATCHES))
+#define G_SCAN_MATCHES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MATCHES, GScanMatchesClass))
+
+
+/* Correspondances trouvées avec un motif (instance) */
+typedef struct _GScanMatches GScanMatches;
+
+/* Correspondances trouvées avec un motif (classe) */
+typedef struct _GScanMatchesClass GScanMatchesClass;
+
+
+/* Indique le type défini pour une série de correspondances identifiées. */
+GType g_scan_matches_get_type(void);
+
+/* Indique la source du motif d'origine recherché. */
+GSearchPattern *g_scan_matches_get_source(const GScanMatches *);
+
+/* Dénombre les correspondances enregistrées pour un motif. */
+size_t g_scan_matches_count(const GScanMatches *);
+
+/* Affiche une série de correspondances au format texte. */
+void g_scan_matches_output_to_text(const GScanMatches *, int);
+
+/* Convertit une série de correspondances en texte. */
+void g_scan_matches_convert_as_text(const GScanMatches *);
+
+/* Affiche une série de correspondances au format JSON. */
+void g_scan_matches_output_to_json(const GScanMatches *, const sized_string_t *, unsigned int, int);
+
+/* Convertit une série de correspondances en JSON. */
+void g_scan_matches_convert_as_json(const GScanMatches *);
+
+
+
+#endif /* _ANALYSIS_SCAN_MATCHES_H */
diff --git a/src/analysis/scan/matches/Makefile.am b/src/analysis/scan/matches/Makefile.am
index d6b51c6..f1a69c3 100644
--- a/src/analysis/scan/matches/Makefile.am
+++ b/src/analysis/scan/matches/Makefile.am
@@ -3,9 +3,9 @@ noinst_LTLIBRARIES = libanalysisscanmatches.la
libanalysisscanmatches_la_SOURCES = \
+ area.h area.c \
bytes-int.h \
- bytes.h bytes.c \
- pending.h pending.c
+ bytes.h bytes.c
libanalysisscanmatches_la_CFLAGS = $(LIBGOBJ_CFLAGS)
diff --git a/src/analysis/scan/matches/area.c b/src/analysis/scan/matches/area.c
new file mode 100644
index 0000000..3f512b0
--- /dev/null
+++ b/src/analysis/scan/matches/area.c
@@ -0,0 +1,57 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * area.c - conservation des localisations de correspondances
+ *
+ * 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 "area.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : a = première zone de correspondance à comparer. *
+* b = seconde zone de correspondance à comparer. *
+* *
+* Description : Etablit une comparaison entre deux zones de correspondance. *
+* *
+* Retour : Bilan de la comparaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int compare_match_area_as_dl_item(const dl_list_item *a, const dl_list_item *b)
+{
+ int result; /* Bilan à retourner */
+ match_area_t *area_a; /* Première zone à traiter */
+ match_area_t *area_b; /* Seconde zone à traiter */
+
+ area_a = match_area_from_item(a);
+ area_b = match_area_from_item(b);
+
+ result = sort_uint64_t(area_a->start, area_b->start);
+
+ if (result == 0)
+ result = sort_uint64_t(area_a->end, area_b->end);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/matches/area.h b/src/analysis/scan/matches/area.h
new file mode 100644
index 0000000..b059b35
--- /dev/null
+++ b/src/analysis/scan/matches/area.h
@@ -0,0 +1,85 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * area.h - prototypes pour la conservation des localisations de correspondances
+ *
+ * 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_MATCHES_AREA_H
+#define _ANALYSIS_SCAN_MATCHES_AREA_H
+
+
+#include <assert.h>
+
+
+#include "../../../arch/vmpa.h"
+#include "../../../common/dllist.h"
+
+
+
+/* Couverture d'une correspondance */
+typedef struct _match_area_t
+{
+ phys_t start; /* Point de départ */
+ phys_t end; /* Point d'arrivée (exclus) */
+
+ DL_LIST_ITEM(link); /* Lien vers les maillons */
+
+ size_t mod_path_index; /* Indice de construction */
+ bool has_mod_path; /* Validité du champ précédent */
+
+} match_area_t;
+
+
+#define match_area_from_item(item) \
+ (match_area_t *)container_of(item, match_area_t, link)
+
+#define add_tail_match_area(new, head) \
+ dl_list_add_tail(new, head, match_area_t, link)
+
+#define del_match_area(item, head) \
+ dl_list_del(item, head, match_area_t, link)
+
+#define for_each_match_area(pos, head) \
+ dl_list_for_each(pos, head, match_area_t, link)
+
+#define for_each_match_area_safe(pos, head, next) \
+ dl_list_for_each_safe(pos, head, next, match_area_t, link)
+
+#define is_last_match_area(item, head) \
+ dl_list_is_last(item, head, link)
+
+#define merge_match_areas(head1, head2) \
+ dl_list_merge(head1, head2, match_area_t, link)
+
+#define sort_match_areas_no_dup(head, len, cmp, dup) \
+ ({ \
+ assert(!dl_list_empty(*(head))); \
+ dl_list_item *hmbr = &(*head)->link; \
+ sort_dl_list_no_dup(&hmbr, len, cmp, dup); \
+ match_area_from_item(hmbr); \
+ })
+
+
+/* Etablit une comparaison entre deux zones de correspondance. */
+int compare_match_area_as_dl_item(const dl_list_item *, const dl_list_item *);
+
+
+
+#endif /* _ANALYSIS_SCAN_MATCHES_AREA_H */
diff --git a/src/analysis/scan/matches/bytes-int.h b/src/analysis/scan/matches/bytes-int.h
index f57cb9f..d356208 100644
--- a/src/analysis/scan/matches/bytes-int.h
+++ b/src/analysis/scan/matches/bytes-int.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * bytes-int.h - prototypes internes pour la sauvegarde d'une correspondance identifiée de suite d'octets
+ * bytes-int.h - prototypes internes pour la sauvegarde de correspondances avec des suites d'octets identifiées
*
* Copyright (C) 2022 Cyrille Bagard
*
@@ -28,35 +28,36 @@
#include "bytes.h"
-#include "../match-int.h"
+#include "../matches-int.h"
-/* Correspondance trouvée avec une chaîne (instance) */
-struct _GScanBytesMatch
+/* Correspondances trouvées avec des suite d'octets (instance) */
+struct _GScanBytesMatches
{
- GScanMatch parent; /* A laisser en premier */
+ GScanMatches parent; /* A laisser en premier */
- GBinContent *content; /* Contenu binaire de référence*/
+ GScanContext *context; /* Contexte de rattachement */
- phys_t start; /* Début du motif représenté */
- phys_t len; /* Taille du motif représenté */
+ // TODO : if NDEBUG ?
+ phys_t content_start; /* Point de début du contenu */
+ phys_t content_end; /* Point de fin du contenu */
- size_t mod_path_index; /* Indice de construction */
- bool has_mod_path; /* Validité du champ précédent */
+ match_area_t *areas; /* Zones couvertes */
+ size_t count; /* Nombre de zones */
};
-/* Correspondance trouvée avec une chaîne (classe) */
-struct _GScanBytesMatchClass
+/* Correspondances trouvées avec des suite d'octets (classe) */
+struct _GScanBytesMatchesClass
{
- GScanMatchClass parent; /* A laisser en premier */
+ GScanMatchesClass parent; /* A laisser en premier */
};
-/* Met en place une correspondance trouvée avec un motif. */
-bool g_scan_bytes_match_create(GScanBytesMatch *, GSearchPattern *, GBinContent *, phys_t, phys_t);
+/* Met en place une série de correspondances avec des octets. */
+bool g_scan_bytes_matches_create(GScanBytesMatches *, GSearchPattern *, GScanContext *);
diff --git a/src/analysis/scan/matches/bytes.c b/src/analysis/scan/matches/bytes.c
index f0b97fe..ca8c5b6 100644
--- a/src/analysis/scan/matches/bytes.c
+++ b/src/analysis/scan/matches/bytes.c
@@ -36,20 +36,20 @@
-/* --------------------- CORRESPONDANCE AVEC UNE SUITE D'OCTETS --------------------- */
+/* -------------------- CONSERVATION DE CORRESPONDANCES ETABLIES -------------------- */
-/* Initialise la classe des correspondances de chaînes. */
-static void g_scan_bytes_match_class_init(GScanBytesMatchClass *);
+/* Initialise la classe des séries de correspondances d'octets. */
+static void g_scan_bytes_matches_class_init(GScanBytesMatchesClass *);
-/* Initialise une instance de correspondance de chaîne trouvée. */
-static void g_scan_bytes_match_init(GScanBytesMatch *);
+/* Initialise une instance de série de correspondances trouvées. */
+static void g_scan_bytes_matches_init(GScanBytesMatches *);
/* Supprime toutes les références externes. */
-static void g_scan_bytes_match_dispose(GScanBytesMatch *);
+static void g_scan_bytes_matches_dispose(GScanBytesMatches *);
/* Procède à la libération totale de la mémoire. */
-static void g_scan_bytes_match_finalize(GScanBytesMatch *);
+static void g_scan_bytes_matches_finalize(GScanBytesMatches *);
@@ -57,27 +57,27 @@ static void g_scan_bytes_match_finalize(GScanBytesMatch *);
/* Affiche une correspondance au format texte. */
-static void g_scan_bytes_match_output_to_text(const GScanBytesMatch *, int);
+static void g_scan_bytes_matches_output_to_text(const GScanBytesMatches *, int);
/* Affiche une correspondance au format JSON. */
-static void g_scan_bytes_match_output_to_json(const GScanBytesMatch *, const sized_string_t *, unsigned int, int);
+static void g_scan_bytes_matches_output_to_json(const GScanBytesMatches *, const sized_string_t *, unsigned int, int);
/* ---------------------------------------------------------------------------------- */
-/* CORRESPONDANCE AVEC UNE SUITE D'OCTETS */
+/* CONSERVATION DE CORRESPONDANCES ETABLIES */
/* ---------------------------------------------------------------------------------- */
-/* Indique le type défini pour un correspondance de chaîne identifiée. */
-G_DEFINE_TYPE(GScanBytesMatch, g_scan_bytes_match, G_TYPE_SCAN_MATCH);
+/* Indique le type défini pour une série de correspondances d'octets identifiées. */
+G_DEFINE_TYPE(GScanBytesMatches, g_scan_bytes_matches, G_TYPE_SCAN_MATCHES);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
-* Description : Initialise la classe des correspondances de chaînes. *
+* Description : Initialise la classe des séries de correspondances d'octets. *
* *
* Retour : - *
* *
@@ -85,29 +85,29 @@ G_DEFINE_TYPE(GScanBytesMatch, g_scan_bytes_match, G_TYPE_SCAN_MATCH);
* *
******************************************************************************/
-static void g_scan_bytes_match_class_init(GScanBytesMatchClass *klass)
+static void g_scan_bytes_matches_class_init(GScanBytesMatchesClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
- GScanMatchClass *match; /* Version parente de la classe*/
+ GScanMatchesClass *matches; /* Version parente de la classe*/
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_bytes_match_dispose;
- object->finalize = (GObjectFinalizeFunc)g_scan_bytes_match_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_bytes_matches_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_bytes_matches_finalize;
- match = G_SCAN_MATCH_CLASS(klass);
+ matches = G_SCAN_MATCHES_CLASS(klass);
- match->to_text = (output_scan_match_to_text_fc)g_scan_bytes_match_output_to_text;
- match->to_json = (output_scan_match_to_json_fc)g_scan_bytes_match_output_to_json;
+ matches->to_text = (output_scan_matches_to_text_fc)g_scan_bytes_matches_output_to_text;
+ matches->to_json = (output_scan_matches_to_json_fc)g_scan_bytes_matches_output_to_json;
}
/******************************************************************************
* *
-* Paramètres : match = instance à initialiser. *
+* Paramètres : matches = instance à initialiser. *
* *
-* Description : Initialise une instance de correspondance de chaîne trouvée. *
+* Description : Initialise une instance de série de correspondances trouvées.*
* *
* Retour : - *
* *
@@ -115,21 +115,22 @@ static void g_scan_bytes_match_class_init(GScanBytesMatchClass *klass)
* *
******************************************************************************/
-static void g_scan_bytes_match_init(GScanBytesMatch *match)
+static void g_scan_bytes_matches_init(GScanBytesMatches *matches)
{
- match->content = NULL;
+ matches->context = NULL;
- match->start = VMPA_NO_PHYSICAL;
- match->len = VMPA_NO_PHYSICAL;
+ matches->content_start = VMPA_NO_PHYSICAL;
+ matches->content_end = VMPA_NO_PHYSICAL;
- match->has_mod_path = false;
+ matches->areas = NULL;
+ matches->count = 0;
}
/******************************************************************************
* *
-* Paramètres : match = instance d'objet GLib à traiter. *
+* Paramètres : matches = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -139,18 +140,18 @@ static void g_scan_bytes_match_init(GScanBytesMatch *match)
* *
******************************************************************************/
-static void g_scan_bytes_match_dispose(GScanBytesMatch *match)
+static void g_scan_bytes_matches_dispose(GScanBytesMatches *matches)
{
- g_clear_object(&match->content);
+ //g_clear_object(&matches->context);
- G_OBJECT_CLASS(g_scan_bytes_match_parent_class)->dispose(G_OBJECT(match));
+ G_OBJECT_CLASS(g_scan_bytes_matches_parent_class)->dispose(G_OBJECT(matches));
}
/******************************************************************************
* *
-* Paramètres : match = instance d'objet GLib à traiter. *
+* Paramètres : matches = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -160,9 +161,9 @@ static void g_scan_bytes_match_dispose(GScanBytesMatch *match)
* *
******************************************************************************/
-static void g_scan_bytes_match_finalize(GScanBytesMatch *match)
+static void g_scan_bytes_matches_finalize(GScanBytesMatches *matches)
{
- G_OBJECT_CLASS(g_scan_bytes_match_parent_class)->finalize(G_OBJECT(match));
+ G_OBJECT_CLASS(g_scan_bytes_matches_parent_class)->finalize(G_OBJECT(matches));
}
@@ -170,11 +171,9 @@ static void g_scan_bytes_match_finalize(GScanBytesMatch *match)
/******************************************************************************
* *
* Paramètres : source = lien vers le motif recherché d'origine. *
-* content = contenu binaire présentant un motif reconnu. *
-* start = position de départ d'un motif détecté. *
-* len = taille du motif repéré. *
+* context = contexte associé au scan courant. *
* *
-* Description : Prend note d'une correspondance trouvée avec un motif. *
+* Description : Crée un suivi pour série de correspondances avec des octets. *
* *
* Retour : Correspondance mise en place. *
* *
@@ -182,13 +181,13 @@ static void g_scan_bytes_match_finalize(GScanBytesMatch *match)
* *
******************************************************************************/
-GScanMatch *g_scan_bytes_match_new(GSearchPattern *source, GBinContent *content, phys_t start, phys_t len)
+GScanMatches *g_scan_bytes_matches_new(GSearchPattern *source, GScanContext *context)
{
- GScanMatch *result; /* Structure à retourner */
+ GScanMatches *result; /* Structure à retourner */
- result = g_object_new(G_TYPE_SCAN_BYTES_MATCH, NULL);
+ result = g_object_new(G_TYPE_SCAN_BYTES_MATCHES, NULL);
- if (!g_scan_bytes_match_create(G_SCAN_BYTES_MATCH(result), source, content, start, len))
+ if (!g_scan_bytes_matches_create(G_SCAN_BYTES_MATCHES(result), source, context))
g_clear_object(&result);
return result;
@@ -198,13 +197,11 @@ GScanMatch *g_scan_bytes_match_new(GSearchPattern *source, GBinContent *content,
/******************************************************************************
* *
-* Paramètres : match = instance à initialiser pleinement. *
+* Paramètres : matches = instance à initialiser pleinement. *
* source = lien vers le motif recherché d'origine. *
-* content = contenu binaire présentant un motif reconnu. *
-* start = position de départ d'un motif détecté. *
-* len = taille du motif repéré. *
+* context = contexte associé au scan courant. *
* *
-* Description : Met en place une correspondance trouvée avec un motif. *
+* Description : Met en place une série de correspondances avec des octets. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -212,23 +209,33 @@ GScanMatch *g_scan_bytes_match_new(GSearchPattern *source, GBinContent *content,
* *
******************************************************************************/
-bool g_scan_bytes_match_create(GScanBytesMatch *match, GSearchPattern *source, GBinContent *content, phys_t start, phys_t len)
+bool g_scan_bytes_matches_create(GScanBytesMatches *matches, GSearchPattern *source, GScanContext *context)
{
bool result; /* Bilan à retourner */
- GScanMatch *base; /* Lien vers les infos de base */
+ GScanMatches *base; /* Lien vers les infos de base */
+ GBinContent *content; /* Contenu à manipuler */
+ vmpa2t start; /* Point de début du contenu */
+ vmpa2t end; /* Point de fin du contenu */
result = true;
- base = G_SCAN_MATCH(match);
+ base = G_SCAN_MATCHES(matches);
base->source = source;
g_object_ref(G_OBJECT(source));
- match->content = content;
- g_object_ref(G_OBJECT(content));
+ matches->context = context;
+ //g_object_ref(G_OBJECT(context));
- match->start = start;
- match->len = len;
+ content = g_scan_context_get_content(context);
+
+ g_binary_content_compute_start_pos(content, &start);
+ g_binary_content_compute_end_pos(content, &end);
+
+ matches->content_start = start.physical;
+ matches->content_end = end.physical;
+
+ g_object_unref(G_OBJECT(content));
return result;
@@ -237,21 +244,21 @@ bool g_scan_bytes_match_create(GScanBytesMatch *match, GSearchPattern *source, G
/******************************************************************************
* *
-* Paramètres : match = informations de correspondance à consulter. *
+* Paramètres : matches = informations de correspondances à consulter. *
* *
-* Description : Fournit une référence au contenu lié à la correspondance. *
+* Description : Fournit le contexte du scan associé aux correspondances. *
* *
-* Retour : Content binaire associé au context. *
+* Retour : Contexte de scan courant. *
* *
* Remarques : - *
* *
******************************************************************************/
-GBinContent *g_scan_bytes_match_get_content(const GScanBytesMatch *match)
+GScanContext *g_scan_bytes_matches_get_context(const GScanBytesMatches *matches)
{
- GBinContent *result; /* Instance à retourner */
+ GScanContext *result; /* Instance à retourner */
- result = match->content;
+ result = matches->context;
g_object_ref(G_OBJECT(result));
@@ -262,26 +269,44 @@ GBinContent *g_scan_bytes_match_get_content(const GScanBytesMatch *match)
/******************************************************************************
* *
-* Paramètres : match = informations de correspondance à consulter. *
-* start = position de départ d'un motif détecté. [OUT] *
-* end = position d'arrivée d'un motif détecté. [OUT] *
+* Paramètres : matches = suivi de correspondances à manipuler. *
+* list = correspondances établies à mémoriser. *
+* count = taille de cette liste. *
* *
-* Description : Indique la localisation d'une correspondance établie. *
+* Description : Intègre une liste de correspondances vérifiées. *
* *
-* Retour : Taille mesurée de la correspondance. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-phys_t g_scan_bytes_match_get_location(const GScanBytesMatch *match, phys_t *start, phys_t *end)
+void g_scan_bytes_matches_set_list(GScanBytesMatches *matches, match_area_t *list, size_t count)
{
- phys_t result; /* Taille à retourner */
+ matches->areas = list;
- result = match->len;
+ matches->count = count;
- *start = match->start;
- *end = match->start + result;
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : matches = suivi de correspondances à consulter. *
+* *
+* Description : Indique le nombre de correspondances pour une définition. *
+* *
+* Retour : Quantité de correspondances établies pour un motif entier. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_scan_bytes_matches_count(const GScanBytesMatches *matches)
+{
+ size_t result; /* Quantité à retourner */
+
+ result = matches->count;
return result;
@@ -290,28 +315,71 @@ phys_t g_scan_bytes_match_get_location(const GScanBytesMatch *match, phys_t *sta
/******************************************************************************
* *
-* Paramètres : match = informations de correspondance à compléter. *
-* index = indice de la combinaison de modificateurs ciblée. *
+* Paramètres : matches = suivi de correspondances à consulter. *
+* index = indice de la correspondance recherchée. *
* *
-* Description : Mémorise l'origine d'une correspondance à partir d'un indice.*
+* Description : Fournit les informations relatives à une correspondance. *
* *
-* Retour : - *
+* Retour : Propritétés de la correspondance visée ou NULL pour un échec.*
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const match_area_t *g_scan_bytes_matches_get(const GScanBytesMatches *matches, size_t index)
+{
+ const match_area_t *result; /* Pointeur à retourner */
+
+
+ for_each_match_area(result, matches->areas)
+ {
+ if (index == 0)
+ break;
+ }
+
+ assert(index == 0);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : matches = informations de correspondance à consulter. *
+* index = indice de la correspondance visée. *
+* start = position de départ d'un motif détecté. [OUT] *
+* end = position d'arrivée d'un motif détecté. [OUT] *
+* *
+* Description : Indique la localisation d'une correspondance établie. *
+* *
+* Retour : Taille mesurée de la correspondance. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_scan_bytes_match_remember_modifier_path(GScanBytesMatch *match, size_t index)
+phys_t g_scan_bytes_matches_get_location(const GScanBytesMatches *matches, size_t index, phys_t *start, phys_t *end)
{
- match->mod_path_index = index;
- match->has_mod_path = true;
+ phys_t result; /* Taille à retourner */
+
+ result = 0;
+
+ /*
+ result = match->len;
+
+ *start = match->start;
+ *end = match->start + result;
+ */
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : match = informations de correspondance à consulter. *
+* Paramètres : matches = informations de correspondance à consulter. *
* *
* Description : Retrouve l'origine d'une correspondance à partir d'un indice.*
* *
@@ -321,11 +389,15 @@ void g_scan_bytes_match_remember_modifier_path(GScanBytesMatch *match, size_t in
* *
******************************************************************************/
-char *g_scan_bytes_match_get_modifier_path(const GScanBytesMatch *match)
+char *g_scan_bytes_matches_get_modifier_path(const GScanBytesMatches *matches)
{
char *result; /* Combinaison à retourner */
GBytesToken *pattern; /* Autre version du motif */
+ result = NULL;
+
+ /*
+
if (match->has_mod_path)
{
pattern = G_BYTES_TOKEN(G_SCAN_MATCH(match)->source);
@@ -334,6 +406,7 @@ char *g_scan_bytes_match_get_modifier_path(const GScanBytesMatch *match)
else
result = NULL;
+ */
return result;
@@ -348,8 +421,8 @@ char *g_scan_bytes_match_get_modifier_path(const GScanBytesMatch *match)
/******************************************************************************
* *
-* Paramètres : match = définition de correspondance à manipuler. *
-* fd = canal d'écriture. *
+* Paramètres : matches = définition de correspondance à manipuler. *
+* fd = canal d'écriture. *
* *
* Description : Affiche une correspondance au format texte. *
* *
@@ -359,91 +432,105 @@ char *g_scan_bytes_match_get_modifier_path(const GScanBytesMatch *match)
* *
******************************************************************************/
-static void g_scan_bytes_match_output_to_text(const GScanBytesMatch *match, int fd)
+static void g_scan_bytes_matches_output_to_text(const GScanBytesMatches *matches, int fd)
{
+ GBinContent *content; /* Contenu binaire analysé */
+ GScanMatches *base; /* Lien vers les infos de base */
+ const char *name; /* Désignation du motif ciblé */
+ match_area_t *iter; /* Boucle de parcours #1 */
char value[2 + ULLONG_MAXLEN]; /* Impression de la position */
int ret; /* Bilan d'une conversion */
- GScanMatch *base; /* Lien vers les infos de base */
- const char *name; /* Désignation du motif ciblé */
vmpa2t pos; /* Tête de lecture */
+ phys_t len; /* Taille d'une correspondance */
const bin_t *data; /* Accès aux données brutes */
phys_t k; /* Boucle de parcours #2 */
- /* Position dans le binaire (hexadécimal) */
+ content = g_scan_context_get_content(matches->context);
- ret = snprintf(value, ULLONG_MAXLEN, "0x%llx", (unsigned long long)match->start);
+ base = G_SCAN_MATCHES(matches);
- if (ret > 0)
- write(fd, value, ret);
+ name = g_search_pattern_get_name(base->source);
- else
+ for_each_match_area(iter, matches->areas)
{
- log_simple_message(LMT_EXT_ERROR, "Error while converting offset to hex!");
- write(fd, "\"<error>\"", 9);
- }
-
- write(fd, ":", 1);
+ /* Position dans le binaire (hexadécimal) */
- /* Affichage de la désignation */
+ ret = snprintf(value, ULLONG_MAXLEN, "0x%llx", (unsigned long long)iter->start);
- write(fd, "$", 1);
+ if (ret > 0)
+ write(fd, value, ret);
- base = G_SCAN_MATCH(match);
+ else
+ {
+ log_simple_message(LMT_EXT_ERROR, "Error while converting offset to hex!");
+ write(fd, "\"<error>\"", 9);
+ }
- name = g_search_pattern_get_name(base->source);
+ write(fd, ":", 1);
- /**
- * Les fonctionnalités Yara d'origine autorisent les variables anonymes '$'.
- *
- * Cette absence de nom est supportée ici.
- */
+ /* Affichage de la désignation */
- if (name != NULL)
- write(fd, name, strlen(name));
+ write(fd, "$", 1);
- write(fd, ": ", 2);
+ /**
+ * Les fonctionnalités Yara d'origine autorisent les variables anonymes '$'.
+ *
+ * Cette absence de nom est supportée ici.
+ */
- /* Affichage du contenu */
+ if (name != NULL)
+ write(fd, name, strlen(name));
- init_vmpa(&pos, match->start, VMPA_NO_VIRTUAL);
+ write(fd, ": ", 2);
- data = g_binary_content_get_raw_access(match->content, &pos, match->len);
+ /* Affichage du contenu */
- for (k = 0; k < match->len; k++)
- {
- if (isprint(data[k]))
- write(fd, &data[k], 1);
+ init_vmpa(&pos, iter->start, VMPA_NO_VIRTUAL);
- else
- {
- write(fd, "\\x", 2);
+ len = iter->end - iter->start;
- ret = snprintf(value, ULLONG_MAXLEN, "%02hhx", data[k]);
+ data = g_binary_content_get_raw_access(content, &pos, len);
+ assert(data != NULL);
- if (ret > 0)
- {
- assert(ret == 2);
- write(fd, value, ret);
- }
+ for (k = 0; k < len; k++)
+ {
+ if (isprint(data[k]))
+ write(fd, &data[k], 1);
else
{
- log_simple_message(LMT_EXT_ERROR, "Error while converting data!");
- write(fd, "??", 2);
+ write(fd, "\\x", 2);
+
+ ret = snprintf(value, ULLONG_MAXLEN, "%02hhx", data[k]);
+
+ if (ret > 0)
+ {
+ assert(ret == 2);
+ write(fd, value, ret);
+ }
+
+ else
+ {
+ log_simple_message(LMT_EXT_ERROR, "Error while converting data!");
+ write(fd, "??", 2);
+ }
+
}
}
+ write(fd, "\n", 1);
+
}
- write(fd, "\n", 1);
+ g_object_unref(G_OBJECT(content));
}
/******************************************************************************
* *
-* Paramètres : match = définition de correspondance à manipuler. *
+* Paramètres : matches = définition de correspondance à manipuler. *
* padding = éventuel bourrage initial à placer ou NULL. *
* level = profondeur actuelle. *
* fd = canal d'écriture. *
@@ -456,188 +543,246 @@ static void g_scan_bytes_match_output_to_text(const GScanBytesMatch *match, int
* *
******************************************************************************/
-static void g_scan_bytes_match_output_to_json(const GScanBytesMatch *match, const sized_string_t *padding, unsigned int level, int fd)
+static void g_scan_bytes_matches_output_to_json(const GScanBytesMatches *matches, const sized_string_t *padding, unsigned int level, int fd)
{
unsigned int i; /* Boucle de parcours #1 */
- vmpa2t pos; /* Tête de lecture */
char value[4 + ULLONG_MAXLEN]; /* Impression de la position */
int ret; /* Bilan d'une conversion */
+ GBinContent *content; /* Contenu binaire analysé */
+ match_area_t *iter; /* Boucle de parcours #1 */
+ vmpa2t pos; /* Tête de lecture */
+ phys_t len; /* Taille d'une correspondance */
const bin_t *data; /* Accès aux données brutes */
phys_t k; /* Boucle de parcours #2 */
- /* Position dans le binaire (décimal) */
+ /* Nombre de correspondances */
for (i = 0; i < level; i++)
write(fd, padding->data, padding->len);
- write(fd, "\"offset\": ", 10);
+ write(fd, "\"match_count\": ", 15);
- ret = snprintf(value, ULLONG_MAXLEN, "%llu", (unsigned long long)match->start);
+ ret = snprintf(value, ULLONG_MAXLEN, "%zu", matches->count);
if (ret > 0)
write(fd, value, ret);
else
{
- log_simple_message(LMT_EXT_ERROR, "Error while converting offset!");
+ log_simple_message(LMT_EXT_ERROR, "Error while converting value!");
write(fd, "null", 4);
}
write(fd, ",\n", 2);
- /* Position dans le binaire (hexadécimal) */
+ /* Détail des correspondances */
for (i = 0; i < level; i++)
write(fd, padding->data, padding->len);
- write(fd, "\"offset_hex\": ", 14);
+ write(fd, "\"matches\": [\n", 13);
- ret = snprintf(value, ULLONG_MAXLEN, "\"0x%llx\"", (unsigned long long)match->start);
+ content = g_scan_context_get_content(matches->context);
- if (ret > 0)
- write(fd, value, ret);
-
- else
+ for_each_match_area(iter, matches->areas)
{
- log_simple_message(LMT_EXT_ERROR, "Error while converting offset to hex!");
- write(fd, "null", 4);
- }
-
- write(fd, ",\n", 2);
+ /* Marqueur de début */
- /* Affichage du contenu brut */
+ for (i = 0; i < (level + 1); i++)
+ write(fd, padding->data, padding->len);
- for (i = 0; i < level; i++)
- write(fd, padding->data, padding->len);
+ write(fd, "{\n", 2);
- write(fd, "\"content\": \"", 12);
+ /* Position dans le binaire (décimal) */
- init_vmpa(&pos, match->start, VMPA_NO_VIRTUAL);
+ for (i = 0; i < (level + 2); i++)
+ write(fd, padding->data, padding->len);
- data = g_binary_content_get_raw_access(match->content, &pos, match->len);
- assert(data != NULL);
+ write(fd, "\"offset\": ", 10);
- for (k = 0; k < match->len; k++)
- {
- if (data[k] == '\\')
- write(fd, "\\\\", 2);
+ ret = snprintf(value, ULLONG_MAXLEN, "%llu", (unsigned long long)iter->start);
- else if (isprint(data[k]))
- write(fd, &data[k], 1);
+ if (ret > 0)
+ write(fd, value, ret);
else
{
- write(fd, "\\u", 2);
+ log_simple_message(LMT_EXT_ERROR, "Error while converting offset!");
+ write(fd, "null", 4);
+ }
- /**
- * Cf. https://datatracker.ietf.org/doc/html/rfc8259#section-7
- */
- ret = snprintf(value, ULLONG_MAXLEN, "%04hhx", data[k]);
+ write(fd, ",\n", 2);
- if (ret > 0)
- {
- assert(ret == 4);
- write(fd, value, ret);
- }
+ /* Position dans le binaire (hexadécimal) */
- else
- {
- log_simple_message(LMT_EXT_ERROR, "Error while converting data!");
- write(fd, "??", 2);
- }
+ for (i = 0; i < (level + 2); i++)
+ write(fd, padding->data, padding->len);
- }
+ write(fd, "\"offset_hex\": ", 14);
- }
+ ret = snprintf(value, ULLONG_MAXLEN, "\"0x%llx\"", (unsigned long long)iter->start);
- write(fd, "\",\n", 3);
+ if (ret > 0)
+ write(fd, value, ret);
- /* Affichage du contenu en version humainement lisible */
+ else
+ {
+ log_simple_message(LMT_EXT_ERROR, "Error while converting offset to hex!");
+ write(fd, "null", 4);
+ }
- for (i = 0; i < level; i++)
- write(fd, padding->data, padding->len);
+ write(fd, ",\n", 2);
- write(fd, "\"content_str\": \"", 16);
+ /* Affichage du contenu brut */
- init_vmpa(&pos, match->start, VMPA_NO_VIRTUAL);
+ for (i = 0; i < (level + 2); i++)
+ write(fd, padding->data, padding->len);
- data = g_binary_content_get_raw_access(match->content, &pos, match->len);
- assert(data != NULL);
+ write(fd, "\"content\": \"", 12);
- for (k = 0; k < match->len; k++)
- {
- if (data[k] == '\\')
- write(fd, "\\\\", 2);
+ init_vmpa(&pos, iter->start, VMPA_NO_VIRTUAL);
- else if (isprint(data[k]))
- write(fd, &data[k], 1);
+ len = iter->end - iter->start;
- else
+ data = g_binary_content_get_raw_access(content, &pos, len);
+ assert(data != NULL);
+
+ for (k = 0; k < len; k++)
{
- write(fd, "\\\\x", 3);
+ if (data[k] == '\\')
+ write(fd, "\\\\", 2);
- ret = snprintf(value, ULLONG_MAXLEN, "%02hhx", data[k]);
+ else if (isprint(data[k]))
+ write(fd, &data[k], 1);
- if (ret > 0)
+ else
{
- assert(ret == 2);
- write(fd, value, ret);
+ write(fd, "\\u", 2);
+
+ /**
+ * Cf. https://datatracker.ietf.org/doc/html/rfc8259#section-7
+ */
+ ret = snprintf(value, ULLONG_MAXLEN, "%04hhx", data[k]);
+
+ if (ret > 0)
+ {
+ assert(ret == 4);
+ write(fd, value, ret);
+ }
+
+ else
+ {
+ log_simple_message(LMT_EXT_ERROR, "Error while converting data!");
+ write(fd, "??", 2);
+ }
+
}
+ }
+
+ write(fd, "\",\n", 3);
+
+ /* Affichage du contenu en version humainement lisible */
+
+ for (i = 0; i < (level + 2); i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "\"content_str\": \"", 16);
+
+ init_vmpa(&pos, iter->start, VMPA_NO_VIRTUAL);
+
+ data = g_binary_content_get_raw_access(content, &pos, len);
+ assert(data != NULL);
+
+ for (k = 0; k < len; k++)
+ {
+ if (data[k] == '\\')
+ write(fd, "\\\\", 2);
+
+ else if (isprint(data[k]))
+ write(fd, &data[k], 1);
+
else
{
- log_simple_message(LMT_EXT_ERROR, "Error while converting data!");
- write(fd, "??", 2);
+ write(fd, "\\\\x", 3);
+
+ ret = snprintf(value, ULLONG_MAXLEN, "%02hhx", data[k]);
+
+ if (ret > 0)
+ {
+ assert(ret == 2);
+ write(fd, value, ret);
+ }
+
+ else
+ {
+ log_simple_message(LMT_EXT_ERROR, "Error while converting data!");
+ write(fd, "??", 2);
+ }
+
}
}
- }
+ write(fd, "\",\n", 3);
- write(fd, "\",\n", 3);
+ /* Affichage du contenu brut */
- /* Affichage du contenu brut */
+ for (i = 0; i < (level + 2); i++)
+ write(fd, padding->data, padding->len);
- for (i = 0; i < level; i++)
- write(fd, padding->data, padding->len);
+ write(fd, "\"length\": ", 10);
- write(fd, "\"length\": ", 10);
+ ret = snprintf(value, ULLONG_MAXLEN, "%llu", (unsigned long long)len);
- init_vmpa(&pos, match->start, VMPA_NO_VIRTUAL);
+ if (ret > 0)
+ write(fd, value, ret);
- ret = snprintf(value, ULLONG_MAXLEN, "%llu", (unsigned long long)match->len);
+ else
+ {
+ log_simple_message(LMT_EXT_ERROR, "Error while converting data!");
+ write(fd, "-1", 2);
+ }
- if (ret > 0)
- write(fd, value, ret);
+ write(fd, ",\n", 2);
- else
- {
- log_simple_message(LMT_EXT_ERROR, "Error while converting data!");
- write(fd, "-1", 2);
- }
+ /* Affichage du contenu brut (hexadécimal) */
- write(fd, ",\n", 2);
+ for (i = 0; i < (level + 2); i++)
+ write(fd, padding->data, padding->len);
- /* Affichage du contenu brut (hexadécimal) */
+ write(fd, "\"length_hex\": ", 14);
- for (i = 0; i < level; i++)
- write(fd, padding->data, padding->len);
+ ret = snprintf(value, ULLONG_MAXLEN, "\"0x%llx\"", (unsigned long long)len);
- write(fd, "\"length_hex\": ", 14);
+ if (ret > 0)
+ write(fd, value, ret);
- init_vmpa(&pos, match->start, VMPA_NO_VIRTUAL);
+ else
+ {
+ log_simple_message(LMT_EXT_ERROR, "Error while converting data!");
+ write(fd, "\"0xffffffffffffffff\"", 20);
+ }
- ret = snprintf(value, ULLONG_MAXLEN, "\"0x%llx\"", (unsigned long long)match->len);
+ write(fd, "\n", 1);
- if (ret > 0)
- write(fd, value, ret);
+ /* Marqueur de fin */
+
+ for (i = 0; i < (level + 1); i++)
+ write(fd, padding->data, padding->len);
+
+ if (is_last_match_area(iter, matches->areas))
+ write(fd, "}\n", 2);
+ else
+ write(fd, "},\n", 3);
- else
- {
- log_simple_message(LMT_EXT_ERROR, "Error while converting data!");
- write(fd, "\"0xffffffffffffffff\"", 20);
}
- write(fd, "\n", 1);
+ g_object_unref(G_OBJECT(content));
+
+ for (i = 0; i < level; i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "]\n", 2);
}
diff --git a/src/analysis/scan/matches/bytes.h b/src/analysis/scan/matches/bytes.h
index bd7425d..9e046aa 100644
--- a/src/analysis/scan/matches/bytes.h
+++ b/src/analysis/scan/matches/bytes.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * bytes.h - prototypes pour la sauvegarde d'une correspondance identifiée de suite d'octets
+ * bytes.h - prototypes pour la sauvegarde de correspondances avec des suites d'octets identifiées
*
* Copyright (C) 2022 Cyrille Bagard
*
@@ -28,43 +28,53 @@
#include <glib-object.h>
-#include "../match.h"
-#include "../../content.h"
+#include "area.h"
+#include "../context.h"
+#include "../matches.h"
-#define G_TYPE_SCAN_BYTES_MATCH g_scan_bytes_match_get_type()
-#define G_SCAN_BYTES_MATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_BYTES_MATCH, GScanBytesMatch))
-#define G_IS_SCAN_BYTES_MATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_BYTES_MATCH))
-#define G_SCAN_BYTES_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_BYTES_MATCH, GScanBytesMatchClass))
-#define G_IS_SCAN_BYTES_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_BYTES_MATCH))
-#define G_SCAN_BYTES_MATCH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_BYTES_MATCH, GScanBytesMatchClass))
+/* -------------------- CONSERVATION DE CORRESPONDANCES ETABLIES -------------------- */
-/* Correspondance trouvée avec une chaîne (instance) */
-typedef struct _GScanBytesMatch GScanBytesMatch;
+#define G_TYPE_SCAN_BYTES_MATCHES g_scan_bytes_matches_get_type()
+#define G_SCAN_BYTES_MATCHES(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_BYTES_MATCHES, GScanBytesMatches))
+#define G_IS_SCAN_BYTES_MATCHES(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_BYTES_MATCHES))
+#define G_SCAN_BYTES_MATCHES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_BYTES_MATCHES, GScanBytesMatchesClass))
+#define G_IS_SCAN_BYTES_MATCHES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_BYTES_MATCHES))
+#define G_SCAN_BYTES_MATCHES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_BYTES_MATCHES, GScanBytesMatchesClass))
-/* Correspondance trouvée avec une chaîne (classe) */
-typedef struct _GScanBytesMatchClass GScanBytesMatchClass;
+/* Correspondances trouvées avec des suite d'octets (instance) */
+typedef struct _GScanBytesMatches GScanBytesMatches;
-/* Indique le type défini pour un correspondance de chaîne identifiée. */
-GType g_scan_bytes_match_get_type(void);
+/* Correspondances trouvées avec des suite d'octets (classe) */
+typedef struct _GScanBytesMatchesClass GScanBytesMatchesClass;
-/* Prend note d'une correspondance trouvée avec un motif. */
-GScanMatch *g_scan_bytes_match_new(GSearchPattern *, GBinContent *, phys_t, phys_t);
-/* Fournit une référence au contenu lié à la correspondance. */
-GBinContent *g_scan_bytes_match_get_content(const GScanBytesMatch *);
+/* Indique le type défini pour une série de correspondances d'octets identifiées. */
+GType g_scan_bytes_matches_get_type(void);
-/* Indique la localisation d'une correspondance établie. */
-phys_t g_scan_bytes_match_get_location(const GScanBytesMatch *, phys_t *, phys_t *);
+/* Crée un suivi pour série de correspondances avec des octets. */
+GScanMatches *g_scan_bytes_matches_new(GSearchPattern *, GScanContext *);
+
+/* Fournit le contexte du scan associé aux correspondances. */
+GScanContext *g_scan_bytes_matches_get_context(const GScanBytesMatches *);
+
+/* Intègre une liste de correspondances vérifiées. */
+void g_scan_bytes_matches_set_list(GScanBytesMatches *, match_area_t *, size_t);
-/* Mémorise l'origine d'une correspondance à partir d'un indice. */
-void g_scan_bytes_match_remember_modifier_path(GScanBytesMatch *, size_t);
+/* Indique le nombre de correspondances pour une définition. */
+size_t g_scan_bytes_matches_count(const GScanBytesMatches *);
+
+/* Fournit les informations relatives à une correspondance. */
+const match_area_t *g_scan_bytes_matches_get(const GScanBytesMatches *, size_t);
+
+/* Indique la localisation d'une correspondance établie. */
+phys_t g_scan_bytes_matches_get_location(const GScanBytesMatches *, size_t, phys_t *, phys_t *);
/* Retrouve l'origine d'une correspondance à partir d'un indice. */
-char *g_scan_bytes_match_get_modifier_path(const GScanBytesMatch *);
+char *g_scan_bytes_matches_get_modifier_path(const GScanBytesMatches *);
diff --git a/src/analysis/scan/matches/pending.c b/src/analysis/scan/matches/pending.c
index 57c63d7..c653257 100644
--- a/src/analysis/scan/matches/pending.c
+++ b/src/analysis/scan/matches/pending.c
@@ -33,6 +33,8 @@
+
+
/* ------------------------- MEMORISATION D'UNE ZONE BORNEE ------------------------- */
@@ -48,6 +50,8 @@ static int compare_match_area(const match_area_t *, const match_area_t *);
+
+
/* ---------------------------------------------------------------------------------- */
/* MEMORISATION D'UNE ZONE BORNEE */
/* ---------------------------------------------------------------------------------- */
@@ -55,6 +59,104 @@ static int compare_match_area(const match_area_t *, const match_area_t *);
/******************************************************************************
* *
+* Paramètres : allocator = allocateur dédié à l'ensemble de zones. *
+* start = point de départ d'une nouvelle correspondance. *
+* length = taille de la zone couverte. *
+* *
+* Description : Crée une nouvelle structure de suivi de correspondance. *
+* *
+* Retour : Structure initialisée mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static match_area_t *create_match_area(GUMemCache *allocator, phys_t start, phys_t length)
+{
+ match_area_t *result; /* Zone à retourner */
+
+ result = g_umem_cache_alloc(allocator);
+
+ DL_LIST_ITEM_INIT(&result->link);
+
+ result->start = start;
+ result->end = start + length;
+
+ assert(matches->content_start <= result->start);
+ assert(result->end <= matches->content_end);
+
+ result->ttl = 1;
+
+ result->has_mod_path = false;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : allocator = allocateur dédié à l'ensemble de zones. *
+* start = point de départ d'une nouvelle correspondance. *
+* length = taille de la zone couverte. *
+* index = indice de construction pour le motif concerné. *
+* *
+* Description : Crée une nouvelle structure de suivi de correspondance. *
+* *
+* Retour : Structure initialisée mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static match_area_t *create_match_area_with_path(GUMemCache *allocator, phys_t start, phys_t length, size_t index)
+{
+ match_area_t *result; /* Zone à retourner */
+
+ result = g_umem_cache_alloc(allocator);
+
+ DL_LIST_ITEM_INIT(&result->link);
+
+ result->start = start;
+ result->end = start + length;
+
+ assert(matches->content_start <= result->start);
+ assert(result->end <= matches->content_end);
+
+ result->ttl = 1;
+
+ result->mod_path_index = index;
+ result->has_mod_path = true;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : area = zone de suivi à supprimer. *
+* allocator = allocateur dédié à l'ensemble de zones. *
+* *
+* Description : Supprime une structure de suivi de correspondance. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void delete_match_area(match_area_t *area, GUMemCache *allocator)
+{
+ // TODO : assert(alone)
+
+ g_umem_cache_free(allocator, area);
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : a = pointeur vers la première zone à analyser. *
* b = pointeur vers la seconde zone à analyser. *
* *
@@ -114,6 +216,7 @@ void init_pending_matches(pending_matches_t *matches, const phys_t *start, const
matches->content_start = *start;
matches->content_end = *end;
+ matches->allocator = NULL;
matches->areas = NULL;
matches->allocated = 0;
matches->used = 0;
@@ -275,27 +378,12 @@ match_area_t * const *get_all_pending_matches(const pending_matches_t *matches,
void add_pending_match(pending_matches_t *matches, phys_t start, phys_t length)
{
- match_area_t *area; /* Zone à initialiser */
-
- if (matches->used == matches->allocated)
- {
- matches->allocated += PENDING_ALLOC_SIZE;
-
- matches->areas = realloc(matches->areas, matches->allocated * sizeof(match_area_t));
-
- }
-
- area = &matches->areas[matches->used++];
+ match_area_t *area; /* Nouvelle zone à intégrer */
- area->start = start;
- area->end = start + length;
+ area = create_match_area(matches->allocator, start, length);
- assert(matches->content_start <= area->start);
- assert(area->end <= matches->content_end);
-
- area->ttl = 1;
-
- area->has_mod_path = false;
+ dl_list_add_tail(area, &matches->areas, match_area_t, link);
+ matches->used++;
}
@@ -317,28 +405,12 @@ void add_pending_match(pending_matches_t *matches, phys_t start, phys_t length)
void add_pending_match_with_path(pending_matches_t *matches, phys_t start, phys_t length, size_t index)
{
- match_area_t *area; /* Zone à initialiser */
-
- if (matches->used == matches->allocated)
- {
- matches->allocated += PENDING_ALLOC_SIZE;
-
- matches->areas = realloc(matches->areas, matches->allocated * sizeof(match_area_t));
-
- }
-
- area = &matches->areas[matches->used++];
-
- area->start = start;
- area->end = start + length;
-
- assert(matches->content_start <= area->start);
- assert(area->end <= matches->content_end);
+ match_area_t *area; /* Nouvelle zone à intégrer */
- area->ttl = 1;
+ area = create_match_area_with_path(matches->allocator, start, length, index);
- area->mod_path_index = index;
- area->has_mod_path = true;
+ dl_list_add_tail(area, &matches->areas, match_area_t, link);
+ matches->used++;
}
diff --git a/src/analysis/scan/matches/pending.h b/src/analysis/scan/matches/pending.h
index f4ac7a2..e430ca1 100644
--- a/src/analysis/scan/matches/pending.h
+++ b/src/analysis/scan/matches/pending.h
@@ -21,7 +21,7 @@
*/
-#ifndef _ANALYSIS_SCAN_MATCHES_PENDING_H
+#if 0 //ndef _ANALYSIS_SCAN_MATCHES_PENDING_H
#define _ANALYSIS_SCAN_MATCHES_PENDING_H
@@ -30,12 +30,20 @@
#include "../../content.h"
+#include "../../../common/dllist.h"
+
+
+
+// TODO : move vers ByteMatch
+typedef int GUMemCache;
/* Couverture d'une correspondance */
typedef struct _match_area_t
{
+ DL_LIST_ITEM(link); /* Lien vers les maillons */
+
phys_t start; /* Point de départ */
phys_t end; /* Point d'arrivée (exclus) */
@@ -52,6 +60,7 @@ typedef struct _pending_matches_t
phys_t content_start; /* Point de début du contenu */
phys_t content_end; /* Point de fin du contenu */
+ GUMemCache *allocator; /* Allocateur pour zones */
match_area_t *areas; /* Zones couvertes */
size_t allocated; /* Nombre d'allocations */
size_t used; /* Nombre de zones */
diff --git a/src/analysis/scan/pattern.c b/src/analysis/scan/pattern.c
index fe3babc..dc4418c 100644
--- a/src/analysis/scan/pattern.c
+++ b/src/analysis/scan/pattern.c
@@ -332,7 +332,7 @@ void g_search_pattern_output_to_json(const GSearchPattern *pattern, GScanContext
class = G_SEARCH_PATTERN_GET_CLASS(pattern);
- class->to_json(pattern, context, padding, level + 1, fd);
+ class->to_json(pattern, context, padding, level, fd);
/* Conclusion */
diff --git a/src/analysis/scan/patterns/Makefile.am b/src/analysis/scan/patterns/Makefile.am
index c520321..989a562 100644
--- a/src/analysis/scan/patterns/Makefile.am
+++ b/src/analysis/scan/patterns/Makefile.am
@@ -10,6 +10,7 @@ libanalysisscanpatterns_la_SOURCES = \
modarg.h \
modifier-int.h \
modifier.h modifier.c \
+ patid.h \
token-int.h \
token.h token.c
diff --git a/src/analysis/scan/patterns/backend-int.h b/src/analysis/scan/patterns/backend-int.h
index b2587df..90daec9 100644
--- a/src/analysis/scan/patterns/backend-int.h
+++ b/src/analysis/scan/patterns/backend-int.h
@@ -33,11 +33,17 @@
typedef size_t (* get_backend_atom_max_size_fc) (const GEngineBackend *);
/* Inscrit dans le moteur une chaîne de caractères à rechercher. */
-typedef patid_t (* enroll_plain_into_backend_fc) (GEngineBackend *, GScanContext *, const uint8_t *, size_t);
+typedef patid_t (* enroll_plain_into_backend_fc) (GEngineBackend *, const uint8_t *, size_t, uint32_t [2]);
/* Met en ordre les derniers détails avant un premier scan. */
typedef void (* warm_up_backend_fc) (GEngineBackend *);
+/* Récupère les identifiants finaux pour un motif recherché. */
+typedef patid_t (* build_backend_plain_pattern_id_fc) (const GEngineBackend *, const uint32_t [2]);
+
+/* Détermine le nombre d'identifiants constitués. */
+typedef size_t (* count_backend_plain_pattern_ids_fc) (const GEngineBackend *);
+
/* Parcours un contenu binaire à la recherche de motifs. */
typedef void (* run_backend_scan_fc) (const GEngineBackend *, GScanContext *);
@@ -57,9 +63,11 @@ struct _GEngineBackendClass
{
GObjectClass parent; /* A laisser en premier */
- get_backend_atom_max_size_fc get_max_size; /* Taille maximale d'atome */
- enroll_plain_into_backend_fc enroll_plain; /* Inscription simple */
+ get_backend_atom_max_size_fc get_max_size; /* Taille maximale d'atome */
+ enroll_plain_into_backend_fc enroll_plain; /* Inscription simpl e */
warm_up_backend_fc warm_up; /* Préchauffage avant analyse */
+ build_backend_plain_pattern_id_fc build_id; /* Définition d'identifiant*/
+ count_backend_plain_pattern_ids_fc count_ids; /* Décompte des id. */
run_backend_scan_fc run_scan; /* Lancement d'une analyse */
output_backend_stats_fc output; /* Impression de statistiques */
diff --git a/src/analysis/scan/patterns/backend.c b/src/analysis/scan/patterns/backend.c
index 0ecc7fe..50cc889 100644
--- a/src/analysis/scan/patterns/backend.c
+++ b/src/analysis/scan/patterns/backend.c
@@ -155,9 +155,9 @@ size_t g_engine_backend_get_atom_max_size(const GEngineBackend *backend)
/******************************************************************************
* *
* Paramètres : backend = moteur de recherche à manipuler. *
-* context = contexte de l'analyse à mener. *
* plain = chaîne de caractères classique à intégrer. *
* len = taille de cette chaîne. *
+* tmp_id = identifiants temporaires vers le motif. [OUT] *
* *
* Description : Inscrit dans le moteur une chaîne de caractères à rechercher.*
* *
@@ -167,14 +167,14 @@ size_t g_engine_backend_get_atom_max_size(const GEngineBackend *backend)
* *
******************************************************************************/
-patid_t g_engine_backend_enroll_plain_pattern(GEngineBackend *backend, GScanContext *context, const uint8_t *plain, size_t len)
+bool g_engine_backend_enroll_plain_pattern(GEngineBackend *backend, const uint8_t *plain, size_t len, uint32_t tmp_id[2])
{
- patid_t result; /* Identifiant à retourner */
+ bool result; /* Bilan à retourner */
GEngineBackendClass *class; /* Classe à activer */
class = G_ENGINE_BACKEND_GET_CLASS(backend);
- result = class->enroll_plain(backend, context, plain, len);
+ result = class->enroll_plain(backend, plain, len, tmp_id);
return result;
@@ -208,6 +208,59 @@ void g_engine_backend_warm_up(GEngineBackend *backend)
/******************************************************************************
* *
* Paramètres : backend = moteur de recherche à manipuler. *
+* tmp_id = identifiants temporaires vers le motif. [OUT] *
+* *
+* Description : Récupère les identifiants finaux pour un motif recherché. *
+* *
+* Retour : Identifiant constitué ou INVALID_PATTERN_ID en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+patid_t g_engine_backend_build_plain_pattern_id(const GEngineBackend *backend, const uint32_t tmp_id[2])
+{
+ patid_t result; /* Identifiant à retourner */
+ GEngineBackendClass *class; /* Classe à activer */
+
+ class = G_ENGINE_BACKEND_GET_CLASS(backend);
+
+ result = class->build_id(backend, tmp_id);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* *
+* Description : Détermine le nombre d'identifiants constitués. *
+* *
+* Retour : Quantité de gestionnaires de suivi à prévoir. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_engine_backend_count_plain_pattern_ids(const GEngineBackend *backend)
+{
+ size_t result; /* Quantité à retourner */
+ GEngineBackendClass *class; /* Classe à activer */
+
+ class = G_ENGINE_BACKEND_GET_CLASS(backend);
+
+ result = class->count_ids(backend);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
* context = lieu d'enregistrement des résultats. *
* *
* Description : Parcours un contenu binaire à la recherche de motifs. *
diff --git a/src/analysis/scan/patterns/backend.h b/src/analysis/scan/patterns/backend.h
index 8f6b929..71c97d1 100644
--- a/src/analysis/scan/patterns/backend.h
+++ b/src/analysis/scan/patterns/backend.h
@@ -57,11 +57,17 @@ GType g_engine_backend_get_type(void);
size_t g_engine_backend_get_atom_max_size(const GEngineBackend *);
/* Inscrit dans le moteur une chaîne de caractères à rechercher. */
-patid_t g_engine_backend_enroll_plain_pattern(GEngineBackend *, GScanContext *, const uint8_t *, size_t);
+bool g_engine_backend_enroll_plain_pattern(GEngineBackend *, const uint8_t *, size_t, uint32_t [2]);
/* Met en ordre les derniers détails avant un premier scan. */
void g_engine_backend_warm_up(GEngineBackend *);
+/* Récupère les identifiants finaux pour un motif recherché. */
+patid_t g_engine_backend_build_plain_pattern_id(const GEngineBackend *, const uint32_t [2]);
+
+/* Détermine le nombre d'identifiants constitués. */
+size_t g_engine_backend_count_plain_pattern_ids(const GEngineBackend *);
+
/* Parcours un contenu binaire à la recherche de motifs. */
void g_engine_backend_run_scan(const GEngineBackend *, GScanContext *);
diff --git a/src/analysis/scan/patterns/backends/acism-int.h b/src/analysis/scan/patterns/backends/acism-int.h
index a8cfd59..af8080f 100644
--- a/src/analysis/scan/patterns/backends/acism-int.h
+++ b/src/analysis/scan/patterns/backends/acism-int.h
@@ -36,7 +36,7 @@
-#define __USE_BYTE_FREQ
+//#define __USE_BYTE_FREQ
//#define __SORT_BEFORE_BITMASK
@@ -50,10 +50,14 @@ typedef struct _acism_source_t
const uint8_t *atoms; /* Motif remarquable */
size_t len; /* Nombre d'octets considérés */
- patid_t pid; /* Identifiant de suivi */
+ uint32_t coverage[2]; /* Départ et quantité de suivis*/
} acism_source_t;
+#define SOURCE_COVERAGE_START 0
+#define SOURCE_COVERAGE_COUNT 1
+#define SOURCE_COVERAGE_END 1
+
/* Etude de la fréquence des octets pour attribution des codes */
typedef struct _acism_freq_rank_t
{
@@ -81,8 +85,6 @@ typedef struct _acism_trie_node_t
bin_t data; /* Donnée brute représentée */
acism_code_t code; /* Identifiant du noeud */
- patid_t pid; /* Identifiant de suivi */
-
acism_code_t min_child_code; /* Plus petit code suivant */
acism_code_t max_child_code; /* Plus grand code suivant */
size_t children_count; /* Nombre de codes suivants */
@@ -127,6 +129,7 @@ typedef union _acism_state_t
struct
{
uint8_t match : 1; /* Correspondance ici */
+ uint8_t single_source : 1; /* Unique source à notifier */
uint8_t atom_size; /* Indice de saut */
uint8_t suffix : 1; /* Correspondance ailleurs */
};
@@ -169,7 +172,7 @@ struct _GAcismBackend
bitfield_t *bitmap_usage; /* Localisation des usages */
acism_state_t *states; /* Tableau de transitions */
- patid_t *pids; /* Identifiants de motifs */
+ uint32_t *coverages; /* Bornes de suivi de positions*/
};
diff --git a/src/analysis/scan/patterns/backends/acism.c b/src/analysis/scan/patterns/backends/acism.c
index bceca09..a36e4b7 100644
--- a/src/analysis/scan/patterns/backends/acism.c
+++ b/src/analysis/scan/patterns/backends/acism.c
@@ -58,10 +58,10 @@ static void g_acism_backend_finalize(GAcismBackend *);
size_t g_acism_backend_get_atom_max_size(const GAcismBackend *);
/* Intègre un motif limité de contenu à rechercher. */
-static patid_t g_acism_backend_setup_for(GAcismBackend *, GScanContext *, const uint8_t *, size_t);
+static void g_acism_backend_setup_for(GAcismBackend *, const uint8_t *, size_t, uint32_t [2]);
/* Inscrit dans le moteur une chaîne de caractères à rechercher. */
-static patid_t g_acism_backend_enroll_plain_pattern(GAcismBackend *, GScanContext *, const uint8_t *, size_t);
+static bool g_acism_backend_enroll_plain_pattern(GAcismBackend *, const uint8_t *, size_t, uint32_t [2]);
#ifdef __USE_BYTE_FREQ
@@ -92,9 +92,15 @@ static void g_acism_backend_prepare_interleave_array(GAcismBackend *);
/* Compresse l'arborescence dans un tableau de position. */
static void g_acism_backend_build_interleave_array(GAcismBackend *);
+/* Détermine le nombre d'identifiants constitués. */
+static size_t g_acism_backend_count_plain_pattern_ids(const GAcismBackend *);
+
/* Met en ordre les derniers détails avant un premier scan. */
static void g_acism_backend_warm_up(GAcismBackend *);
+/* Récupère les identifiants finaux pour un motif recherché. */
+static patid_t g_acism_backend_build_plain_pattern_id(const GAcismBackend *, const uint32_t [2]);
+
/* Parcours un contenu binaire à la recherche de motifs. */
static void g_acism_backend_run_scan(const GAcismBackend *, GScanContext *);
@@ -142,6 +148,8 @@ static void g_acism_backend_class_init(GAcismBackendClass *klass)
backend->get_max_size = (get_backend_atom_max_size_fc)g_acism_backend_get_atom_max_size;
backend->enroll_plain = (enroll_plain_into_backend_fc)g_acism_backend_enroll_plain_pattern;
backend->warm_up = (warm_up_backend_fc)g_acism_backend_warm_up;
+ backend->build_id = (build_backend_plain_pattern_id_fc)g_acism_backend_build_plain_pattern_id;
+ backend->count_ids = (count_backend_plain_pattern_ids_fc)g_acism_backend_count_plain_pattern_ids;
backend->run_scan = (run_backend_scan_fc)g_acism_backend_run_scan;
backend->output = (output_backend_stats_fc)g_acism_backend_output_stats;
@@ -229,8 +237,8 @@ static void g_acism_backend_finalize(GAcismBackend *backend)
if (backend->states != NULL)
free(backend->states);
- if (backend->pids != NULL)
- free(backend->pids);
+ if (backend->coverages != NULL)
+ free(backend->coverages);
G_OBJECT_CLASS(g_acism_backend_parent_class)->finalize(G_OBJECT(backend));
@@ -292,9 +300,9 @@ size_t g_acism_backend_get_atom_max_size(const GAcismBackend *backend)
/******************************************************************************
* *
* Paramètres : backend = moteur de recherche à préparer. *
-* context = contexte de l'analyse à mener. *
-* plain = chaîne de caractères classique à intégrer. *
+* pattern = chaîne de caractères classique à intégrer. *
* len = taille de cette chaîne. *
+* tmp_id = identifiants temporaires vers le motif. [OUT] *
* *
* Description : Intègre un motif limité de contenu à rechercher. *
* *
@@ -304,15 +312,12 @@ size_t g_acism_backend_get_atom_max_size(const GAcismBackend *backend)
* *
******************************************************************************/
-static patid_t g_acism_backend_setup_for(GAcismBackend *backend, GScanContext *context, const uint8_t *pattern, size_t len)
+static void g_acism_backend_setup_for(GAcismBackend *backend, const uint8_t *pattern, size_t len, uint32_t tmp_id[2])
{
- patid_t result; /* Identifiant à retourner */
size_t i; /* Boucle de parcours */
int ret; /* Bilan d'une comparaison */
acism_source_t *source; /* Définition à mémoriser */
- result = INVALID_PATTERN_ID;
-
/*Recherche d'un motif déjà sollicité */
/**
@@ -332,15 +337,19 @@ static patid_t g_acism_backend_setup_for(GAcismBackend *backend, GScanContext *c
if (ret == 0)
{
- result = source->pid;
+ tmp_id[0] = i;
+ tmp_id[1] = source->coverage[SOURCE_COVERAGE_COUNT];
+
+ source->coverage[SOURCE_COVERAGE_COUNT]++;
break;
+
}
}
/* Introduction d'un nouveau motif au besoin */
- if (result == INVALID_PATTERN_ID)
+ if (i == backend->sources_count)
{
backend->sources = realloc(backend->sources, ++backend->sources_count * sizeof(acism_source_t));
@@ -349,8 +358,10 @@ static patid_t g_acism_backend_setup_for(GAcismBackend *backend, GScanContext *c
source->atoms = pattern;
source->len = len;
- result = g_scan_context_get_new_pattern_id(context);
- source->pid = result;
+ source->coverage[SOURCE_COVERAGE_COUNT] = 1;
+
+ tmp_id[0] = i;
+ tmp_id[1] = 0;
backend->nchars += len;
@@ -361,17 +372,15 @@ static patid_t g_acism_backend_setup_for(GAcismBackend *backend, GScanContext *c
}
- return result;
-
}
/******************************************************************************
* *
* Paramètres : backend = moteur de recherche à manipuler. *
-* context = contexte de l'analyse à mener. *
* plain = chaîne de caractères classique à intégrer. *
* len = taille de cette chaîne. *
+* tmp_id = identifiants temporaires vers le motif. [OUT] *
* *
* Description : Inscrit dans le moteur une chaîne de caractères à rechercher.*
* *
@@ -381,12 +390,14 @@ static patid_t g_acism_backend_setup_for(GAcismBackend *backend, GScanContext *c
* *
******************************************************************************/
-static patid_t g_acism_backend_enroll_plain_pattern(GAcismBackend *backend, GScanContext *context, const uint8_t *plain, size_t len)
+static bool g_acism_backend_enroll_plain_pattern(GAcismBackend *backend, const uint8_t *plain, size_t len, uint32_t tmp_id[2])
{
- patid_t result; /* Identifiant à retourner */
+ bool result; /* Bilan à retourner */
assert(len <= ACSIM_ATOM_SIZE);
+ result = true;
+
/**
* Le traitement différé des chaînes à rechercher permet deux choses :
* - la construction d'une table de permutation ;
@@ -405,7 +416,7 @@ static patid_t g_acism_backend_enroll_plain_pattern(GAcismBackend *backend, GSca
* moindre coût un jour.
*/
- result = g_acism_backend_setup_for(backend, context, plain, len);
+ g_acism_backend_setup_for(backend, plain, len, tmp_id);
return result;
@@ -505,6 +516,7 @@ static void g_acism_backend_define_codes(GAcismBackend *backend)
static void g_acism_backend_build_trie(GAcismBackend *backend)
{
size_t i; /* Boucle de parcours #1 */
+ uint32_t current_start; /* Indice de gestionnaire */
acism_trie_node_t *next; /* Prochain noeud disponible */
acism_trie_node_t *node; /* Tête de parcours */
acism_source_t *source; /* Définition à mémoriser */
@@ -520,6 +532,8 @@ static void g_acism_backend_build_trie(GAcismBackend *backend)
backend->nodes[i].max_child_code = MIN_ACISM_CODE;
}
+ current_start = 0;
+
next = backend->nodes + 1;
for (i = 0; i < backend->sources_count; i++)
@@ -528,6 +542,15 @@ static void g_acism_backend_build_trie(GAcismBackend *backend)
source = &backend->sources[i];
+ /* Mise à jour de la couverture des gestionnaires de suivi */
+
+ source->coverage[SOURCE_COVERAGE_START] = current_start;
+ source->coverage[SOURCE_COVERAGE_END] += current_start;
+
+ current_start = source->coverage[SOURCE_COVERAGE_END];
+
+ /* Parcours des noeuds contenus */
+
for (k = 0; k < source->len && node->child != NULL; k++)
{
#ifdef __USE_BYTE_FREQ
@@ -1026,6 +1049,8 @@ static void g_acism_backend_build_interleave_array(GAcismBackend *backend)
size_t i; /* Boucle de parcours #1 */
acism_trie_node_t *node; /* Noeud à transcrire */
acism_state_t *base; /* Base d'une série de cellules*/
+ uint32_t *coverage; /* Couverture des inscriptions */
+ acism_source_t *source; /* Définition originelle */
acism_trie_node_t *iter; /* Sous-noeud à inscrire #2 */
acism_trie_node_t *child; /* Sous-noeud à inscrire #3 */
uint16_t offset; /* Décalage local */
@@ -1033,7 +1058,7 @@ static void g_acism_backend_build_interleave_array(GAcismBackend *backend)
maxsize = get_bit_field_size(backend->bitmap_usage);
backend->states = calloc(maxsize, sizeof(acism_state_t));
- backend->pids = calloc(maxsize, sizeof(patid_t));
+ backend->coverages = calloc(maxsize, 2 * sizeof(uint32_t));
for (i = 0; i < backend->nodes_used; i++)
{
@@ -1045,10 +1070,15 @@ static void g_acism_backend_build_interleave_array(GAcismBackend *backend)
if (node->matched_atom > 0)
{
+ source = &backend->sources[node->matched_atom - 1];
+
base[0].match = 1;
+ base[0].single_source = source->coverage[SOURCE_COVERAGE_COUNT] == 1 ? 1 : 0;
base[0].atom_size = backend->sources[node->matched_atom - 1].len - 1;
+ coverage = &backend->coverages[node->state_index * 2];
- backend->pids[node->state_index] = backend->sources[node->matched_atom - 1].pid;
+ coverage[SOURCE_COVERAGE_START] = source->coverage[SOURCE_COVERAGE_START];
+ coverage[SOURCE_COVERAGE_COUNT] = source->coverage[SOURCE_COVERAGE_COUNT];
for (iter = node->parent->suffix_link; iter != NULL; iter = iter->suffix_link)
{
@@ -1065,6 +1095,7 @@ static void g_acism_backend_build_interleave_array(GAcismBackend *backend)
}
}
+
base[0].index = i == 0 ? 0 : node->suffix_link->state_index;
for (child = node->child; child != NULL; child = child->sibling)
@@ -1111,6 +1142,10 @@ static void g_acism_backend_warm_up(GAcismBackend *backend)
/**
* Construit une arborescence de lecture à partir des différents
* octets présents dans les motifs.
+ *
+ * Les couvertures des futurs tableaux de correspondances sont
+ * établies au passage, ouvrant la voie aux définitions d'identifiant
+ * pour les motifs enregistrés.
*/
g_acism_backend_build_trie(backend);
@@ -1134,6 +1169,58 @@ static void g_acism_backend_warm_up(GAcismBackend *backend)
/******************************************************************************
* *
* Paramètres : backend = moteur de recherche à manipuler. *
+* tmp_id = identifiants temporaires vers le motif. [OUT] *
+* *
+* Description : Récupère les identifiants finaux pour un motif recherché. *
+* *
+* Retour : Identifiant constitué ou INVALID_PATTERN_ID en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static patid_t g_acism_backend_build_plain_pattern_id(const GAcismBackend *backend, const uint32_t tmp_id[2])
+{
+ patid_t result; /* Identifiant à retourner */
+ acism_source_t *source; /* Motif d'origine concerné */
+
+ source = backend->sources + tmp_id[0];
+
+ result = source->coverage[SOURCE_COVERAGE_START] + tmp_id[1];
+
+ assert(result < source->coverage[SOURCE_COVERAGE_END]);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* *
+* Description : Détermine le nombre d'identifiants constitués. *
+* *
+* Retour : Quantité de gestionnaires de suivi à prévoir. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static size_t g_acism_backend_count_plain_pattern_ids(const GAcismBackend *backend)
+{
+ size_t result; /* Quantité à retourner */
+
+ result = backend->sources[backend->sources_count -1].coverage[SOURCE_COVERAGE_END];
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
* context = lieu d'enregistrement des résultats. *
* *
* Description : Parcours un contenu binaire à la recherche de motifs. *
@@ -1150,17 +1237,20 @@ static void g_acism_backend_run_scan(const GAcismBackend *backend, GScanContext
phys_t dlen; /* Quantité de données */
vmpa2t pos; /* Point de départ ciblé */
const bin_t *data; /* Données à analyser */
+ GUMemSlice **matches; /* Zones d'enregistrements */
#ifdef __USE_BYTE_FREQ
acism_code_t codes_for_bytes[256]; /* Copie des codes d'accès */
#endif
acism_state_t *root; /* Racine de l'arborescence */
- patid_t *pids; /* Identifiants de motifs */
+ uint32_t *coverages; /* Bornes de suivi de positions*/
unsigned int state; /* Tête de lecture courante */
phys_t i; /* Boucle de parcours #1 */
acism_code_t code; /* Code du caractère courant */
unsigned int next; /* Prochaine tête à valider */
acism_state_t next_state; /* Prochaine tête à valider */
- unsigned int iter; /* Boucle de parcours #2 */
+ uint32_t final_k; /* Dernier indice à traiter */
+ uint32_t k; /* Boucle de parcours #2 */
+ unsigned int iter; /* Boucle de parcours #3 */
acism_state_t test_state; /* Test de validité alternative*/
acism_state_t sub_state; /* Test de validité alternative*/
@@ -1171,6 +1261,8 @@ static void g_acism_backend_run_scan(const GAcismBackend *backend, GScanContext
g_binary_content_compute_start_pos(content, &pos);
data = g_binary_content_get_raw_access(content, &pos, dlen);
+ matches = g_scan_context_get_match_storages(context, (size_t []){ 0 });
+
/* Suivi via l'arborescence aplatie */
#ifdef __USE_BYTE_FREQ
@@ -1180,7 +1272,7 @@ static void g_acism_backend_run_scan(const GAcismBackend *backend, GScanContext
root = backend->states;
if (root == NULL) goto done;
- pids = backend->pids;
+ coverages = backend->coverages;
state = ROOT_STATE_INDEX;
@@ -1217,9 +1309,19 @@ static void g_acism_backend_run_scan(const GAcismBackend *backend, GScanContext
if (next_state.match)
{
- g_scan_context_register_atom_match(context,
- pids[next],
- i - next_state.atom_size);
+ k = coverages[next * 2 + SOURCE_COVERAGE_START];
+
+ if (next_state.single_source)
+ g_umem_slice_put_uint64(matches[k], i - next_state.atom_size);
+
+ else
+ {
+ final_k = coverages[next * 2 + SOURCE_COVERAGE_END];
+
+ for (; k < final_k; k++)
+ g_umem_slice_put_uint64(matches[k], i - next_state.atom_size);
+
+ }
if (next_state.suffix)
{
@@ -1235,9 +1337,19 @@ static void g_acism_backend_run_scan(const GAcismBackend *backend, GScanContext
{
assert(sub_state.atom_size < next_state.atom_size);
- g_scan_context_register_atom_match(context,
- pids[test_state.index],
- i - sub_state.atom_size);
+ k = coverages[test_state.index * 2 + SOURCE_COVERAGE_START];
+
+ if (sub_state.single_source)
+ g_umem_slice_put_uint64(matches[k], i - sub_state.atom_size);
+
+ else
+ {
+ final_k = coverages[test_state.index * 2 + SOURCE_COVERAGE_END];
+
+ for (; k < final_k; k++)
+ g_umem_slice_put_uint64(matches[k], i - sub_state.atom_size);
+
+ }
}
diff --git a/src/analysis/scan/patterns/backends/bitap.c b/src/analysis/scan/patterns/backends/bitap.c
index 99e16e5..af50c6d 100644
--- a/src/analysis/scan/patterns/backends/bitap.c
+++ b/src/analysis/scan/patterns/backends/bitap.c
@@ -517,7 +517,7 @@ static patid_t enroll_plain_pattern_avx2(GBitapBackend *backend, GScanContext *c
last->m[n] = plen;
- result = g_scan_context_get_new_pattern_id(context);
+ result = 0; // FIXME g_scan_context_get_new_pattern_id(context);
last->found_id[n] = result;
@@ -934,9 +934,11 @@ static void run_scan_avx2(const GBitapBackend *backend, GScanContext *context, c
{
//assert((i + 1) >= group.m[j]);
+ /** TODO : update call
g_scan_context_register_atom_match(context,
group.found_id[j],
(iter - data) + 1 - group.m[j]);
+ **/
}
@@ -1108,9 +1110,11 @@ static void run_scan_avx2(const GBitapBackend *backend, GScanContext *context, c
{
//assert((i + 1) >= group.m[j]);
+ /** TODO : update call
g_scan_context_register_atom_match(context,
group.found_id[j],
(iter - data) + 1 - group.m[j]);
+ **/
}
@@ -1617,7 +1621,7 @@ static patid_t enroll_plain_pattern_avx512(GBitapBackend *backend, GScanContext
last->m[n] = plen;
- result = g_scan_context_get_new_pattern_id(context);
+ result = 0; // FIXME g_scan_context_get_new_pattern_id(context);
last->found_id[n] = result;
@@ -1925,9 +1929,11 @@ static void run_scan_avx512(const GBitapBackend *backend, GScanContext *context,
{
//assert((i + 1) >= group.m[j]);
+ /** TODO : update call
g_scan_context_register_atom_match(context,
group.found_id[j],
(iter - data) + 1 - group.m[j]);
+ **/
}
@@ -1946,9 +1952,11 @@ static void run_scan_avx512(const GBitapBackend *backend, GScanContext *context,
{
//assert((i + 1) >= group.m[j]);
+ /** TODO : update call
g_scan_context_register_atom_match(context,
_group->found_id[j],
(iter - data) + 1 - _group->m[j]);
+ **/
}
diff --git a/src/analysis/scan/patterns/patid.h b/src/analysis/scan/patterns/patid.h
new file mode 100644
index 0000000..e8b7eee
--- /dev/null
+++ b/src/analysis/scan/patterns/patid.h
@@ -0,0 +1,36 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * patid.h - prototypes pour la définition d'un identifiant de motif partiel
+ *
+ * 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_PATTERNS_PATID_H
+#define _ANALYSIS_SCAN_PATTERNS_PATID_H
+
+
+
+/* Identifiant de motif intégré */
+typedef uint32_t patid_t;
+
+#define INVALID_PATTERN_ID 0xffffffff
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_PATID_H */
diff --git a/src/analysis/scan/patterns/token.c b/src/analysis/scan/patterns/token.c
index e5eb287..76a5e66 100644
--- a/src/analysis/scan/patterns/token.c
+++ b/src/analysis/scan/patterns/token.c
@@ -248,7 +248,6 @@ bool g_bytes_token_is_private(const GBytesToken *token)
/******************************************************************************
* *
* Paramètres : token = définition de la bribe à enregistrer. *
-* context = contexte de l'analyse à mener. *
* backend = moteur de recherche à préchauffer. *
* maxsize = taille max. des atomes (mise en commun optimisée). *
* *
@@ -260,13 +259,37 @@ bool g_bytes_token_is_private(const GBytesToken *token)
* *
******************************************************************************/
-bool g_bytes_token_enroll(GBytesToken *token, GScanContext *context, GEngineBackend *backend, size_t maxsize)
+bool g_bytes_token_enroll(GBytesToken *token, GEngineBackend *backend, size_t maxsize)
{
bool result; /* Statut à retourner */
token->need_backward = g_scan_token_node_setup_tree(token->root);
- result = g_scan_token_node_enroll(token->root, context, backend, maxsize, &token->slow);
+ result = g_scan_token_node_enroll(token->root, backend, maxsize, &token->slow);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : token = définition de la bribe à peaufiner. *
+* backend = moteur de recherche à préchauffer. *
+* *
+* Description : Récupère les identifiants finaux pour un motif recherché. *
+* *
+* Retour : Bilan de l'opération à renvoyer. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_bytes_token_build_id(GBytesToken *token, GEngineBackend *backend)
+{
+ bool result; /* Statut à retourner */
+
+ result = g_scan_token_node_build_id(token->root, backend);
return result;
@@ -276,8 +299,6 @@ bool g_bytes_token_enroll(GBytesToken *token, GScanContext *context, GEngineBack
/******************************************************************************
* *
* Paramètres : token = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
* matches = suivi des correspondances à consolider. *
* *
* Description : Transforme les correspondances locales en trouvailles. *
@@ -288,60 +309,98 @@ bool g_bytes_token_enroll(GBytesToken *token, GScanContext *context, GEngineBack
* *
******************************************************************************/
-void g_bytes_token_check(const GBytesToken *token, GScanContext *context, GBinContent *content, pending_matches_t *matches)
+void g_bytes_token_check(const GBytesToken *token, GScanBytesMatches *matches)
{
- size_t p; /* Boucle de parcours #3 */
- match_area_t *pending; /* Correspondance à traiter */
+ scan_node_check_params_t params; /* Rassemblement de paramètres */
+ vmpa2t start; /* Point de début du contenu */
+ vmpa2t end; /* Point de fin du contenu */
+ match_area_t *area; /* Correspondance à valider */
+ match_area_t *next; /* Correspondance suivante */
vmpa2t pos; /* Tête de lecture */
const bin_t *byte; /* Octet à valider */
- g_scan_token_node_check_forward(token->root, context, content, matches);
+ /* Définition d'un contexte */
+
+ params.context = g_scan_bytes_matches_get_context(matches);
+ params.content = g_scan_context_get_content(params.context);
+ params.allocator = g_umem_slice_new(sizeof(match_area_t));
+
+ g_binary_content_compute_start_pos(params.content, &start);
+ g_binary_content_compute_end_pos(params.content, &end);
+
+ params.content_start = start.physical;
+ params.content_end = end.physical;
+
+ // offset
+
+ params.initialized = false;
+
+ params.main_areas = NULL;
+ params.main_count = 0;
+
+ params.created_areas = NULL;
+ params.created_count = 0;
+
+ params.kept_areas = NULL;
+ params.kept_count = 0;
+
+ /* Lancement des analyses */
+
+ g_scan_token_node_check_forward(token->root, &params);
if (token->need_backward)
- g_scan_token_node_check_backward(token->root, context, content, matches);
+ g_scan_token_node_check_backward(token->root, &params);
- sort_and_filter_pending_matches(matches);
+ // REMME ? sort_and_filter_pending_matches(matches);
if (token->fullword)
{
- reset_pending_matches_ttl(matches);
-
- for (p = 0; p < matches->used; p++)
+ for_each_match_area_safe(area, &params.main_areas, next)
{
- pending = &matches->areas[p];
-
/* Validation de l'octet précédent, s'il existe */
- if (pending->start > matches->content_start)
+ if (area->start > params.content_start)
{
- init_vmpa(&pos, pending->start - 1, VMPA_NO_VIRTUAL);
+ init_vmpa(&pos, area->start - 1, VMPA_NO_VIRTUAL);
- byte = g_binary_content_get_raw_access(content, &pos, 1);
+ byte = g_binary_content_get_raw_access(params.content, &pos, 1);
if (isalnum(*byte))
+ {
+ del_match_area(area, &params.main_areas);
+ assert(&params.main_count > 0);
+ params.main_count--;
continue;
+ }
}
/* Validation de l'octet suivant, s'il existe */
- if (pending->end < matches->content_end)
+ if (area->end < params.content_end)
{
- init_vmpa(&pos, pending->end, VMPA_NO_VIRTUAL);
+ init_vmpa(&pos, area->end, VMPA_NO_VIRTUAL);
- byte = g_binary_content_get_raw_access(content, &pos, 1);
+ byte = g_binary_content_get_raw_access(params.content, &pos, 1);
if (isalnum(*byte))
+ {
+ del_match_area(area, &params.main_areas);
+ assert(&params.main_count > 0);
+ params.main_count--;
continue;
+ }
}
- keep_pending_match(pending);
-
}
- purge_pending_matches(matches);
-
}
+ g_scan_bytes_matches_set_list(matches, params.main_areas, params.main_count);
+
+ g_object_unref(G_OBJECT(params.context));
+ g_object_unref(G_OBJECT(params.content));
+ //g_object_unref(G_OBJECT(params.allocator));
+
}
@@ -394,17 +453,20 @@ char *g_bytes_token_get_modifier_path(const GBytesToken *token, size_t index)
static void g_bytes_token_output_to_text(const GBytesToken *pattern, GScanContext *context, int fd)
{
- const GScanMatch **matches; /* Correspondances établies */
- size_t count; /* Quantité de cette liste */
- size_t i; /* Boucle de parcours */
+ GScanMatches *matches; /* Correspondances établies */
if (g_bytes_token_is_private(pattern))
return;
- matches = g_scan_context_get_full_matches(context, G_SEARCH_PATTERN(pattern), &count);
+ matches = g_scan_context_get_full_matches(context, G_SEARCH_PATTERN(pattern));
- for (i = 0; i < count; i++)
- g_scan_match_output_to_text(matches[i], fd);
+ if (matches != NULL)
+ {
+ g_scan_matches_output_to_text(matches, fd);
+
+ g_object_unref(G_OBJECT(matches));
+
+ }
}
@@ -427,57 +489,19 @@ static void g_bytes_token_output_to_text(const GBytesToken *pattern, GScanContex
static void g_bytes_token_output_to_json(const GBytesToken *pattern, GScanContext *context, const sized_string_t *padding, unsigned int level, int fd)
{
- unsigned int i; /* Boucle de parcours #1 */
- const GScanMatch **matches; /* Correspondances établies */
- size_t count; /* Quantité de cette liste */
- char value[ULLONG_MAXLEN]; /* Impression de la position */
- int ret; /* Bilan d'une conversion */
- size_t k; /* Boucle de parcours #2 */
- bool trailing; /* Virgule finale */
+ GScanMatches *matches; /* Correspondances établies */
if (g_bytes_token_is_private(pattern))
return;
- matches = g_scan_context_get_full_matches(context, G_SEARCH_PATTERN(pattern), &count);
-
- /* Nombre de correspondances */
-
- for (i = 0; i < level; i++)
- write(fd, padding->data, padding->len);
+ matches = g_scan_context_get_full_matches(context, G_SEARCH_PATTERN(pattern));
- write(fd, "\"match_count\": ", 15);
-
- ret = snprintf(value, ULLONG_MAXLEN, "%zu", count);
-
- if (ret > 0)
- write(fd, value, ret);
-
- else
- {
- log_simple_message(LMT_EXT_ERROR, "Error while converting value!");
- write(fd, "null", 4);
- }
-
- write(fd, ",\n", 2);
-
- /* Détail des correspondances */
-
- for (i = 0; i < level; i++)
- write(fd, padding->data, padding->len);
-
- write(fd, "\"matches\": [\n", 13);
-
- for (k = 0; k < count; k++)
+ if (matches != NULL)
{
- trailing = ((k + 1) < count);
-
- g_scan_match_output_to_json(matches[k], padding, level + 1, fd, trailing);
+ g_scan_matches_output_to_json(matches, padding, level, fd);
+
+ g_object_unref(G_OBJECT(matches));
}
- for (i = 0; i < level; i++)
- write(fd, padding->data, padding->len);
-
- write(fd, "]\n", 2);
-
}
diff --git a/src/analysis/scan/patterns/token.h b/src/analysis/scan/patterns/token.h
index 2816bf8..3bc5cb7 100644
--- a/src/analysis/scan/patterns/token.h
+++ b/src/analysis/scan/patterns/token.h
@@ -30,7 +30,7 @@
#include "backend.h"
#include "tokens/node.h"
-#include "../matches/pending.h"
+#include "../matches/bytes.h"
@@ -59,10 +59,13 @@ bool g_bytes_token_target_fullword(const GBytesToken *);
bool g_bytes_token_is_private(const GBytesToken *);
/* Inscrit la définition d'un motif dans un moteur de recherche. */
-bool g_bytes_token_enroll(GBytesToken *, GScanContext *, GEngineBackend *, size_t);
+bool g_bytes_token_enroll(GBytesToken *, GEngineBackend *, size_t);
+
+/* Récupère les identifiants finaux pour un motif recherché. */
+bool g_bytes_token_build_id(GBytesToken *, GEngineBackend *);
/* Transforme les correspondances locales en trouvailles. */
-void g_bytes_token_check(const GBytesToken *, GScanContext *, GBinContent *, pending_matches_t *);
+void g_bytes_token_check(const GBytesToken *, GScanBytesMatches *);
/* Retrouve l'origine d'une correspondance à partir d'un indice. */
char *g_bytes_token_get_modifier_path(const GBytesToken *, size_t);
diff --git a/src/analysis/scan/patterns/tokens/atom.c b/src/analysis/scan/patterns/tokens/atom.c
index 01da28d..580ad30 100644
--- a/src/analysis/scan/patterns/tokens/atom.c
+++ b/src/analysis/scan/patterns/tokens/atom.c
@@ -26,6 +26,7 @@
#include <assert.h>
#include <malloc.h>
+#include <math.h>
@@ -168,6 +169,8 @@ void find_best_atom(const sized_binary_t *raw, size_t maxsize, tracked_scan_atom
atom->len = raw->len;
atom->rem = 0;
+ atom->fast_check = true;
+
if (letters != NULL)
{
*letters = 0;
@@ -240,11 +243,16 @@ void find_best_atom(const sized_binary_t *raw, size_t maxsize, tracked_scan_atom
atom->rem = raw->len - atom->pos - maxsize;
+ atom->fast_check = false;
+
if (letters != NULL)
*letters = best_letters;
}
+ assert((atom->fast_check && atom->pos == 0 && atom->rem == 0)
+ || (!atom->fast_check && (atom->pos != 0 || atom->rem != 0)));
+
}
@@ -340,11 +348,11 @@ sized_binary_t *make_atoms_case_insensitive(const sized_binary_t *src, const tra
/******************************************************************************
* *
-* Paramètres : byte = octet partiel à interpréter. *
-* mask = valeur du masque à appliquer. *
+* Paramètres : bytes = octets partiels avec leur masque à interpréter. *
+* len = quantité d'octets à interpréter. *
* produced = nombre de contenus générés. [OUT] *
* *
-* Description : Etablit la liste des cas de figures avec un octet partiel. *
+* Description : Etablit la liste des cas de figures avec des octets partiels.*
* *
* Retour : Liste de toutes les combinaisons possibles. *
* *
@@ -352,28 +360,66 @@ sized_binary_t *make_atoms_case_insensitive(const sized_binary_t *src, const tra
* *
******************************************************************************/
-sized_binary_t *make_atoms_from_masked_byte(bin_t value, bin_t mask, size_t *produced)
+sized_binary_t *make_atoms_from_masked_bytes(const masked_byte_t *bytes, size_t len, size_t *produced)
{
sized_binary_t *result; /* Liste à retourner */
+ size_t seq_len; /* Taille de séquence retenue */
+ size_t repeat_times; /* Répétitions pour remplissage*/
+ sized_binary_t *maxiter; /* Borne de fin de parcours */
size_t i; /* Boucle de parcours #1 */
+ sized_binary_t *iter; /* Boucle de parcours #2 */
+ size_t j; /* Boucle de parcours #3 */
+ size_t k; /* Boucle de parcours #4 */
+
+ seq_len = (len > MASK_MAX_LEN_FOR_ATOMS ? MASK_MAX_LEN_FOR_ATOMS : len);
+
+ /**
+ * Si l'usage de la fonction pow() disparaît, la bibliothèque m
+ * peut être retirée de libchrysacore_la_LDFLAGS dans le Makefile
+ * principal.
+ */
+ repeat_times = pow(16, seq_len - 1);
- *produced = 16;
+ *produced = 16 * repeat_times;
/* Création du réceptacle */
- result = malloc(16 * sizeof(tracked_scan_atom_t));
+ result = malloc(*produced * sizeof(tracked_scan_atom_t));
+
+ maxiter = result + *produced;
/* Remplissage */
- for (i = 0; i < 16; i++)
+ for (i = 0; i < seq_len; i++)
{
- result[i].data = malloc(1);
- result[i].len = 1;
+ for (iter = result; iter < maxiter; )
+ {
+ for (j = 0; j < 16; j++)
+ {
+ assert(bytes[i].mask == 0x0f || bytes[i].mask == 0xf0);
- if (mask == 0x0f)
- result[i].data[0] = value | (i << 4);
- else
- result[i].data[0] = value | i;
+ for (k = 0; k < repeat_times; k++)
+ {
+ if (i == 0)
+ {
+ iter->data = malloc(seq_len);
+ iter->len = seq_len;
+ }
+
+ if (bytes[i].mask == 0x0f)
+ iter->data[i] = bytes[i].value | (j << 4);
+ else
+ iter->data[i] = bytes[i].value | j;
+
+ iter++;
+
+ }
+
+ }
+
+ }
+
+ repeat_times /= 16;
}
@@ -385,11 +431,10 @@ sized_binary_t *make_atoms_from_masked_byte(bin_t value, bin_t mask, size_t *pro
/******************************************************************************
* *
* Paramètres : raw = définition de la bribe à enregistrer. *
-* context = contexte de l'analyse à mener. *
* backend = moteur de recherche à préchauffer. *
* atom = informations de suivi constituées. [OUT] *
* *
-* Description : Enregistre l'atome déterminé d'une série d'octets. *
+* Description : Amorce l'insertion de l'atome déterminé d'une série d'octets.*
* *
* Retour : Bilan de l'opération à renvoyer. *
* *
@@ -397,14 +442,38 @@ sized_binary_t *make_atoms_from_masked_byte(bin_t value, bin_t mask, size_t *pro
* *
******************************************************************************/
-bool enroll_prepared_atom(const sized_binary_t *raw, GScanContext *context, GEngineBackend *backend, tracked_scan_atom_t *atom)
+bool enroll_prepared_atom(const sized_binary_t *raw, GEngineBackend *backend, tracked_scan_atom_t *atom)
{
bool result; /* Statut à retourner */
const bin_t *data; /* Données à rechercher */
data = raw->data + atom->pos;
- atom->pid = g_engine_backend_enroll_plain_pattern(backend, context, data, atom->len);
+ result = g_engine_backend_enroll_plain_pattern(backend, data, atom->len, atom->tmp_id);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : atom = informations de suivi constituées. [OUT] *
+* backend = moteur de recherche à préchauffer. *
+* *
+* Description : Récupère un identifiant final pour un atome d'octets. *
+* *
+* Retour : Bilan de l'opération à renvoyer. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool build_atom_pattern_id(tracked_scan_atom_t *atom, GEngineBackend *backend)
+{
+ bool result; /* Statut à retourner */
+
+ atom->pid = g_engine_backend_build_plain_pattern_id(backend, atom->tmp_id);
result = (atom->pid != INVALID_PATTERN_ID);
diff --git a/src/analysis/scan/patterns/tokens/atom.h b/src/analysis/scan/patterns/tokens/atom.h
index 2fbc19e..1d912d7 100644
--- a/src/analysis/scan/patterns/tokens/atom.h
+++ b/src/analysis/scan/patterns/tokens/atom.h
@@ -29,7 +29,6 @@
#include "../backend.h"
-#include "../../context.h"
#include "../../../../arch/vmpa.h"
#include "../../../../common/bits.h"
#include "../../../../common/szstr.h"
@@ -43,11 +42,14 @@ typedef struct _tracked_scan_atom_t
phys_t len; /* Taille de ladite sélection */
phys_t rem; /* Reste après l'atome */
+ bool fast_check; /* Besoin de vérifications ? */
+
+ uint32_t tmp_id[2]; /* Couple d'identifiants temp. */
+
patid_t pid; /* Identifiant de la bribe */
} tracked_scan_atom_t;
-
/* Note l'intêret de rechercher un octet particulier. */
int rate_byte_quality(bin_t, bitfield_t *, size_t *);
@@ -60,11 +62,24 @@ void find_best_atom(const sized_binary_t *, size_t , tracked_scan_atom_t *, size
/* Etablit la liste des cas de figures ignorant la casse. */
sized_binary_t *make_atoms_case_insensitive(const sized_binary_t *, const tracked_scan_atom_t *, size_t);
-/* Etablit la liste des cas de figures avec un octet partiel. */
-sized_binary_t *make_atoms_from_masked_byte(bin_t, bin_t, size_t *);
+/* Mémorisation d'un octet visé avec son masque */
+typedef struct _masked_byte_t
+{
+ bin_t value; /* Valeur de l'octet visé */
+ bin_t mask; /* Masque à appliquer */
+
+} masked_byte_t;
+
+#define MASK_MAX_LEN_FOR_ATOMS 2
+
+/* Etablit la liste des cas de figures avec des octets partiels. */
+sized_binary_t *make_atoms_from_masked_bytes(const masked_byte_t *, size_t, size_t *);
+
+/* Amorce l'insertion de l'atome déterminé d'une série d'octets. */
+bool enroll_prepared_atom(const sized_binary_t *, GEngineBackend *, tracked_scan_atom_t *);
-/* Enregistre l'atome déterminé d'une série d'octets. */
-bool enroll_prepared_atom(const sized_binary_t *, GScanContext *, GEngineBackend *, tracked_scan_atom_t *);
+/* Récupère un identifiant final pour un atome d'octets. */
+bool build_atom_pattern_id(tracked_scan_atom_t *, GEngineBackend *);
diff --git a/src/analysis/scan/patterns/tokens/node-int.h b/src/analysis/scan/patterns/tokens/node-int.h
index 091a5be..520e2a4 100644
--- a/src/analysis/scan/patterns/tokens/node-int.h
+++ b/src/analysis/scan/patterns/tokens/node-int.h
@@ -28,9 +28,9 @@
#include "node.h"
-#include "offset.h"
-
+/* Communique l'intérêt d'un noeud au sein d'une analyse. */
+typedef float (* compute_scan_token_node_weight_fc) (const GScanTokenNode *);
/* Prend acte d'une nouvelle propriété pour le noeud. */
typedef void (* apply_scan_token_node_flags_fc) (GScanTokenNode *, ScanTokenNodeFlags);
@@ -38,23 +38,30 @@ typedef void (* apply_scan_token_node_flags_fc) (GScanTokenNode *, ScanTokenNode
/* Noeuds clefs de l'arborescence mise en place */
typedef struct _scan_tree_points_t
{
- GScanTokenNode *first_node; /* Premier noeud de traitement */
- GScanTokenNode *last_node; /* Dernier noeud de traitement */
-
GScanTokenNode *first_plain; /* Premier noeud textuel */
GScanTokenNode *best_masked; /* Noeud masqué le plus long */
} scan_tree_points_t;
-
/* Parcourt une arborescence de noeuds et y relève des éléments. */
typedef void (* visit_scan_token_node_fc) (GScanTokenNode *, scan_tree_points_t *);
/* Inscrit la définition d'un motif dans un moteur de recherche. */
-typedef bool (* enroll_scan_token_node_fc) (GScanTokenNode *, GScanContext *, GEngineBackend *, size_t, size_t *);
+typedef bool (* enroll_scan_token_node_fc) (GScanTokenNode *, GEngineBackend *, size_t, size_t *);
+
+/* Récupère un identifiant final pour un atome d'octets. */
+typedef bool (* build_scan_token_node_id_fc) (GScanTokenNode *, GEngineBackend *);
+
+typedef enum _TokenNodeCheckFlags
+{
+ TNCF_UPDATE_IN_PLACE = (1 << 0), /* Actualisation de l'entrée */
+ TNCF_CREATE_NEW = (1 << 1), /* Allocation de positions */
+ TNCF_KEEP_DISCARDED = (1 << 2), /* Inversion des résultats */
+
+} TokenNodeCheckFlags;
/* Transforme les correspondances locales en trouvailles. */
-typedef void (* check_scan_token_node_fc) (const GScanTokenNode *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *);
+typedef void (* check_scan_token_node_fc) (const GScanTokenNode *, scan_node_check_params_t *, TokenNodeCheckFlags, bool *);
/* Décomposition d'un motif de recherche en atomes (instance) */
@@ -71,10 +78,12 @@ struct _GScanTokenNodeClass
{
GObjectClass parent; /* A laisser en premier */
+ compute_scan_token_node_weight_fc compute_weight; /* Evaluation */
+ visit_scan_token_node_fc visit; /* Phase de répérage initial */
apply_scan_token_node_flags_fc apply; /* Prise en compte de fanions */
- visit_scan_token_node_fc visit; /* Phase de répérage initial */
enroll_scan_token_node_fc enroll; /* Inscription d'un motif */
+ build_scan_token_node_id_fc build_id; /* Récupération d'identifiant */
check_scan_token_node_fc check_forward; /* Conversion en trouvailles */
check_scan_token_node_fc check_backward;/* Conversion en trouvailles */
@@ -86,13 +95,13 @@ struct _GScanTokenNodeClass
void g_scan_token_node_visit(GScanTokenNode *, scan_tree_points_t *);
/* Inscrit la définition d'un motif dans un moteur de recherche. */
-bool _g_scan_token_node_enroll(GScanTokenNode *, GScanContext *, GEngineBackend *, size_t, size_t *);
+bool _g_scan_token_node_enroll(GScanTokenNode *, GEngineBackend *, size_t, size_t *);
/* Transforme les correspondances locales en trouvailles. */
-void _g_scan_token_node_check_forward(const GScanTokenNode *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *);
+void _g_scan_token_node_check_forward(const GScanTokenNode *, scan_node_check_params_t *, TokenNodeCheckFlags, bool *);
/* Transforme les correspondances locales en trouvailles. */
-void _g_scan_token_node_check_backward(const GScanTokenNode *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *);
+void _g_scan_token_node_check_backward(const GScanTokenNode *, scan_node_check_params_t *, TokenNodeCheckFlags, bool *);
diff --git a/src/analysis/scan/patterns/tokens/node.c b/src/analysis/scan/patterns/tokens/node.c
index 71fcf05..767cc6d 100644
--- a/src/analysis/scan/patterns/tokens/node.c
+++ b/src/analysis/scan/patterns/tokens/node.c
@@ -143,6 +143,38 @@ static void g_scan_token_node_finalize(GScanTokenNode *node)
* *
* Paramètres : node = noeud de motif à consulter. *
* *
+* Description : Communique l'intérêt d'un noeud au sein d'une analyse. *
+* *
+* Retour : Poids de l'importance pour un départ de scan. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+float g_scan_token_node_compute_weight_for_scan(const GScanTokenNode *node)
+{
+ float result; /* Valeur à retourner */
+ GScanTokenNodeClass *class; /* Classe de l'instance */
+
+ class = G_SCAN_TOKEN_NODE_GET_CLASS(node);
+
+ if (class->compute_weight != NULL)
+ result = class->compute_weight(node);
+ else
+ result = 0;
+
+ return result;
+
+}
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : node = noeud de motif à consulter. *
+* *
* Description : Indique les propriétés particulières d'un noeud d'analyse. *
* *
* Retour : Propriétés particulières associées au noeud. *
@@ -206,15 +238,6 @@ void g_scan_token_node_visit(GScanTokenNode *node, scan_tree_points_t *points)
{
GScanTokenNodeClass *class; /* Classe de l'instance */
- if (node->flags & STNF_PROD)
- {
- if (points->first_node == NULL)
- points->first_node = node;
-
- points->last_node = node;
-
- }
-
class = G_SCAN_TOKEN_NODE_GET_CLASS(node);
if (class->visit != NULL)
@@ -243,9 +266,6 @@ bool g_scan_token_node_setup_tree(GScanTokenNode *node)
/* Phase de localisation */
- points.first_node = NULL;
- points.last_node = NULL;
-
points.first_plain = NULL;
points.best_masked = NULL;
@@ -253,9 +273,8 @@ bool g_scan_token_node_setup_tree(GScanTokenNode *node)
/* Phase d'application */
- // TODO : REMME
- //g_scan_token_node_set_flags(points.first_node, STNF_FIRST);
- //g_scan_token_node_set_flags(points.last_node, STNF_LAST);
+ g_scan_token_node_set_flags(node, STNF_FIRST);
+ g_scan_token_node_set_flags(node, STNF_LAST);
if (points.first_plain != NULL)
main = points.first_plain;
@@ -264,11 +283,11 @@ bool g_scan_token_node_setup_tree(GScanTokenNode *node)
main = points.best_masked;
else
- main = node;//points.first_node;
+ main = node;
g_scan_token_node_set_flags(main, STNF_MAIN);
- result = (main != node/*points.first_node*/);
+ result = (main != node);
return result;
@@ -278,7 +297,6 @@ bool g_scan_token_node_setup_tree(GScanTokenNode *node)
/******************************************************************************
* *
* Paramètres : node = définition de la bribe à enregistrer. *
-* context = contexte de l'analyse à mener. *
* backend = moteur de recherche à préchauffer. *
* maxsize = taille max. des atomes (mise en commun optimisée). *
* slow = niveau de ralentissement induit (0 = idéal). [OUT] *
@@ -291,14 +309,14 @@ bool g_scan_token_node_setup_tree(GScanTokenNode *node)
* *
******************************************************************************/
-bool _g_scan_token_node_enroll(GScanTokenNode *node, GScanContext *context, GEngineBackend *backend, size_t maxsize, size_t *slow)
+bool _g_scan_token_node_enroll(GScanTokenNode *node, GEngineBackend *backend, size_t maxsize, size_t *slow)
{
bool result; /* Statut à retourner */
GScanTokenNodeClass *class; /* Classe de l'instance */
class = G_SCAN_TOKEN_NODE_GET_CLASS(node);
- result = class->enroll(node, context, backend, maxsize, slow);
+ result = class->enroll(node, backend, maxsize, slow);
return result;
@@ -308,7 +326,6 @@ bool _g_scan_token_node_enroll(GScanTokenNode *node, GScanContext *context, GEng
/******************************************************************************
* *
* Paramètres : node = définition de la bribe à enregistrer. *
-* context = contexte de l'analyse à mener. *
* backend = moteur de recherche à préchauffer. *
* maxsize = taille max. des atomes (mise en commun optimisée). *
* slow = niveau de ralentissement induit (0 = idéal). [OUT] *
@@ -321,7 +338,7 @@ bool _g_scan_token_node_enroll(GScanTokenNode *node, GScanContext *context, GEng
* *
******************************************************************************/
-bool g_scan_token_node_enroll(GScanTokenNode *node, GScanContext *context, GEngineBackend *backend, size_t maxsize, size_t *slow)
+bool g_scan_token_node_enroll(GScanTokenNode *node, GEngineBackend *backend, size_t maxsize, size_t *slow)
{
bool result; /* Statut à retourner */
@@ -329,7 +346,37 @@ bool g_scan_token_node_enroll(GScanTokenNode *node, GScanContext *context, GEngi
*slow = 0;
- result = _g_scan_token_node_enroll(node, context, backend, maxsize, slow);
+ result = _g_scan_token_node_enroll(node, backend, maxsize, slow);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : node = définition de la bribe à peaufiner. *
+* backend = moteur de recherche à préchauffer. *
+* *
+* Description : Récupère un identifiant final pour un atome d'octets. *
+* *
+* Retour : Bilan de l'opération à renvoyer. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_token_node_build_id(GScanTokenNode *node, GEngineBackend *backend)
+{
+ bool result; /* Statut à retourner */
+ GScanTokenNodeClass *class; /* Classe de l'instance */
+
+ class = G_SCAN_TOKEN_NODE_GET_CLASS(node);
+
+ if (class->build_id == NULL)
+ result = true;
+ else
+ result = class->build_id(node, backend);
return result;
@@ -338,13 +385,10 @@ bool g_scan_token_node_enroll(GScanTokenNode *node, GScanContext *context, GEngi
/******************************************************************************
* *
-* Paramètres : node = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
-* matches = suivi des correspondances à consolider. *
-* offset = tolérance dans les positions à appliquer. *
-* not = indique si les résultats doivent être inversés. *
-* skip = détermine si l'analyse est différée. [OUT] *
+* Paramètres : node = définition de la bribe à manipuler. *
+* params = accès direct aux éléments utiles aux validations. *
+* cflags = altérations de traitement à respecter. *
+* skip = détermine si l'analyse est différée. [OUT] *
* *
* Description : Transforme les correspondances locales en trouvailles. *
* *
@@ -354,7 +398,7 @@ bool g_scan_token_node_enroll(GScanTokenNode *node, GScanContext *context, GEngi
* *
******************************************************************************/
-void _g_scan_token_node_check_forward(const GScanTokenNode *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip)
+void _g_scan_token_node_check_forward(const GScanTokenNode *node, scan_node_check_params_t *params, TokenNodeCheckFlags cflags, bool *skip)
{
GScanTokenNodeClass *class; /* Classe de l'instance */
@@ -366,17 +410,15 @@ void _g_scan_token_node_check_forward(const GScanTokenNode *node, GScanContext *
class = G_SCAN_TOKEN_NODE_GET_CLASS(node);
- class->check_forward(node, context, content, matches, offset, not, skip);
+ class->check_forward(node, params, cflags, skip);
}
/******************************************************************************
* *
-* Paramètres : node = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
-* matches = suivi des correspondances à consolider. *
+* Paramètres : node = définition de la bribe à manipuler. *
+* params = accès direct aux éléments utiles aux validations. *
* *
* Description : Transforme les correspondances locales en trouvailles. *
* *
@@ -386,9 +428,9 @@ void _g_scan_token_node_check_forward(const GScanTokenNode *node, GScanContext *
* *
******************************************************************************/
-void g_scan_token_node_check_forward(const GScanTokenNode *node, GScanContext *context, GBinContent *content, pending_matches_t *matches)
+void g_scan_token_node_check_forward(const GScanTokenNode *node, scan_node_check_params_t *params)
{
- node_search_offset_t offset; /* Espace des correspondances */
+ node_search_offset_t offset; /* Espace des correspondances */
bool skip; /* Mise en attente des analyses*/
size_t ocount; /* Quantité de bornes présentes*/
node_offset_range_t * const *ranges_ptr;/* Bornes d'espace à parcourir */
@@ -401,11 +443,14 @@ void g_scan_token_node_check_forward(const GScanTokenNode *node, GScanContext *c
const node_offset_range_t *range; /* Bornes d'espace à parcourir */
phys_t new_end; /* Nouveau point d'arrivée */
- init_node_search_offset(&offset);
+ init_node_search_offset(&params->offset);
skip = true;
- _g_scan_token_node_check_forward(node, context, content, matches, &offset, false, &skip);
+ _g_scan_token_node_check_forward(node, params, TNCF_UPDATE_IN_PLACE, &skip);
+
+
+#if 0 // FIXME
/**
* Si un décalage entre octets n'a pas été consommé,
@@ -425,8 +470,41 @@ void g_scan_token_node_check_forward(const GScanTokenNode *node, GScanContext *c
* phase d'extension des résultats inexistants est ainsi sautée.
*/
if (count_pending_matches(matches) == 0)
+ {
+
+
+ for (o = 0; o < ocount; o++)
+ {
+ range = (*ranges_ptr) + o;
+
+
+ printf("range: %u - %u\n",
+ (unsigned int)range->min,
+ (unsigned int)range->max);
+
+
+ /*
+ new_end = old_end + range->min;
+
+ if (new_end > matches->content_end)
+ new_end = matches->content_end;
+
+ add_pending_match(pending_matches_t *, phys_t, phys_t);
+
+ extend_pending_match_ending(matches, p, new_end);
+ */
+
+ }
+
+
+
+
+
+
goto offset_done;
+ }
+
reset_pending_matches_ttl(matches);
pending_ptr = get_all_pending_matches(matches, &pcount);
@@ -466,20 +544,19 @@ void g_scan_token_node_check_forward(const GScanTokenNode *node, GScanContext *c
assert(offset.used == 0);
- exit_node_search_offset(&offset);
+#endif
+
+ exit_node_search_offset(&params->offset);
}
/******************************************************************************
* *
-* Paramètres : node = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
-* matches = suivi des correspondances à consolider. *
-* offset = tolérance dans les positions à appliquer. *
-* not = indique si les résultats doivent être inversés. *
-* skip = détermine si l'analyse est différée. [OUT] *
+* Paramètres : node = définition de la bribe à manipuler. *
+* params = accès direct aux éléments utiles aux validations. *
+* cflags = altérations de traitement à respecter. *
+* skip = détermine si l'analyse est différée. [OUT] *
* *
* Description : Transforme les correspondances locales en trouvailles. *
* *
@@ -489,13 +566,13 @@ void g_scan_token_node_check_forward(const GScanTokenNode *node, GScanContext *c
* *
******************************************************************************/
-void _g_scan_token_node_check_backward(const GScanTokenNode *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip)
+void _g_scan_token_node_check_backward(const GScanTokenNode *node, scan_node_check_params_t *params, TokenNodeCheckFlags cflags, bool *skip)
{
GScanTokenNodeClass *class; /* Classe de l'instance */
class = G_SCAN_TOKEN_NODE_GET_CLASS(node);
- class->check_backward(node, context, content, matches, offset, not, skip);
+ class->check_backward(node, params, cflags, skip);
if (node->flags & STNF_MAIN)
{
@@ -508,10 +585,8 @@ void _g_scan_token_node_check_backward(const GScanTokenNode *node, GScanContext
/******************************************************************************
* *
-* Paramètres : node = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
-* matches = suivi des correspondances à consolider. *
+* Paramètres : node = définition de la bribe à manipuler. *
+* params = accès direct aux éléments utiles aux validations. *
* *
* Description : Transforme les correspondances locales en trouvailles. *
* *
@@ -521,7 +596,7 @@ void _g_scan_token_node_check_backward(const GScanTokenNode *node, GScanContext
* *
******************************************************************************/
-void g_scan_token_node_check_backward(const GScanTokenNode *node, GScanContext *context, GBinContent *content, pending_matches_t *matches)
+void g_scan_token_node_check_backward(const GScanTokenNode *node, scan_node_check_params_t *params)
{
node_search_offset_t offset; /* Espace des correspondances */
bool skip; /* Mise en attente des analyses*/
@@ -536,11 +611,13 @@ void g_scan_token_node_check_backward(const GScanTokenNode *node, GScanContext *
const node_offset_range_t *range; /* Bornes d'espace à parcourir */
phys_t new_start; /* Nouveau point d'arrivée */
- init_node_search_offset(&offset);
+ init_node_search_offset(&params->offset);
skip = true;
- _g_scan_token_node_check_backward(node, context, content, matches, &offset, false, &skip);
+ _g_scan_token_node_check_backward(node, params, TNCF_UPDATE_IN_PLACE, &skip);
+
+#if 0 // FIXME
/**
* Si un décalage entre octets n'a pas été consommé,
@@ -591,6 +668,8 @@ void g_scan_token_node_check_backward(const GScanTokenNode *node, GScanContext *
assert(offset.used == 0);
- exit_node_search_offset(&offset);
+#endif
+
+ exit_node_search_offset(&params->offset);
}
diff --git a/src/analysis/scan/patterns/tokens/node.h b/src/analysis/scan/patterns/tokens/node.h
index a2e3b0d..55bf0a8 100644
--- a/src/analysis/scan/patterns/tokens/node.h
+++ b/src/analysis/scan/patterns/tokens/node.h
@@ -29,9 +29,10 @@
#include <stdbool.h>
+#include "offset.h"
#include "../backend.h"
#include "../../context.h"
-#include "../../matches/pending.h"
+#include "../../matches/bytes.h"
#define G_TYPE_SCAN_TOKEN_NODE g_scan_token_node_get_type()
@@ -53,10 +54,9 @@ typedef struct _GScanTokenNodeClass GScanTokenNodeClass;
typedef enum _ScanTokenNodeFlags
{
STNF_NONE = (0 << 0), /* Absence de singularité */
- STNF_PROD = (1 << 0), /* Absence de singularité */
- STNF_FIRST = (1 << 1), /* Premier noeud de traitement */ /* REMME ? */
- STNF_LAST = (1 << 2), /* Dernier noeud de traitement */ /* REMME ? */
- STNF_MAIN = (1 << 3), /* Point de départ d'analyse */
+ STNF_FIRST = (1 << 0), /* Premier noeud de traitement */
+ STNF_LAST = (1 << 1), /* Dernier noeud de traitement */
+ STNF_MAIN = (1 << 2), /* Point de départ d'analyse */
} ScanTokenNodeFlags;
@@ -64,6 +64,11 @@ typedef enum _ScanTokenNodeFlags
/* Indique le type défini pour un élément décomposant un motif d'octets à rechercher. */
GType g_scan_token_node_get_type(void);
+/* Communique l'intérêt d'un noeud au sein d'une analyse. */
+float g_scan_token_node_compute_weight_for_scan(const GScanTokenNode *);
+
+
+
/* Indique les propriétés particulières d'un noeud d'analyse. */
ScanTokenNodeFlags g_scan_token_node_get_flags(const GScanTokenNode *);
@@ -74,13 +79,47 @@ void g_scan_token_node_set_flags(GScanTokenNode *, ScanTokenNodeFlags);
bool g_scan_token_node_setup_tree(GScanTokenNode *);
/* Inscrit la définition d'un motif dans un moteur de recherche. */
-bool g_scan_token_node_enroll(GScanTokenNode *, GScanContext *, GEngineBackend *, size_t, size_t *);
+bool g_scan_token_node_enroll(GScanTokenNode *, GEngineBackend *, size_t, size_t *);
+
+/* Récupère un identifiant final pour un atome d'octets. */
+bool g_scan_token_node_build_id(GScanTokenNode *, GEngineBackend *);
+
+/* Accès direct aux éléments utiles aux contrôles */
+typedef struct _scan_node_check_params_t
+{
+ GScanContext *context; /* Contexte de scan en cours */
+ GBinContent *content; /* Contenu binaire associé */
+ GUMemSlice *allocator; /* Allocateur pour zones */
+
+ phys_t content_start; /* Point de début du contenu */
+ phys_t content_end; /* Point de fin du contenu */
+
+ node_search_offset_t offset; /* Décalages à respecter */
+
+ bool initialized; /* Etat du suivi */
+
+ /* TNCF_UPDATE_IN_PLACE */
+
+ match_area_t *main_areas; /* Zones principales à analyser*/
+ size_t main_count; /* Taille de cette liste */
+
+ /* TNCF_CREATE_NEW */
+
+ match_area_t *created_areas; /* Zones principales à analyser*/
+ size_t created_count; /* Taille de cette liste */
+
+ /* TNCF_KEEP_DISCARDED */
+
+ match_area_t *kept_areas; /* Zones principales à analyser*/
+ size_t kept_count; /* Taille de cette liste */
+
+} scan_node_check_params_t;
/* Transforme les correspondances locales en trouvailles. */
-void g_scan_token_node_check_forward(const GScanTokenNode *, GScanContext *, GBinContent *, pending_matches_t *);
+void g_scan_token_node_check_forward(const GScanTokenNode *, scan_node_check_params_t *);
/* Transforme les correspondances locales en trouvailles. */
-void g_scan_token_node_check_backward(const GScanTokenNode *, GScanContext *, GBinContent *, pending_matches_t *);
+void g_scan_token_node_check_backward(const GScanTokenNode *, scan_node_check_params_t *);
diff --git a/src/analysis/scan/patterns/tokens/nodes/any.c b/src/analysis/scan/patterns/tokens/nodes/any.c
index 6233cb4..10a01cd 100644
--- a/src/analysis/scan/patterns/tokens/nodes/any.c
+++ b/src/analysis/scan/patterns/tokens/nodes/any.c
@@ -55,10 +55,10 @@ static void g_scan_token_node_any_finalize(GScanTokenNodeAny *);
static bool g_scan_token_node_any_enroll(GScanTokenNodeAny *, GScanContext *, GEngineBackend *, size_t, size_t *);
/* Transforme les correspondances locales en trouvailles. */
-static void g_scan_token_node_any_check_forward(const GScanTokenNodeAny *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *);
+static void g_scan_token_node_any_check_forward(const GScanTokenNodeAny *, scan_node_check_params_t *, TokenNodeCheckFlags, bool *);
/* Transforme les correspondances locales en trouvailles. */
-static void g_scan_token_node_any_check_backward(const GScanTokenNodeAny *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *);
+static void g_scan_token_node_any_check_backward(const GScanTokenNodeAny *, scan_node_check_params_t *, TokenNodeCheckFlags, bool *);
@@ -95,6 +95,7 @@ static void g_scan_token_node_any_class_init(GScanTokenNodeAnyClass *klass)
node = G_SCAN_TOKEN_NODE_CLASS(klass);
+ node->apply = (apply_scan_token_node_flags_fc)NULL;
node->visit = (visit_scan_token_node_fc)NULL;
node->enroll = (enroll_scan_token_node_fc)g_scan_token_node_any_enroll;
node->check_forward = (check_scan_token_node_fc)g_scan_token_node_any_check_forward;
@@ -117,8 +118,6 @@ static void g_scan_token_node_any_class_init(GScanTokenNodeAnyClass *klass)
static void g_scan_token_node_any_init(GScanTokenNodeAny *any)
{
- g_scan_token_node_set_flags(G_SCAN_TOKEN_NODE(any), STNF_PROD);
-
any->min = 0;
any->has_max = false;
@@ -297,13 +296,10 @@ static bool g_scan_token_node_any_enroll(GScanTokenNodeAny *node, GScanContext *
/******************************************************************************
* *
-* Paramètres : node = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
-* matches = suivi des correspondances à consolider. *
-* offset = tolérance dans les positions à appliquer. *
-* not = indique si les résultats doivent être inversés. *
-* skip = détermine si l'analyse est différée. [OUT] *
+* Paramètres : node = définition de la bribe à manipuler. *
+* params = accès direct aux éléments utiles aux validations. *
+* cflags = altérations de traitement à respecter. *
+* skip = détermine si l'analyse est différée. [OUT] *
* *
* Description : Transforme les correspondances locales en trouvailles. *
* *
@@ -313,66 +309,250 @@ static bool g_scan_token_node_any_enroll(GScanTokenNodeAny *node, GScanContext *
* *
******************************************************************************/
-static void g_scan_token_node_any_check_forward(const GScanTokenNodeAny *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip)
+static void g_scan_token_node_any_check_forward(const GScanTokenNodeAny *node, scan_node_check_params_t *params, TokenNodeCheckFlags cflags, bool *skip)
{
- bool initialized; /* Initialisation du suivi ? */
+ ScanTokenNodeFlags flags; /* Particularités du noeud */
bool forced; /* Inclusion dans un scan ? */
phys_t size; /* Quantité d'octets considérés*/
- const phys_t *datasize; /* Taille max. à communiquer */
+ phys_t match_size; /* Taille de correspondance */
+ phys_t i; /* Boucle de parcours #1 */
+ match_area_t *space; /* Nouvelle zone à intégrer */
+ match_area_t *area; /* Correspondance à valider */
+ match_area_t *next; /* Correspondance suivante */
+ phys_t after; /* Espace disposible après */
+ phys_t min_end; /* Fin la plus proche possible */
+ phys_t max_end; /* Fin la plus éloignée trouvée*/
+ bool updated; /* Existence de correspondance */
+ size_t rcount; /* Quantité de bornes présentes*/
+ const node_offset_range_t *ranges; /* Bornes d'espace à parcourir */
+ size_t r; /* Boucle de parcours #2 */
+ phys_t updated_edge; /* Nouvelle bordure de motif */
+ match_area_t *new_area; /* Copie de correspondance */
+
+ if (0x1) printf("=================== CHECK :: %s (skip? %d)\n", __FUNCTION__, *skip);
if (*skip)
return;
+ flags = g_scan_token_node_get_flags(G_SCAN_TOKEN_NODE(node));
- // $a = { [1-3] 6f }
- // pas d'initialisation, construction de résultats avec une taille nulle
+ forced = (flags & STNF_MAIN);
+ assert((!params->initialized && forced) || (params->initialized & !forced));
+
+ /**
+ * La situation forcée correspond au cas particulier d'une définition
+ * complètement abstraite : ??, ?? ??, etc.
+ */
+ if (forced)
+ {
+ size = params->content_end - params->content_start;
+ if (node->has_max && 0 /* greedy ? */)
+ {
+ match_size = node->max;
- initialized = are_pending_matches_initialized(matches);
+ if (match_size > size)
+ match_size = node->min;
- forced = (g_scan_token_node_get_flags(G_SCAN_TOKEN_NODE(node)) & STNF_MAIN);
+ }
+ else
+ match_size = node->min;
+
+ /**
+ * Si le contenu binaire est trop petit pour contenir au moins un enregistrement,
+ * aucune correspondance n'est enregistrée. Comme le noeud est le principale, ie.
+ * seul et unique, l'analyse s'arrête ensuite d'elle même.
+ *
+ * Si le contenu binaire est suffisamment large, des espaces sont créés et l'analyse
+ * se termine ensuite. La conservation des espaces n'est donc pas utile, ni réalisée.
+ */
- size = matches->content_end - matches->content_start;
+ if (match_size <= size)
+ {
+ size -= match_size;
- datasize = (not ? &size : NULL);
+ assert(cflags & TNCF_UPDATE_IN_PLACE);
- if (forced)
- {
- assert(!initialized);
+ for (i = 0; i < size; i++)
+ {
+ space = g_umem_slice_alloc(params->allocator);
- if (node->min > size)
- /* TODO set abort in matches */;
+ space->start = params->content_start + i;
+ space->end = space->start + match_size;
- else
- add_range_to_node_search_offset(offset,
- matches->content_start,
- matches->content_end - matches->content_start,
- datasize);
+ add_tail_match_area(space, &params->main_areas);
+ params->main_count++;
+
+ }
+
+ }
}
+
+ /**
+ * Situation usuelle : des espaces séparent deux noeuds.
+ */
else
{
- assert(initialized);
+ assert(params->initialized);
+
+ /**
+ * Les espaces existants sont à compléter. La présence de tels espaces
+ * restant à traiter peut provenir d'un aiguillage imposé par un motif
+ * tel que :
+ *
+ * ( aa ?? ?? | bb cc dd ) [0-5] ee ee
+ *
+ * Deux espaces sont à considérer avant de rechercher des octets ee :
+ * [2-7] et [0-5].
+ *
+ * Note : ces espaces peuvent être disjoints.
+ *
+ * Si aucun espace n'est en place, un est créé.
+ */
+ extend_node_search_offset(&params->offset, node->min, node->max, node->has_max);
- // TODO : compléter les intervales éventuels déjà en place
+ /**
+ * Si un décalage enregistré ne peut être consommé par un noeud, les
+ * résultats sont étendus ici à minima ou maxima.
+ */
+ if (flags & STNF_LAST)
+ {
+ assert(offsets_exist(&params->offset));
- /*
- printf("[i] create hole: %llx <-> %llx\n",
- (unsigned long long)node->min,
- (unsigned long long)node->max);
- */
+ if (0x1) printf(" LIST : %p (sz = %zu)\n", params->main_areas, params->main_count);
+ for_each_match_area_safe(area, &params->main_areas, next)
+ {
+ assert(area->end <= params->content_end);
- if (node->has_max)
- add_range_to_node_search_offset(offset, node->min, node->max, datasize);
- else
- add_range_to_node_search_offset(offset, node->min, matches->content_end - node->min, datasize);
+ after = params->content_end - area->end;
+
+ if (0x1) printf("---------- iter @ %u -> %u\n", (unsigned int)area->start, (unsigned int)area->end);
- // TODO : si dernier, virer les correspondances qui n'ont plus l'espace de fin requis
- // -> au niveau du noeud, en fonction du flag _LAST
+ min_end = params->content_end;
+ max_end = params->content_start;
+
+ updated = false;
+
+ ranges = get_node_search_offset_ranges_2(&params->offset, &rcount);
+
+ for (r = 0; r < rcount; r++)
+ {
+ if (ranges[r].min > after)
+ continue;
+
+ updated_edge = area->end + ranges[r].min;
+
+ if (updated_edge < min_end)
+ min_end = updated_edge;
+
+ if (ranges[r].has_max)
+ {
+ if (ranges[r].max > after)
+ updated_edge = params->content_end;
+ else
+ updated_edge = area->end + ranges[r].max;
+
+ if (updated_edge > max_end)
+ max_end = updated_edge;
+
+ }
+
+ updated = true;
+
+ }
+
+ if (updated)
+ {
+ /**
+ * Si seuls les rejets sont d'intérêt, les correspondances établies
+ * ne se voient pas mises à jours ni retirées.
+ */
+
+ if ((cflags & TNCF_KEEP_DISCARDED) == 0)
+ {
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ area->end = (1 /* greedy */ ? min_end : max_end);
+
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ new_area = g_umem_slice_alloc(params->allocator);
+
+ *new_area = *area;
+
+ new_area->end = (1 /* greedy */ ? min_end : max_end);
+
+ add_tail_match_area(new_area, &params->created_areas);
+ params->created_count++;
+
+ }
+
+#ifndef NDEBUG
+ else
+ assert(false);
+#endif
+
+ }
+
+ }
+
+ else
+ {
+ /**
+ * Si la liste principale doit être mise à jour...
+ */
+
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ {
+ del_match_area(area, &params->main_areas);
+ assert(params->main_count > 0);
+ params->main_count--;
+ }
+
+ /**
+ * Au cas où le rejet est d'intérêt, l'absence de correspondance
+ * est conservée dans une liste dédiée.
+ */
+
+ if (cflags & TNCF_KEEP_DISCARDED)
+ {
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ {
+ add_tail_match_area(area, &params->kept_areas);
+ params->kept_count++;
+ }
+
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ new_area = g_umem_slice_alloc(params->allocator);
+
+ *new_area = *area;
+
+ new_area->end = (1 /* greedy */ ? min_end : max_end);
+
+ add_tail_match_area(new_area, &params->kept_areas);
+ params->kept_count++;
+
+ }
+
+#ifndef NDEBUG
+ else
+ assert(false);
+#endif
+
+ }
+
+ }
+
+ }
+
+ disable_all_ranges_in_node_search_offset(&params->offset);
+
+ }
}
@@ -381,13 +561,10 @@ static void g_scan_token_node_any_check_forward(const GScanTokenNodeAny *node, G
/******************************************************************************
* *
-* Paramètres : node = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
-* matches = suivi des correspondances à consolider. *
-* offset = tolérance dans les positions à appliquer. *
-* not = indique si les résultats doivent être inversés. *
-* skip = détermine si l'analyse est différée. [OUT] *
+* Paramètres : node = définition de la bribe à manipuler. *
+* params = accès direct aux éléments utiles aux validations. *
+* cflags = altérations de traitement à respecter. *
+* skip = détermine si l'analyse est différée. [OUT] *
* *
* Description : Transforme les correspondances locales en trouvailles. *
* *
@@ -397,55 +574,191 @@ static void g_scan_token_node_any_check_forward(const GScanTokenNodeAny *node, G
* *
******************************************************************************/
-static void g_scan_token_node_any_check_backward(const GScanTokenNodeAny *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip)
+static void g_scan_token_node_any_check_backward(const GScanTokenNodeAny *node, scan_node_check_params_t *params, TokenNodeCheckFlags cflags, bool *skip)
{
+ ScanTokenNodeFlags flags; /* Particularités du noeud */
#ifndef NDEBUG
bool forced; /* Inclusion dans un scan ? */
#endif
- phys_t size; /* Quantité d'octets considérés*/
- const phys_t *datasize; /* Taille max. à communiquer */
+ match_area_t *area; /* Correspondance à valider */
+ match_area_t *next; /* Correspondance suivante */
+ phys_t before; /* Espace disposible avant */
+ phys_t min_start; /* Début le plus proche trouvé */
+ phys_t max_start; /* Début le plus distant trouvé*/
+ bool updated; /* Existence de correspondance */
+ size_t rcount; /* Quantité de bornes présentes*/
+ const node_offset_range_t *ranges; /* Bornes d'espace à parcourir */
+ size_t r; /* Boucle de parcours */
+ phys_t updated_edge; /* Nouvelle bordure de motif */
+ match_area_t *new_area; /* Copie de correspondance */
+
+ if (0x1) printf("=================== CHECK :: %s (skip? %d)\n", __FUNCTION__, *skip);
if (*skip)
return;
/**
* En lecture à rebourd, au moins un noeud a été solicité pour analyse (lors
- * du sens de lecteur normal). Donc l'initialisation a déjà dû avoir lieu.
+ * du sens de lecture normal). Donc l'initialisation a déjà dû avoir lieu.
*/
- assert(are_pending_matches_initialized(matches));
+
+ assert(params->initialized);
+
+ flags = g_scan_token_node_get_flags(G_SCAN_TOKEN_NODE(node));
/**
* Si les recherches associées au noeud ont été forcées, alors les traitements
* liés ont déjà été effectués, et l'appel de cette fonction aurait dû être sauté.
*/
#ifndef NDEBUG
- forced = (g_scan_token_node_get_flags(G_SCAN_TOKEN_NODE(node)) & STNF_MAIN);
+ forced = (flags & STNF_MAIN);
assert(!forced);
#endif
- size = matches->content_end - matches->content_start;
+ /**
+ * Les considérations pour l'extension des espaces en place sont identiques
+ * à celles formulées dans la fonction g_scan_token_node_any_check_forward().
+ */
- if (node->min > size)
- /* TODO set abort in matches */;
+ extend_node_search_offset(&params->offset, node->min, node->max, node->has_max);
- else
+ /**
+ * Si un décalage enregistré ne peut être consommé par un noeud, les
+ * résultats sont étendus ici à minima ou maxima.
+ */
+
+ if (flags & STNF_FIRST)
{
- datasize = (not ? &size : NULL);
+ assert(offsets_exist(&params->offset));
- /**
- * Une tolérance basée sur des espaces (et non des positions) est déterminée
- * ici.
- *
- * Charge au prochain noeud de traitement de filtrer les résultats courants
- * avec, voire à la fonction _g_scan_token_node_check_backward() de
- * réaliser une synthèse finale si le noeud courant est le dernier d'une
- * lignée.
- */
+ if (0x1) printf(" LIST : %p (sz = %zu)\n", params->main_areas, params->main_count);
- if (node->has_max)
- add_range_to_node_search_offset(offset, node->min, node->max, datasize);
- else
- add_range_to_node_search_offset(offset, node->min, matches->content_end - node->min, datasize);
+ for_each_match_area_safe(area, &params->main_areas, next)
+ {
+ assert(params->content_start <= area->start);
+
+ before = area->start - params->content_start;
+
+ if (0x1) printf("---------- iter @ %u -> %u\n", (unsigned int)area->start, (unsigned int)area->end);
+
+ min_start = params->content_start;
+ max_start = params->content_end;
+
+ updated = false;
+
+ ranges = get_node_search_offset_ranges_2(&params->offset, &rcount);
+
+ for (r = 0; r < rcount; r++)
+ {
+ if (ranges[r].min > before)
+ continue;
+
+ updated_edge = area->start - ranges[r].min;
+
+ if (updated_edge > min_start)
+ min_start = updated_edge;
+
+ if (ranges[r].has_max)
+ {
+ if (ranges[r].max > before)
+ updated_edge = params->content_start;
+ else
+ updated_edge = area->start - ranges[r].max;
+
+ if (updated_edge < max_start)
+ max_start = updated_edge;
+
+ }
+
+ updated = true;
+
+ }
+
+ if (updated)
+ {
+ /**
+ * Si seuls les rejets sont d'intérêt, les correspondances établies
+ * ne se voient pas mises à jours ni retirées.
+ */
+
+ if ((cflags & TNCF_KEEP_DISCARDED) == 0)
+ {
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ area->start = (1 /* greedy */ ? min_start : max_start);
+
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ new_area = g_umem_slice_alloc(params->allocator);
+
+ *new_area = *area;
+
+ new_area->start = (1 /* greedy */ ? min_start : max_start);
+
+ add_tail_match_area(new_area, &params->created_areas);
+ params->created_count++;
+
+ }
+
+#ifndef NDEBUG
+ else
+ assert(false);
+#endif
+
+ }
+
+ }
+
+ else
+ {
+ /**
+ * Si la liste principale doit être mise à jour...
+ */
+
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ {
+ del_match_area(area, &params->main_areas);
+ assert(params->main_count > 0);
+ params->main_count--;
+ }
+
+ /**
+ * Au cas où le rejet est d'intérêt, l'absence de correspondance
+ * est conservée dans une liste dédiée.
+ */
+
+ if (cflags & TNCF_KEEP_DISCARDED)
+ {
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ {
+ add_tail_match_area(area, &params->kept_areas);
+ params->kept_count++;
+ }
+
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ new_area = g_umem_slice_alloc(params->allocator);
+
+ *new_area = *area;
+
+ new_area->start = (1 /* greedy */ ? min_start : max_start);
+
+ add_tail_match_area(new_area, &params->kept_areas);
+ params->kept_count++;
+
+ }
+
+#ifndef NDEBUG
+ else
+ assert(false);
+#endif
+
+ }
+
+ }
+
+ }
+
+ disable_all_ranges_in_node_search_offset(&params->offset);
}
diff --git a/src/analysis/scan/patterns/tokens/nodes/choice.c b/src/analysis/scan/patterns/tokens/nodes/choice.c
index df6ae45..102c7de 100644
--- a/src/analysis/scan/patterns/tokens/nodes/choice.c
+++ b/src/analysis/scan/patterns/tokens/nodes/choice.c
@@ -24,6 +24,9 @@
#include "choice.h"
+#include <assert.h>
+
+
#include "choice-int.h"
@@ -48,6 +51,9 @@ static void g_scan_token_node_choice_finalize(GScanTokenNodeChoice *);
/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+/* Communique l'intérêt d'un noeud au sein d'une analyse. */
+static float g_scan_token_node_choice_compute_weight_for_scan(const GScanTokenNodeChoice *);
+
/* Prend acte d'une nouvelle propriété pour le noeud. */
static void g_scan_token_node_choice_apply_flags(GScanTokenNodeChoice *, ScanTokenNodeFlags);
@@ -55,13 +61,16 @@ static void g_scan_token_node_choice_apply_flags(GScanTokenNodeChoice *, ScanTok
static void g_scan_token_node_choice_visit(GScanTokenNodeChoice *, scan_tree_points_t *);
/* Inscrit la définition d'un motif dans un moteur de recherche. */
-static bool g_scan_token_node_choice_enroll(GScanTokenNodeChoice *, GScanContext *, GEngineBackend *, size_t, size_t *);
+static bool g_scan_token_node_choice_enroll(GScanTokenNodeChoice *, GEngineBackend *, size_t, size_t *);
+
+/* Récupère un identifiant final pour un atome d'octets. */
+static bool g_scan_token_node_choice_build_id(GScanTokenNodeChoice *, GEngineBackend *);
/* Transforme les correspondances locales en trouvailles. */
-static void g_scan_token_node_choice_check_forward(const GScanTokenNodeChoice *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *);
+static void g_scan_token_node_choice_check_forward(const GScanTokenNodeChoice *, scan_node_check_params_t *, TokenNodeCheckFlags, bool *);
/* Transforme les correspondances locales en trouvailles. */
-static void g_scan_token_node_choice_check_backward(const GScanTokenNodeChoice *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *);
+static void g_scan_token_node_choice_check_backward(const GScanTokenNodeChoice *, scan_node_check_params_t *, TokenNodeCheckFlags, bool *);
@@ -98,9 +107,11 @@ static void g_scan_token_node_choice_class_init(GScanTokenNodeChoiceClass *klass
node = G_SCAN_TOKEN_NODE_CLASS(klass);
+ node->compute_weight = (compute_scan_token_node_weight_fc)g_scan_token_node_choice_compute_weight_for_scan;
node->apply = (apply_scan_token_node_flags_fc)g_scan_token_node_choice_apply_flags;
node->visit = (visit_scan_token_node_fc)g_scan_token_node_choice_visit;
node->enroll = (enroll_scan_token_node_fc)g_scan_token_node_choice_enroll;
+ node->build_id = (build_scan_token_node_id_fc)g_scan_token_node_choice_build_id;
node->check_forward = (check_scan_token_node_fc)g_scan_token_node_choice_check_forward;
node->check_backward = (check_scan_token_node_fc)g_scan_token_node_choice_check_backward;
@@ -227,6 +238,51 @@ void g_scan_token_node_choice_add(GScanTokenNodeChoice *choice, GScanTokenNode *
/******************************************************************************
* *
+* Paramètres : node = noeud de motif à consulter. *
+* *
+* Description : Communique l'intérêt d'un noeud au sein d'une analyse. *
+* *
+* Retour : Poids de l'importance pour un départ de scan. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static float g_scan_token_node_choice_compute_weight_for_scan(const GScanTokenNodeChoice *node)
+{
+ float result; /* Valeur à retourner */
+ size_t weight_count; /* Nombre de comptabilisations */
+ size_t i; /* Boucle de parcours */
+ float weight; /* Nouveau poids à intégrer */
+
+ result = 0;
+
+ weight_count = 0;
+
+ for (i = 0; i < node->count; i++)
+ {
+ weight = g_scan_token_node_compute_weight_for_scan(node->children[i]);
+
+ if (weight > 0)
+ {
+ result += weight;
+ weight_count++;
+ }
+
+ }
+
+ if (weight_count != node->count)
+ result = 0;
+ else
+ result /= weight_count;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : node = noeud de motif à mettre à jour. *
* flags = propriétés particulières à associer au noeud. *
* *
@@ -274,9 +330,6 @@ static void g_scan_token_node_choice_visit(GScanTokenNodeChoice *node, scan_tree
for (i = 0; i < node->count; i++)
{
- tmp_points.first_node = NULL;
- tmp_points.last_node = NULL;
-
tmp_points.first_plain = NULL;
tmp_points.best_masked = NULL;
@@ -296,7 +349,6 @@ static void g_scan_token_node_choice_visit(GScanTokenNodeChoice *node, scan_tree
/******************************************************************************
* *
* Paramètres : node = définition de la bribe à enregistrer. *
-* context = contexte de l'analyse à mener. *
* backend = moteur de recherche à préchauffer. *
* maxsize = taille max. des atomes (mise en commun optimisée). *
* slow = niveau de ralentissement induit (0 = idéal). [OUT] *
@@ -309,7 +361,7 @@ static void g_scan_token_node_choice_visit(GScanTokenNodeChoice *node, scan_tree
* *
******************************************************************************/
-static bool g_scan_token_node_choice_enroll(GScanTokenNodeChoice *node, GScanContext *context, GEngineBackend *backend, size_t maxsize, size_t *slow)
+static bool g_scan_token_node_choice_enroll(GScanTokenNodeChoice *node, GEngineBackend *backend, size_t maxsize, size_t *slow)
{
bool result; /* Statut à retourner */
size_t i; /* Boucle de parcours */
@@ -317,7 +369,7 @@ static bool g_scan_token_node_choice_enroll(GScanTokenNodeChoice *node, GScanCon
result = true;
for (i = 0; i < node->count && result; i++)
- result = _g_scan_token_node_enroll(node->children[i], context, backend, maxsize, slow);
+ result = _g_scan_token_node_enroll(node->children[i], backend, maxsize, slow);
return result;
@@ -326,13 +378,38 @@ static bool g_scan_token_node_choice_enroll(GScanTokenNodeChoice *node, GScanCon
/******************************************************************************
* *
-* Paramètres : node = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
-* matches = suivi des correspondances à consolider. *
-* offset = tolérance dans les positions à appliquer. *
-* not = indique si les résultats doivent être inversés. *
-* skip = détermine si l'analyse est différée. [OUT] *
+* Paramètres : node = définition de la bribe à peaufiner. *
+* backend = moteur de recherche à préchauffer. *
+* *
+* Description : Récupère un identifiant final pour un atome d'octets. *
+* *
+* Retour : Bilan de l'opération à renvoyer. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_token_node_choice_build_id(GScanTokenNodeChoice *node, GEngineBackend *backend)
+{
+ bool result; /* Statut à retourner */
+ size_t i; /* Boucle de parcours #1 */
+
+ result = true;
+
+ for (i = 0; i < node->count && result; i++)
+ result = g_scan_token_node_build_id(node->children[i], backend);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : node = définition de la bribe à manipuler. *
+* params = accès direct aux éléments utiles aux validations. *
+* cflags = altérations de traitement à respecter. *
+* skip = détermine si l'analyse est différée. [OUT] *
* *
* Description : Transforme les correspondances locales en trouvailles. *
* *
@@ -342,78 +419,117 @@ static bool g_scan_token_node_choice_enroll(GScanTokenNodeChoice *node, GScanCon
* *
******************************************************************************/
-static void g_scan_token_node_choice_check_forward(const GScanTokenNodeChoice *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip)
+static void g_scan_token_node_choice_check_forward(const GScanTokenNodeChoice *node, scan_node_check_params_t *params, TokenNodeCheckFlags cflags, bool *skip)
{
- pending_matches_t init_matches; /* Correspondances initiales */
- node_search_offset_t init_offset; /* Intervales initiaux */
- size_t new_offset; /* Décompte d'intervales */
+ bool initialized; /* Initialisation du suivi ? */
+ match_area_t *collected_areas; /* Zones mises en place ici */
+ size_t collected_count; /* Quantité de ces zones */
+ TokenNodeCheckFlags local_cflags; /* Particularités nouvelles */
size_t i; /* Boucle de parcours */
- pending_matches_t tmp_matches; /* Copie locale de travail #1 */
- node_search_offset_t tmp_offset; /* Copie locale de travail #2 */
+ scan_node_check_params_t local_params; /* Rassemblement de paramètres */
+
+ if (0x1) printf("=================== CHECK :: %s (skip? %d)\n", __FUNCTION__, *skip);
if (*skip)
return;
- /* Copie des contextes de départ */
+ /* Lancement des sous-traitements */
- copy_pending_matches(&init_matches, matches);
+ initialized = false;
- exit_pending_matches(matches);
- init_pending_matches(matches, &init_matches.content_start, &init_matches.content_end);
+ collected_areas = NULL;
+ collected_count = 0;
- copy_node_search_offset(&init_offset, offset);
+ local_cflags = (cflags & ~TNCF_UPDATE_IN_PLACE) | TNCF_CREATE_NEW;
- exit_node_search_offset(offset);
- init_node_search_offset(offset);
+ for (i = 0; i < node->count; i++)
+ {
+ local_params = *params;
- /* Lancement des sous-traitements */
+ local_params.created_areas = NULL;
+ local_params.created_count = 0;
- new_offset = 0;
+ local_params.kept_areas = NULL;
+ local_params.kept_count = 0;
- for (i = 0; i < node->count; i++)
- {
- copy_pending_matches(&tmp_matches, &init_matches);
- copy_node_search_offset(&tmp_offset, &init_offset);
+ if ((cflags & TNCF_CREATE_NEW) == 0 && (i + 1) == node->count)
+ local_cflags = cflags;
+
+ _g_scan_token_node_check_forward(node->children[i], &local_params, local_cflags, skip);
- _g_scan_token_node_check_forward(node->children[i], context, content,
- &tmp_matches, &tmp_offset, not, skip);
+ initialized |= local_params.initialized;
- merge_pending_matches(matches, &tmp_matches);
- merge_node_search_offset(offset, &tmp_offset);
+ if (local_cflags & TNCF_KEEP_DISCARDED)
+ {
+ merge_match_areas(&collected_areas, &local_params.kept_areas);
+ collected_count += local_params.kept_count;
+ }
- if (tmp_offset.used > 0)
- new_offset++;
+ else if (local_cflags & TNCF_CREATE_NEW)
+ {
+ merge_match_areas(&collected_areas, &local_params.created_areas);
+ collected_count += local_params.created_count;
+ }
- exit_pending_matches(&tmp_matches);
- exit_node_search_offset(&tmp_offset);
+ else
+ {
+ assert(local_cflags & TNCF_UPDATE_IN_PLACE);
+
+ merge_match_areas(&collected_areas, &local_params.main_areas);
+ collected_count += local_params.main_count;
+
+ }
}
- /* Sortie propre */
+ /* Enregistrement des résultats finaux */
- exit_pending_matches(&init_matches);
- exit_node_search_offset(&init_offset);
+ if (collected_count > 1)
+ sort_match_areas_no_dup(&collected_areas, &collected_count, compare_match_area_as_dl_item, NULL);
- /* "Alternative" directe en cas de motif(s) non terminé(s) par un intervale */
+ if (0x1) printf("[%s] collected: #%zu (bis)\n", __FUNCTION__, collected_count);
- if (new_offset != node->count)
+ params->initialized = initialized;
+
+ if (cflags & TNCF_KEEP_DISCARDED)
{
- assert(node->count > 1);
- add_range_to_node_search_offset(offset, 0, 0, NULL);
+ params->kept_areas = collected_areas;
+ params->kept_count = collected_count;
}
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ params->created_areas = collected_areas;
+ params->created_count = collected_count;
+ }
+
+ else
+ {
+ assert(cflags & TNCF_UPDATE_IN_PLACE);
+
+ params->main_areas = collected_areas;
+ params->main_count = collected_count;
+
+ }
+
+
+
+
+
+ /// TODO : gestion des offets en sortie : ajout (+ ajout d'un test en Python)
+
+
+
+
}
/******************************************************************************
* *
-* Paramètres : node = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
-* matches = suivi des correspondances à consolider. *
-* offsets = tolérance dans les positions à appliquer. *
-* not = indique si les résultats doivent être inversés. *
-* skip = détermine si l'analyse est différée. [OUT] *
+* Paramètres : node = définition de la bribe à manipuler. *
+* params = accès direct aux éléments utiles aux validations. *
+* cflags = altérations de traitement à respecter. *
+* skip = détermine si l'analyse est différée. [OUT] *
* *
* Description : Transforme les correspondances locales en trouvailles. *
* *
@@ -423,64 +539,108 @@ static void g_scan_token_node_choice_check_forward(const GScanTokenNodeChoice *n
* *
******************************************************************************/
-static void g_scan_token_node_choice_check_backward(const GScanTokenNodeChoice *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip)
+static void g_scan_token_node_choice_check_backward(const GScanTokenNodeChoice *node, scan_node_check_params_t *params, TokenNodeCheckFlags cflags, bool *skip)
{
- pending_matches_t init_matches; /* Correspondances initiales */
- node_search_offset_t init_offset; /* Intervales initiaux */
- size_t new_offset; /* Décompte d'intervales */
+ match_area_t *collected_areas; /* Zones mises en place ici */
+ size_t collected_count; /* Quantité de ces zones */
+ TokenNodeCheckFlags local_cflags; /* Particularités nouvelles */
size_t i; /* Boucle de parcours */
- pending_matches_t tmp_matches; /* Copie locale de travail #1 */
- node_search_offset_t tmp_offset; /* Copie locale de travail #2 */
+ scan_node_check_params_t local_params; /* Rassemblement de paramètres */
+
+ if (0x1) printf("=================== CHECK :: %s (skip? %d)\n", __FUNCTION__, *skip);
if (*skip)
return;
- /* Copie des contextes de départ */
+ /**
+ * En lecture à rebourd, au moins un noeud a été solicité pour analyse (lors
+ * du sens de lecture normal). Donc l'initialisation a déjà dû avoir lieu.
+ */
- copy_pending_matches(&init_matches, matches);
-
- exit_pending_matches(matches);
- init_pending_matches(matches, &init_matches.content_start, &init_matches.content_end);
-
- copy_node_search_offset(&init_offset, offset);
-
- exit_node_search_offset(offset);
- init_node_search_offset(offset);
+ assert(params->initialized);
/* Lancement des sous-traitements */
- new_offset = 0;
+ collected_areas = NULL;
+ collected_count = 0;
+
+ local_cflags = (cflags & ~TNCF_UPDATE_IN_PLACE) | TNCF_CREATE_NEW;
for (i = 0; i < node->count; i++)
{
- copy_pending_matches(&tmp_matches, &init_matches);
- copy_node_search_offset(&tmp_offset, &init_offset);
+ local_params = *params;
+
+ local_params.created_areas = NULL;
+ local_params.created_count = 0;
+
+ local_params.kept_areas = NULL;
+ local_params.kept_count = 0;
+
+ if ((cflags & TNCF_CREATE_NEW) == 0 && (i + 1) == node->count)
+ local_cflags = cflags;
- _g_scan_token_node_check_backward(node->children[i], context, content,
- &tmp_matches, &tmp_offset, not, skip);
+ _g_scan_token_node_check_backward(node->children[i], &local_params, local_cflags, skip);
- merge_pending_matches(matches, &tmp_matches);
- merge_node_search_offset(offset, &tmp_offset);
+ if (local_cflags & TNCF_KEEP_DISCARDED)
+ {
+ merge_match_areas(&collected_areas, &local_params.kept_areas);
+ collected_count += local_params.kept_count;
+ }
- if (tmp_offset.used > 0)
- new_offset++;
+ else if (local_cflags & TNCF_CREATE_NEW)
+ {
+ merge_match_areas(&collected_areas, &local_params.created_areas);
+ collected_count += local_params.created_count;
+ }
- exit_pending_matches(&tmp_matches);
- exit_node_search_offset(&tmp_offset);
+ else
+ {
+ assert(local_cflags & TNCF_UPDATE_IN_PLACE);
+
+ merge_match_areas(&collected_areas, &local_params.main_areas);
+ collected_count += local_params.main_count;
+
+ }
}
- /* Sortie propre */
+ /* Enregistrement des résultats finaux */
- exit_pending_matches(&init_matches);
- exit_node_search_offset(&init_offset);
+ if (collected_count > 1)
+ sort_match_areas_no_dup(&collected_areas, &collected_count, compare_match_area_as_dl_item, NULL);
- /* "Alternative" directe en cas de motif(s) non terminé(s) par un intervale */
+ if (0x1) printf("[%s] collected: #%zu (bis)\n", __FUNCTION__, collected_count);
- if (new_offset != node->count)
+ if (cflags & TNCF_KEEP_DISCARDED)
{
- assert(node->count > 1);
- add_range_to_node_search_offset(offset, 0, 0, NULL);
+ params->kept_areas = collected_areas;
+ params->kept_count = collected_count;
}
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ params->created_areas = collected_areas;
+ params->created_count = collected_count;
+ }
+
+ else
+ {
+ assert(cflags & TNCF_UPDATE_IN_PLACE);
+
+ params->main_areas = collected_areas;
+ params->main_count = collected_count;
+
+ }
+
+
+
+
+
+ /// TODO : gestion des offets en sortie : ajout (+ ajout d'un test en Python)
+
+
+
+
+
+
}
diff --git a/src/analysis/scan/patterns/tokens/nodes/masked-int.h b/src/analysis/scan/patterns/tokens/nodes/masked-int.h
index 9eb8712..5fcc330 100644
--- a/src/analysis/scan/patterns/tokens/nodes/masked-int.h
+++ b/src/analysis/scan/patterns/tokens/nodes/masked-int.h
@@ -41,8 +41,9 @@ struct _GScanTokenNodeMasked
size_t len; /* Taille de cette série */
sized_binary_t *raw; /* Liste de motifs à couvrir */
- tracked_scan_atom_t *atoms; /* Atomes correspondants */
- size_t count; /* Taille de cette liste */
+ size_t raw_count; /* Taille de cette liste */
+
+ tracked_scan_atom_t *enrolled_atoms; /* Atomes correspondants */
size_t enrolled_count; /* Quantité avec identifiant */
};
diff --git a/src/analysis/scan/patterns/tokens/nodes/masked.c b/src/analysis/scan/patterns/tokens/nodes/masked.c
index 8765b1d..2dbdb08 100644
--- a/src/analysis/scan/patterns/tokens/nodes/masked.c
+++ b/src/analysis/scan/patterns/tokens/nodes/masked.c
@@ -56,16 +56,19 @@ static void g_scan_token_node_masked_finalize(GScanTokenNodeMasked *);
static void g_scan_token_node_masked_visit(GScanTokenNodeMasked *, scan_tree_points_t *);
/* Inscrit la définition d'un motif dans un moteur de recherche. */
-static bool g_scan_token_node_masked_enroll(GScanTokenNodeMasked *, GScanContext *, GEngineBackend *, size_t, size_t *);
+static bool g_scan_token_node_masked_enroll(GScanTokenNodeMasked *, GEngineBackend *, size_t, size_t *);
+
+/* Récupère un identifiant final pour un atome d'octets. */
+static bool g_scan_token_node_masked_build_id(GScanTokenNodeMasked *, GEngineBackend *);
/* Détermine si un contenu d'intérêt est présent à une position. */
static bool check_scan_token_node_masked_content(const masked_byte_t *, size_t, phys_t, GBinContent *);
/* Transforme les correspondances locales en trouvailles. */
-static void g_scan_token_node_masked_check_forward(const GScanTokenNodeMasked *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *);
+static void g_scan_token_node_masked_check_forward(const GScanTokenNodeMasked *, scan_node_check_params_t *, TokenNodeCheckFlags, bool *);
/* Transforme les correspondances locales en trouvailles. */
-static void g_scan_token_node_masked_check_backward(const GScanTokenNodeMasked *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *);
+static void g_scan_token_node_masked_check_backward(const GScanTokenNodeMasked *, scan_node_check_params_t *, TokenNodeCheckFlags, bool *);
@@ -102,8 +105,10 @@ static void g_scan_token_node_masked_class_init(GScanTokenNodeMaskedClass *klass
node = G_SCAN_TOKEN_NODE_CLASS(klass);
+ node->apply = (apply_scan_token_node_flags_fc)NULL;
node->visit = (visit_scan_token_node_fc)g_scan_token_node_masked_visit;
node->enroll = (enroll_scan_token_node_fc)g_scan_token_node_masked_enroll;
+ node->build_id = (build_scan_token_node_id_fc)g_scan_token_node_masked_build_id;
node->check_forward = (check_scan_token_node_fc)g_scan_token_node_masked_check_forward;
node->check_backward = (check_scan_token_node_fc)g_scan_token_node_masked_check_backward;
@@ -124,14 +129,14 @@ static void g_scan_token_node_masked_class_init(GScanTokenNodeMaskedClass *klass
static void g_scan_token_node_masked_init(GScanTokenNodeMasked *masked)
{
- g_scan_token_node_set_flags(G_SCAN_TOKEN_NODE(masked), STNF_PROD);
-
masked->bytes = NULL;
masked->len = 0;
masked->raw = NULL;
- masked->atoms = NULL;
- masked->count = 0;
+ masked->raw_count = 0;
+
+ masked->enrolled_atoms = NULL;
+ masked->enrolled_count = 0;
}
@@ -174,14 +179,14 @@ static void g_scan_token_node_masked_finalize(GScanTokenNodeMasked *masked)
if (masked->bytes != NULL)
free(masked->bytes);
- for (i = 0; i < masked->count; i++)
+ for (i = 0; i < masked->raw_count; i++)
exit_szstr(&masked->raw[i]);
if (masked->raw != NULL)
free(masked->raw);
- if (masked->atoms != NULL)
- free(masked->atoms);
+ if (masked->enrolled_atoms != NULL)
+ free(masked->enrolled_atoms);
G_OBJECT_CLASS(g_scan_token_node_masked_parent_class)->finalize(G_OBJECT(masked));
@@ -305,7 +310,6 @@ static void g_scan_token_node_masked_visit(GScanTokenNodeMasked *node, scan_tree
/******************************************************************************
* *
* Paramètres : node = définition de la bribe à enregistrer. *
-* context = contexte de l'analyse à mener. *
* backend = moteur de recherche à préchauffer. *
* maxsize = taille max. des atomes (mise en commun optimisée). *
* slow = niveau de ralentissement induit (0 = idéal). [OUT] *
@@ -318,7 +322,7 @@ static void g_scan_token_node_masked_visit(GScanTokenNodeMasked *node, scan_tree
* *
******************************************************************************/
-static bool g_scan_token_node_masked_enroll(GScanTokenNodeMasked *node, GScanContext *context, GEngineBackend *backend, size_t maxsize, size_t *slow)
+static bool g_scan_token_node_masked_enroll(GScanTokenNodeMasked *node, GEngineBackend *backend, size_t maxsize, size_t *slow)
{
bool result; /* Statut à retourner */
bool forced; /* Inclusion dans un scan ? */
@@ -333,6 +337,8 @@ static bool g_scan_token_node_masked_enroll(GScanTokenNodeMasked *node, GScanCon
{
*slow += (maxsize * 2);
+ node->raw = make_atoms_from_masked_bytes(node->bytes, node->len, &node->raw_count);
+
/**
* Dans le cas bien précis de l'usage de l'algorithme Bitap pour les recherches
* dans le contenu binaire à analyser, on tire parti du coût nul des recherches
@@ -353,19 +359,23 @@ static bool g_scan_token_node_masked_enroll(GScanTokenNodeMasked *node, GScanCon
else
{
- node->raw = make_atoms_from_masked_byte(node->bytes[0].value, node->bytes[0].mask, &node->count);
+ node->enrolled_atoms = malloc(node->raw_count * sizeof(tracked_scan_atom_t));
+ node->enrolled_count = node->raw_count;
- node->atoms = malloc(node->count * sizeof(tracked_scan_atom_t));
-
- for (i = 0; i < node->count && result; i++)
+ for (i = 0; i < node->enrolled_count && result; i++)
{
- find_best_atom(&node->raw[i], maxsize, &node->atoms[i], NULL);
+ find_best_atom(&node->raw[i], maxsize, &node->enrolled_atoms[i], NULL);
- result = enroll_prepared_atom(&node->raw[i], context, backend, &node->atoms[i]);
+ /**
+ * Correction : si l'atome ne représente qu'une vue partielle,
+ * la validation rapide ne peut s'appliquer.
+ */
+ if (node->enrolled_atoms[i].fast_check)
+ node->enrolled_atoms[i].fast_check = (node->enrolled_atoms[i].len == node->len);
- }
+ result = enroll_prepared_atom(&node->raw[i], backend, &node->enrolled_atoms[i]);
- node->enrolled_count = node->count;
+ }
}
@@ -378,6 +388,34 @@ static bool g_scan_token_node_masked_enroll(GScanTokenNodeMasked *node, GScanCon
/******************************************************************************
* *
+* Paramètres : node = définition de la bribe à peaufiner. *
+* backend = moteur de recherche à préchauffer. *
+* *
+* Description : Récupère un identifiant final pour un atome d'octets. *
+* *
+* Retour : Bilan de l'opération à renvoyer. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_token_node_masked_build_id(GScanTokenNodeMasked *node, GEngineBackend *backend)
+{
+ bool result; /* Statut à retourner */
+ size_t i; /* Boucle de parcours #1 */
+
+ result = true;
+
+ for (i = 0; i < node->enrolled_count && result; i++)
+ result = build_atom_pattern_id(&node->enrolled_atoms[i], backend);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : bytes = octets partiels avec leur masque à interpréter. *
* len = quantité d'octets à interpréter. *
* start = point d'analyse à respecter. *
@@ -419,13 +457,10 @@ static bool check_scan_token_node_masked_content(const masked_byte_t *bytes, siz
/******************************************************************************
* *
-* Paramètres : node = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
-* matches = suivi des correspondances à consolider. *
-* offset = tolérance dans les positions à appliquer. *
-* not = indique si les résultats doivent être inversés. *
-* skip = détermine si l'analyse est différée. [OUT] *
+* Paramètres : node = définition de la bribe à manipuler. *
+* params = accès direct aux éléments utiles aux validations. *
+* cflags = altérations de traitement à respecter. *
+* skip = détermine si l'analyse est différée. [OUT] *
* *
* Description : Transforme les correspondances locales en trouvailles. *
* *
@@ -435,37 +470,36 @@ static bool check_scan_token_node_masked_content(const masked_byte_t *bytes, siz
* *
******************************************************************************/
-static void g_scan_token_node_masked_check_forward(const GScanTokenNodeMasked *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip)
+static void g_scan_token_node_masked_check_forward(const GScanTokenNodeMasked *node, scan_node_check_params_t *params, TokenNodeCheckFlags cflags, bool *skip)
{
- bool initialized; /* Initialisation du suivi ? */
#ifndef NDEBUG
bool forced; /* Inclusion dans un scan ? */
#endif
- size_t ocount; /* Quantité de bornes présentes*/
- node_offset_range_t * const *ranges_ptr;/* Bornes d'espace à parcourir */
size_t i; /* Boucle de parcours #1 */
const tracked_scan_atom_t *atom; /* Atome correspondant */
- size_t count; /* Quantité de bribes trouvées */
- const phys_t *found; /* Localisations des bribes */
- size_t k; /* Boucle de parcours #2 */
- phys_t new_begin; /* Nouveau départ à tester */
- size_t o; /* Boucle de parcours #3 */
- const node_offset_range_t *range; /* Bornes d'espace à parcourir */
+ GUMemSlice *atoms; /* Localisations des bribes */
+ const umem_slice_iter_t *aiter; /* Boucle de parcours #2 */
+ match_area_t *end; /* Borne de fin de parcours */
+ match_area_t *pos; /* Position courante */
bool status; /* Bilan d'une correspondance */
- size_t pcount; /* Nombre de correspondances */
- match_area_t * const *pending_ptr; /* Correspondances actuelles */
- size_t p; /* Boucle de parcours #4 */
- match_area_t *pending; /* Correspondance à traiter */
+ match_area_t *area; /* Correspondance à valider */
+ match_area_t *next; /* Correspondance suivante */
phys_t after; /* Espace disposible après */
- phys_t min; /* Borne minimale déterminée */
- phys_t max; /* Borne maximale déterminée */
- phys_t j; /* Boucle de parcours #5 */
+ phys_t min_end; /* Fin la plus proche possible */
+ phys_t max_end; /* Fin la plus éloignée trouvée*/
+ bool updated; /* Existence de correspondance */
+ size_t rcount; /* Quantité de bornes présentes*/
+ const node_offset_range_t *ranges; /* Bornes d'espace à parcourir */
+ size_t r; /* Boucle de parcours #xxxxxxxxxxxx*/
+ phys_t p; /* Boucle de parcours #xxxxxxxxxxxx*/
+ phys_t updated_edge; /* Nouvelle bordure de motif */
+ match_area_t *new_area; /* Copie de correspondance */
+
+ if (0x1) printf("=================== CHECK :: %s (skip? %d)\n", __FUNCTION__, *skip);
if (*skip)
return;
- initialized = are_pending_matches_initialized(matches);
-
/**
* Si l'analyse arrive à un ou plusieurs octets masqués, soit il s'agit du
* premier noeud, et la génération d'atomes a été forcée pour obtenir des
@@ -475,61 +509,103 @@ static void g_scan_token_node_masked_check_forward(const GScanTokenNodeMasked *n
*/
#ifndef NDEBUG
forced = (g_scan_token_node_get_flags(G_SCAN_TOKEN_NODE(node)) & STNF_MAIN);
- assert((!initialized && forced) || (initialized && (!forced || not)));
+ assert((!params->initialized && forced) || (params->initialized && (!forced || cflags & TNCF_KEEP_DISCARDED)));
#endif
- ranges_ptr = get_node_search_offset_ranges(offset, &ocount);
-
- /* Si aucune correspondance n'a été établie */
- if (!initialized)
+ if (!params->initialized)
{
for (i = 0; i < node->enrolled_count; i++)
{
- atom = &node->atoms[i];
+ atom = &node->enrolled_atoms[i];
- found = g_scan_context_get_atom_matches(context, atom->pid, &count);
+ atoms = g_scan_context_get_atom_matches(params->context, atom->pid);
- for (k = 0; k < count; k++)
+ if (atom->fast_check)
{
- assert(atom->pos == 0);
+ for (aiter = g_umem_slice_get_iter(atoms); aiter != NULL; aiter = aiter->next)
+ {
+ end = aiter->data_end;
- new_begin = found[k];
+ for (pos = aiter->data; pos < end; pos++)
+ {
+ /**
+ * La modification de la zone d'origine est possible dans tous les cas
+ * car cette zone a été allouée de façon dédiée à un type de correspondances
+ * et ne sera pas réutilisée comme autre source de correspondance ailleurs.
+ */
+ pos->end = pos->start + atom->len;
- /**
- * Si des bornes sont spécifiées, la position de l'atome est testée.
- *
- * Dans la pratique, cette situation (non initialisée) ne peut provenir
- * que d'un espace situé dans le vide, donc couvrant un large périmètre.
- * La validation a ainsi de grandes chances de passer...
- *
- * Le motif pouvant amener à cette situation (pas d'initialisation,
- * mais à décalage à considérer) est par exemple :
- *
- * ~( ?? ?1 )
- *
- */
- if (ocount > 0)
- {
- if (!does_node_search_offset_include_pos_forward(offset, 0, new_begin))
- continue;
- }
+ if (cflags & TNCF_KEEP_DISCARDED)
+ {
+ add_tail_match_area(pos, &params->kept_areas);
+ params->kept_count++;
+ }
- /**
- * Existe-t-il assez de place pour faire tenir le motif masqué ?
- */
- if ((new_begin + node->len) > matches->content_end)
- continue;
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ add_tail_match_area(pos, &params->created_areas);
+ params->created_count++;
+ }
+
+ else
+ {
+ assert(cflags & TNCF_UPDATE_IN_PLACE);
+
+ add_tail_match_area(pos, &params->main_areas);
+ params->main_count++;
- status = check_scan_token_node_masked_content(node->bytes, node->len, new_begin, content);
+ }
+
+ }
- if ((status && !not) || (!status && not))
+ }
+
+ }
+
+ else
+ {
+ for (aiter = g_umem_slice_get_iter(atoms); aiter != NULL; aiter = aiter->next)
{
- /**
- * Il ne peut y avoir qu'une seule séquence d'octets à un même
- * emplacement, donc le couple (start, len) enregistré est
- * unique.
- */
- add_pending_match(matches, new_begin, node->len);
+ end = aiter->data_end;
+
+ for (pos = aiter->data; pos < end; pos++)
+ {
+ status = check_scan_token_node_masked_content(node->bytes, node->len,
+ pos->start, params->content);
+
+ if (status)
+ {
+ /**
+ * La modification de la zone d'origine est possible dans tous les cas
+ * car cette zone a été allouée de façon dédiée à un type de correspondances
+ * et ne sera pas réutilisée comme autre source de correspondance ailleurs.
+ */
+ pos->end = pos->start + node->len;
+
+ if (cflags & TNCF_KEEP_DISCARDED)
+ {
+ add_tail_match_area(pos, &params->kept_areas);
+ params->kept_count++;
+ }
+
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ add_tail_match_area(pos, &params->created_areas);
+ params->created_count++;
+ }
+
+ else
+ {
+ assert(cflags & TNCF_UPDATE_IN_PLACE);
+
+ add_tail_match_area(pos, &params->main_areas);
+ params->main_count++;
+
+ }
+
+ }
+
+ }
}
@@ -539,69 +615,77 @@ static void g_scan_token_node_masked_check_forward(const GScanTokenNodeMasked *n
}
- /* Si les correspondances en place sont à confirmer et compléter */
+ /**
+ * Poursuite des traitements sur des correspondances déjà amorcées, impliquant
+ * des comparaisons entières de motifs.
+ */
else
{
- reset_pending_matches_ttl(matches);
+ if (0x1) printf(" LIST : %p (sz = %zu)\n", params->main_areas, params->main_count);
- pending_ptr = get_all_pending_matches(matches, &pcount);
-
- for (p = 0; p < pcount; p++)
+ for_each_match_area_safe(area, &params->main_areas, next)
{
- pending = (*pending_ptr) + p;
+ assert(area->end <= params->content_end);
+
+ after = params->content_end - area->end;
- assert(pending->end <= matches->content_end);
+ if (0x1) printf("---------- iter @ %u -> %u\n", (unsigned int)area->start, (unsigned int)area->end);
+
+ /**
+ * S'il s'avère qu'il existe de multiples correspondances dans l'espace
+ * analysé, c'est la prise en compte d'une éventuelle avarice quant aux
+ * distances consommées qui va sélectionner la position d'une bribe de
+ * correspondance retenue.
+ *
+ * Par exemple, deux correspondances '?1 ?1 [1-3] ?2 ?2' peuvent être
+ * valides pour un même contenu :
+ *
+ * aa.bbb -> correspondance 'aa.bb'
+ * ^
+ *
+ * aa.bbb -> correspondance 'aa..bb'
+ * ^
+ */
- after = matches->content_end - pending->end;
+ min_end = params->content_end;
+ max_end = params->content_start;
- new_begin = pending->end;
+ updated = false;
- if (ocount > 0)
+ /* Souplesse dans les positions ? */
+ if (offsets_exist(&params->offset))
{
- for (o = 0; o < ocount; o++)
+ ranges = get_node_search_offset_ranges_2(&params->offset, &rcount);
+
+ for (r = 0; r < rcount; r++)
{
- range = (*ranges_ptr) + o;
-
- /**
- * Si bornes de tolérance il y a, l'espace restant est validé en
- * tenant compte de ces bornes.
- */
- if (!get_node_offset_range(range, node->len, after, &min, &max))
- continue;
-
- /**
- * Une recherche des différentes correspondances amont est lancée.
- */
- for (j = min; j <= max; j++)
+ assert(ranges[r].has_max);
+ assert((ranges[r].max - ranges[r].min) <= MAX_RANGE_FOR_MANUAL_CHECK);
+
+ for (p = ranges[r].min; p <= ranges[r].max; p++)
{
+ /**
+ * Si la fin d'une correspondance potentielle est trop près de
+ * la fin du contenu binaire et ne peut contenir le motif
+ * représenté, alors la corresponance est écartée sans appel.
+ */
+ if ((p + node->len) > after)
+ break;
+
status = check_scan_token_node_masked_content(node->bytes, node->len,
- new_begin + j, content);
+ area->end + p, params->content);
- if ((status && !not) || (!status && not))
+ if (status)
{
- /**
- * S'il s'avère qu'il existe de multiples correspondances dans l'espace
- * analysé, c'est la fonction extend_pending_match_ending() qui
- * duplique cette correspondance, en s'appuyant sur le TTL pour
- * repérer ce cas de figure.
- *
- * Par exemple, deux correspondances '?1 ?1 [1-3] ?2 ?2'
- * sont valides pour un même contenu :
- *
- * aa.bbb -> correspondance 'aa.bb'
- * ^
- *
- * aa.bbb -> correspondance 'aa..bb'
- * ^
- */
- extend_pending_match_ending(matches, p, new_begin + j + node->len);
+ updated_edge = area->end + p + node->len;
- /**
- * Comme l'extension a pu conduire à un ajout et donc à une
- * réallocation de la liste, on recharge l'élément pour les
- * itérations suivantes.
- */
- pending = (*pending_ptr) + p;
+ if (updated_edge < min_end)
+ min_end = updated_edge;
+
+ if (updated_edge > max_end)
+ max_end = updated_edge;
+
+ updated = true;
}
@@ -611,55 +695,133 @@ static void g_scan_token_node_masked_check_forward(const GScanTokenNodeMasked *n
}
+ /* Position immédiatement attendue */
else
{
/**
* Si la fin d'une correspondance potentielle est trop près de
* la fin du contenu binaire et ne peut contenir le motif
- * représenté, alors la corresponance est écartée.
+ * représenté, alors la corresponance est écartée sans appel.
*/
- if (node->len > after)
- continue;
+ if (node->len <= after)
+ {
+ status = check_scan_token_node_masked_content(node->bytes, node->len,
+ area->end, params->content);
+
+ if (status)
+ {
+ updated_edge = area->end + node->len;
+
+ min_end = updated_edge;
+ max_end = updated_edge;
+
+ updated = true;
+
+ }
+
+ }
- new_begin = pending->end;
+ }
- status = check_scan_token_node_masked_content(node->bytes, node->len, new_begin, content);
+ if (updated)
+ {
+ /**
+ * Si seuls les rejets sont d'intérêt, les correspondances établies
+ * ne se voient pas mises à jours ni retirées.
+ */
- if ((status && !not) || (!status && not))
+ if ((cflags & TNCF_KEEP_DISCARDED) == 0)
{
- extend_pending_match_ending(matches, p, new_begin + node->len);
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ area->end = (1 /* greedy */ ? min_end : max_end);
- /**
- * Comme il n'y a qu'une seule itération par correspondance,
- * nul besoin de recharcher l'élément.
- */
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ new_area = g_umem_slice_alloc(params->allocator);
+
+ *new_area = *area;
+
+ new_area->end = (1 /* greedy */ ? min_end : max_end);
+
+ add_tail_match_area(new_area, &params->created_areas);
+ params->created_count++;
+
+ }
+
+#ifndef NDEBUG
+ else
+ assert(false);
+#endif
}
}
- }
+ else
+ {
+ /**
+ * Si la liste principale doit être mise à jour...
+ */
- purge_pending_matches(matches);
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ {
+ del_match_area(area, &params->main_areas);
+ assert(params->main_count > 0);
+ params->main_count--;
+ }
+
+ /**
+ * Au cas où le rejet est d'intérêt, l'absence de correspondance
+ * est conservée dans une liste dédiée.
+ */
+
+ if (cflags & TNCF_KEEP_DISCARDED)
+ {
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ {
+ add_tail_match_area(area, &params->kept_areas);
+ params->kept_count++;
+ }
+
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ new_area = g_umem_slice_alloc(params->allocator);
+
+ *new_area = *area;
+
+ new_area->end = (1 /* greedy */ ? min_end : max_end);
+
+ add_tail_match_area(new_area, &params->kept_areas);
+ params->kept_count++;
+
+ }
+
+#ifndef NDEBUG
+ else
+ assert(false);
+#endif
+
+ }
+
+ }
+
+ }
}
- set_pending_matches_initialized(matches);
+ params->initialized = true;
- disable_all_ranges_in_node_search_offset(offset);
+ disable_all_ranges_in_node_search_offset(&params->offset);
}
/******************************************************************************
* *
-* Paramètres : node = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
-* matches = suivi des correspondances à consolider. *
-* offsets = tolérance dans les positions à appliquer. *
-* not = indique si les résultats doivent être inversés. *
-* skip = détermine si l'analyse est différée. [OUT] *
+* Paramètres : node = définition de la bribe à manipuler. *
+* params = accès direct aux éléments utiles aux validations. *
+* cflags = altérations de traitement à respecter. *
+* skip = détermine si l'analyse est différée. [OUT] *
* *
* Description : Transforme les correspondances locales en trouvailles. *
* *
@@ -669,26 +831,32 @@ static void g_scan_token_node_masked_check_forward(const GScanTokenNodeMasked *n
* *
******************************************************************************/
-static void g_scan_token_node_masked_check_backward(const GScanTokenNodeMasked *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip)
+static void g_scan_token_node_masked_check_backward(const GScanTokenNodeMasked *node, scan_node_check_params_t *params, TokenNodeCheckFlags cflags, bool *skip)
{
#ifndef NDEBUG
bool forced; /* Inclusion dans un scan ? */
#endif
- size_t pcount; /* Nombre de correspondances */
- match_area_t * const *pending_ptr; /* Correspondances actuelles */
- size_t ocount; /* Quantité de bornes présentes*/
- node_offset_range_t * const *ranges_ptr;/* Bornes d'espace à parcourir */
- size_t p; /* Boucle de parcours #1 */
- const match_area_t *pending; /* Correspondance à traiter */
- phys_t before; /* Espace disposible avant */
- phys_t new_begin; /* Nouveau départ à tester */
- size_t o; /* Boucle de parcours #2 */
- const node_offset_range_t *range; /* Bornes d'espace à parcourir */
- phys_t min; /* Borne minimale déterminée */
- phys_t max; /* Borne maximale déterminée */
- phys_t j; /* Boucle de parcours #3 */
+
+
+
bool status; /* Bilan d'une correspondance */
+
+ match_area_t *area; /* Correspondance à valider */
+ match_area_t *next; /* Correspondance suivante */
+ phys_t before; /* Espace disposible avant */
+ phys_t min_start; /* Début le plus proche trouvé */
+ phys_t max_start; /* Début le plus distant trouvé*/
+ bool updated; /* Existence de correspondance */
+ size_t rcount; /* Quantité de bornes présentes*/
+ const node_offset_range_t *ranges; /* Bornes d'espace à parcourir */
+ size_t r; /* Boucle de parcours #xxxxxxxxxxxx*/
+ phys_t p; /* Boucle de parcours #xxxxxxxxxxxx*/
+ phys_t updated_edge; /* Nouvelle bordure de motif */
+ match_area_t *new_area; /* Copie de correspondance */
+
+ if (0x1) printf("=================== CHECK :: %s (skip? %d)\n", __FUNCTION__, *skip);
+
if (*skip)
return;
@@ -696,7 +864,7 @@ static void g_scan_token_node_masked_check_backward(const GScanTokenNodeMasked *
* En lecture à rebourd, au moins un noeud a été solicité pour analyse (lors
* du sens de lecteur normal). Donc l'initialisation a déjà dû avoir lieu.
*/
- assert(are_pending_matches_initialized(matches));
+ assert(params->initialized);
/**
* Si les recherches associées au noeud ont été forcées, alors les traitements
@@ -707,65 +875,121 @@ static void g_scan_token_node_masked_check_backward(const GScanTokenNodeMasked *
assert(!forced);
#endif
- reset_pending_matches_ttl(matches);
- pending_ptr = get_all_pending_matches(matches, &pcount);
- ranges_ptr = get_node_search_offset_ranges(offset, &ocount);
- for (p = 0; p < pcount; p++)
+ /**
+ * .............
+ */
+ if (0)
{
- pending = (*pending_ptr) + p;
- assert(matches->content_start <= pending->start);
- before = pending->start - matches->content_start;
+ ;
+
+
- new_begin = pending->start - node->len;
+ }
+
+ /**
+ * Poursuite des traitements sur des correspondances déjà amorcées, impliquant
+ * des comparaisons entières de motifs.
+ */
+ else
+ {
+ if (0x1) printf(" LIST : %p (sz = %zu)\n", params->main_areas, params->main_count);
- if (ocount > 0)
+ for_each_match_area_safe(area, &params->main_areas, next)
{
- for (o = 0; o < ocount; o++)
+ assert(params->content_start <= area->start);
+
+ before = area->start - params->content_start;
+
+ if (0x1) printf("---------- iter @ %u -> %u\n", (unsigned int)area->start, (unsigned int)area->end);
+
+ /**
+ * Il ne peut y avoir qu'une seule séquence d'octets à un même
+ * emplacement. En revanche, des modificateurs peuvent construire
+ * possédant une même base, mais offrant des suffixes différents
+ * (par exemple, un marqueur nul UTF-16 final en complément).
+ *
+ * L'ensemble des combinaisons produites doit ainsi être exploré.
+ */
+
+ min_start = params->content_start;
+ max_start = params->content_end;
+
+ updated = false;
+
+ /* Souplesse dans les positions ? */
+ if (offsets_exist(&params->offset))
{
- range = (*ranges_ptr) + o;
+ ranges = get_node_search_offset_ranges_2(&params->offset, &rcount);
- /**
- * Si bornes de tolérance il y a, l'espace restant est validé en
- * tenant compte de ces bornes.
- */
- if (!get_node_offset_range(range, node->len, before, &min, &max))
+ for (r = 0; r < rcount; r++)
{
- if (not)
- extend_pending_match_beginning(matches, p, pending->start - node->len);
+ assert(ranges[r].has_max);
+ assert((ranges[r].max - ranges[r].min) <= MAX_RANGE_FOR_MANUAL_CHECK);
+
+ for (p = ranges[r].min; p <= ranges[r].max; p++)
+ {
+ /**
+ * Si la fin d'une correspondance potentielle est trop près de
+ * la fin du contenu binaire et ne peut contenir le motif
+ * représenté, alors la corresponance est écartée sans appel.
+ */
+ if ((p + node->len) > before)
+ break;
+
+ status = check_scan_token_node_masked_content(node->bytes, node->len,
+ area->start - node->len - p,
+ params->content);
+
+ if (status)
+ {
+ updated_edge = area->start - node->len - p;
+
+ if (updated_edge > min_start)
+ min_start = updated_edge;
+
+ if (updated_edge < max_start)
+ max_start = updated_edge;
+
+ updated = true;
- continue;
+ }
+
+ }
}
+ }
+
+ /* Position immédiatement attendue */
+ else
+ {
/**
- * Une recherche des différentes correspondances amont est lancée.
+ * Si la fin d'une correspondance potentielle est trop près du
+ * début du contenu binaire et ne peut contenir le motif
+ * représenté, alors la corresponance est écartée sans appel.
*/
- for (j = min; j <= max; j++)
+ if (node->len <= before)
{
status = check_scan_token_node_masked_content(node->bytes, node->len,
- new_begin - j, content);
+ area->start - node->len,
+ params->content);
- if ((status && !not) || (!status && not))
+ if (status)
{
- /**
- * S'il s'avère qu'il existe de multiples correspondances dans l'espace
- * analysé, c'est la fonction extend_pending_match_beginning() qui
- * duplique cette correspondance, en s'appuyant sur le TTL pour
- * repérer ce cas de figure.
- */
- extend_pending_match_beginning(matches, p, new_begin);
+ updated_edge = area->start - node->len;
- /**
- * Comme l'extension a pu conduire à un ajout et donc à une
- * réallocation de la liste, on recharge l'élément pour les
- * itérations suivantes.
- */
- pending = (*pending_ptr) + p;
+ if (updated_edge > min_start)
+ min_start = updated_edge;
+
+ if (updated_edge < max_start)
+ max_start = updated_edge;
+
+ updated = true;
}
@@ -773,35 +997,92 @@ static void g_scan_token_node_masked_check_backward(const GScanTokenNodeMasked *
}
- }
-
- else
- {
- /**
- * Si le début d'une correspondance potentielle est trop près du début
- * du contenu binaire et ne peut contenir le motif représenté, alors
- * la corresponance est écartée.
- */
- if (node->len > before)
+ if (updated)
{
- if (not)
- extend_pending_match_beginning(matches, p, new_begin);
+ /**
+ * Si seuls les rejets sont d'intérêt, les correspondances établies
+ * ne se voient pas mises à jours ni retirées.
+ */
+
+ if ((cflags & TNCF_KEEP_DISCARDED) == 0)
+ {
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ area->start = (1 /* greedy */ ? min_start : max_start);
+
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ new_area = g_umem_slice_alloc(params->allocator);
+
+ *new_area = *area;
+
+ new_area->start = (1 /* greedy */ ? min_start : max_start);
+
+ add_tail_match_area(new_area, &params->created_areas);
+ params->created_count++;
+
+ }
+
+#ifndef NDEBUG
+ else
+ assert(false);
+#endif
- continue;
+ }
}
- status = check_scan_token_node_masked_content(node->bytes, node->len, new_begin, content);
+ else
+ {
+ /**
+ * Si la liste principale doit être mise à jour...
+ */
+
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ {
+ del_match_area(area, &params->main_areas);
+ assert(params->main_count > 0);
+ params->main_count--;
+ }
+
+ /**
+ * Au cas où le rejet est d'intérêt, l'absence de correspondance
+ * est conservée dans une liste dédiée.
+ */
- if ((status && !not) || (!status && not))
- extend_pending_match_beginning(matches, p, new_begin);
+ if (cflags & TNCF_KEEP_DISCARDED)
+ {
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ {
+ add_tail_match_area(area, &params->kept_areas);
+ params->kept_count++;
+ }
+
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ new_area = g_umem_slice_alloc(params->allocator);
+
+ *new_area = *area;
+
+ new_area->start = (1 /* greedy */ ? min_start : max_start);
+
+ add_tail_match_area(new_area, &params->kept_areas);
+ params->kept_count++;
+
+ }
+
+#ifndef NDEBUG
+ else
+ assert(false);
+#endif
+
+ }
+
+ }
}
}
- purge_pending_matches(matches);
-
- disable_all_ranges_in_node_search_offset(offset);
+ disable_all_ranges_in_node_search_offset(&params->offset);
}
diff --git a/src/analysis/scan/patterns/tokens/nodes/masked.h b/src/analysis/scan/patterns/tokens/nodes/masked.h
index d1765fa..04a05bc 100644
--- a/src/analysis/scan/patterns/tokens/nodes/masked.h
+++ b/src/analysis/scan/patterns/tokens/nodes/masked.h
@@ -49,15 +49,6 @@ typedef struct _GScanTokenNodeMasked GScanTokenNodeMasked;
typedef struct _GScanTokenNodeMaskedClass GScanTokenNodeMaskedClass;
-/* Mémorisation d'un octet visé avec son masque */
-typedef struct _masked_byte_t
-{
- bin_t value; /* Valeur de l'octet visé */
- bin_t mask; /* Masque à appliquer */
-
-} masked_byte_t;
-
-
/* Indique le type défini pour un noeud représentant une bribe partielle à retrouver. */
GType g_scan_token_node_masked_get_type(void);
diff --git a/src/analysis/scan/patterns/tokens/nodes/not.c b/src/analysis/scan/patterns/tokens/nodes/not.c
index 645a1c8..81fce28 100644
--- a/src/analysis/scan/patterns/tokens/nodes/not.c
+++ b/src/analysis/scan/patterns/tokens/nodes/not.c
@@ -24,6 +24,9 @@
#include "not.h"
+#include <assert.h>
+
+
#include "not-int.h"
@@ -48,17 +51,23 @@ static void g_scan_token_node_not_finalize(GScanTokenNodeNot *);
/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+/* Prend acte d'une nouvelle propriété pour le noeud. */
+static void g_scan_token_node_not_apply_flags(GScanTokenNodeNot *, ScanTokenNodeFlags);
+
/* Parcourt une arborescence de noeuds et y relève des éléments. */
static void g_scan_token_node_not_visit(GScanTokenNodeNot *, scan_tree_points_t *);
/* Inscrit la définition d'un motif dans un moteur de recherche. */
-static bool g_scan_token_node_not_enroll(GScanTokenNodeNot *, GScanContext *, GEngineBackend *, size_t, size_t *);
+static bool g_scan_token_node_not_enroll(GScanTokenNodeNot *, GEngineBackend *, size_t, size_t *);
+
+/* Récupère un identifiant final pour un atome d'octets. */
+static bool g_scan_token_node_not_build_id(GScanTokenNodeNot *, GEngineBackend *);
/* Transforme les correspondances locales en trouvailles. */
-static void g_scan_token_node_not_check_forward(const GScanTokenNodeNot *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *);
+static void g_scan_token_node_not_check_forward(const GScanTokenNodeNot *, scan_node_check_params_t *, TokenNodeCheckFlags, bool *);
/* Transforme les correspondances locales en trouvailles. */
-static void g_scan_token_node_not_check_backward(const GScanTokenNodeNot *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *);
+static void g_scan_token_node_not_check_backward(const GScanTokenNodeNot *, scan_node_check_params_t *, TokenNodeCheckFlags, bool *);
@@ -95,8 +104,10 @@ static void g_scan_token_node_not_class_init(GScanTokenNodeNotClass *klass)
node = G_SCAN_TOKEN_NODE_CLASS(klass);
+ node->apply = (apply_scan_token_node_flags_fc)g_scan_token_node_not_apply_flags;
node->visit = (visit_scan_token_node_fc)g_scan_token_node_not_visit;
node->enroll = (enroll_scan_token_node_fc)g_scan_token_node_not_enroll;
+ node->build_id = (build_scan_token_node_id_fc)g_scan_token_node_not_build_id;
node->check_forward = (check_scan_token_node_fc)g_scan_token_node_not_check_forward;
node->check_backward = (check_scan_token_node_fc)g_scan_token_node_not_check_backward;
@@ -223,6 +234,26 @@ bool g_scan_token_node_not_create(GScanTokenNodeNot *not, GScanTokenNode *child)
/******************************************************************************
* *
+* Paramètres : node = noeud de motif à mettre à jour. *
+* flags = propriétés particulières à associer au noeud. *
+* *
+* Description : Prend acte d'une nouvelle propriété pour le noeud. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_token_node_not_apply_flags(GScanTokenNodeNot *node, ScanTokenNodeFlags flags)
+{
+ g_scan_token_node_set_flags(node->child, flags);
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : node = point de départ du parcours à effectuer. *
* points = points capitaux de l'arborescence. [OUT] *
* *
@@ -244,7 +275,6 @@ static void g_scan_token_node_not_visit(GScanTokenNodeNot *node, scan_tree_point
/******************************************************************************
* *
* Paramètres : node = définition de la bribe à enregistrer. *
-* context = contexte de l'analyse à mener. *
* backend = moteur de recherche à préchauffer. *
* maxsize = taille max. des atomes (mise en commun optimisée). *
* slow = niveau de ralentissement induit (0 = idéal). [OUT] *
@@ -257,11 +287,11 @@ static void g_scan_token_node_not_visit(GScanTokenNodeNot *node, scan_tree_point
* *
******************************************************************************/
-static bool g_scan_token_node_not_enroll(GScanTokenNodeNot *node, GScanContext *context, GEngineBackend *backend, size_t maxsize, size_t *slow)
+static bool g_scan_token_node_not_enroll(GScanTokenNodeNot *node, GEngineBackend *backend, size_t maxsize, size_t *slow)
{
bool result; /* Statut à retourner */
- result = _g_scan_token_node_enroll(node->child, context, backend, maxsize, slow);
+ result = _g_scan_token_node_enroll(node->child, backend, maxsize, slow);
return result;
@@ -270,13 +300,34 @@ static bool g_scan_token_node_not_enroll(GScanTokenNodeNot *node, GScanContext *
/******************************************************************************
* *
-* Paramètres : node = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
-* matches = suivi des correspondances à consolider. *
-* offset = tolérance dans les positions à appliquer. *
-* not = indique si les résultats doivent être inversés. *
-* skip = détermine si l'analyse est différée. [OUT] *
+* Paramètres : node = définition de la bribe à peaufiner. *
+* backend = moteur de recherche à préchauffer. *
+* *
+* Description : Récupère un identifiant final pour un atome d'octets. *
+* *
+* Retour : Bilan de l'opération à renvoyer. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_token_node_not_build_id(GScanTokenNodeNot *node, GEngineBackend *backend)
+{
+ bool result; /* Statut à retourner */
+
+ result = g_scan_token_node_build_id(node->child, backend);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : node = définition de la bribe à manipuler. *
+* params = accès direct aux éléments utiles aux validations. *
+* cflags = altérations de traitement à respecter. *
+* skip = détermine si l'analyse est différée. [OUT] *
* *
* Description : Transforme les correspondances locales en trouvailles. *
* *
@@ -286,8 +337,12 @@ static bool g_scan_token_node_not_enroll(GScanTokenNodeNot *node, GScanContext *
* *
******************************************************************************/
-static void g_scan_token_node_not_check_forward(const GScanTokenNodeNot *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip)
+static void g_scan_token_node_not_check_forward(const GScanTokenNodeNot *node, scan_node_check_params_t *params, TokenNodeCheckFlags cflags, bool *skip)
{
+
+#if 0
+
+
bool initialized; /* Initialisation du suivi ? */
phys_t i; /* Boucle de parcours */
@@ -322,7 +377,7 @@ static void g_scan_token_node_not_check_forward(const GScanTokenNodeNot *node, G
_g_scan_token_node_check_forward(node->child, context, content, matches, offset, !not, skip);
-
+#endif
}
@@ -330,13 +385,10 @@ static void g_scan_token_node_not_check_forward(const GScanTokenNodeNot *node, G
/******************************************************************************
* *
-* Paramètres : node = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
-* matches = suivi des correspondances à consolider. *
-* offset = tolérance dans les positions à appliquer. *
-* not = indique si les résultats doivent être inversés. *
-* skip = détermine si l'analyse est différée. [OUT] *
+* Paramètres : node = définition de la bribe à manipuler. *
+* params = accès direct aux éléments utiles aux validations. *
+* cflags = altérations de traitement à respecter. *
+* skip = détermine si l'analyse est différée. [OUT] *
* *
* Description : Transforme les correspondances locales en trouvailles. *
* *
@@ -346,7 +398,7 @@ static void g_scan_token_node_not_check_forward(const GScanTokenNodeNot *node, G
* *
******************************************************************************/
-static void g_scan_token_node_not_check_backward(const GScanTokenNodeNot *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip)
+static void g_scan_token_node_not_check_backward(const GScanTokenNodeNot *node, scan_node_check_params_t *params, TokenNodeCheckFlags cflags, bool *skip)
{
diff --git a/src/analysis/scan/patterns/tokens/nodes/plain.c b/src/analysis/scan/patterns/tokens/nodes/plain.c
index 71f5f17..166ce74 100644
--- a/src/analysis/scan/patterns/tokens/nodes/plain.c
+++ b/src/analysis/scan/patterns/tokens/nodes/plain.c
@@ -52,20 +52,26 @@ static void g_scan_token_node_plain_finalize(GScanTokenNodePlain *);
/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+/* Communique l'intérêt d'un noeud au sein d'une analyse. */
+static float g_scan_token_node_plain_compute_weight_for_scan(const GScanTokenNodePlain *);
+
/* Parcourt une arborescence de noeuds et y relève des éléments. */
static void g_scan_token_node_plain_visit(GScanTokenNodePlain *, scan_tree_points_t *);
/* Inscrit la définition d'un motif dans un moteur de recherche. */
-static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *, GScanContext *, GEngineBackend *, size_t, size_t *);
+static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *, GEngineBackend *, size_t, size_t *);
+
+/* Récupère un identifiant final pour un atome d'octets. */
+static bool g_scan_token_node_plain_build_id(GScanTokenNodePlain *, GEngineBackend *);
/* Détermine si un contenu d'intérêt est présent à une position. */
static bool check_scan_token_node_plain_content(const sized_binary_t *, const tracked_scan_atom_t *, bool, phys_t, GBinContent *);
/* Transforme les correspondances locales en trouvailles. */
-static void g_scan_token_node_plain_check_forward(const GScanTokenNodePlain *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *);
+static void g_scan_token_node_plain_check_forward(const GScanTokenNodePlain *, scan_node_check_params_t *, TokenNodeCheckFlags, bool *);
/* Transforme les correspondances locales en trouvailles. */
-static void g_scan_token_node_plain_check_backward(const GScanTokenNodePlain *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *);
+static void g_scan_token_node_plain_check_backward(const GScanTokenNodePlain *, scan_node_check_params_t *, TokenNodeCheckFlags, bool *);
@@ -102,8 +108,11 @@ static void g_scan_token_node_plain_class_init(GScanTokenNodePlainClass *klass)
node = G_SCAN_TOKEN_NODE_CLASS(klass);
+ node->compute_weight = (compute_scan_token_node_weight_fc)g_scan_token_node_plain_compute_weight_for_scan;
+ node->apply = (apply_scan_token_node_flags_fc)NULL;
node->visit = (visit_scan_token_node_fc)g_scan_token_node_plain_visit;
node->enroll = (enroll_scan_token_node_fc)g_scan_token_node_plain_enroll;
+ node->build_id = (build_scan_token_node_id_fc)g_scan_token_node_plain_build_id;
node->check_forward = (check_scan_token_node_fc)g_scan_token_node_plain_check_forward;
node->check_backward = (check_scan_token_node_fc)g_scan_token_node_plain_check_backward;
@@ -124,8 +133,6 @@ static void g_scan_token_node_plain_class_init(GScanTokenNodePlainClass *klass)
static void g_scan_token_node_plain_init(GScanTokenNodePlain *plain)
{
- g_scan_token_node_set_flags(G_SCAN_TOKEN_NODE(plain), STNF_PROD);
-
init_szstr(&plain->orig);
plain->modifier = NULL;
plain->flags = SPNF_NONE;
@@ -314,6 +321,29 @@ char *g_scan_token_node_plain_get_modifier_path(const GScanTokenNodePlain *node,
/******************************************************************************
* *
+* Paramètres : node = noeud de motif à consulter. *
+* *
+* Description : Communique l'intérêt d'un noeud au sein d'une analyse. *
+* *
+* Retour : Poids de l'importance pour un départ de scan. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static float g_scan_token_node_plain_compute_weight_for_scan(const GScanTokenNodePlain *node)
+{
+ float result; /* Valeur à retourner */
+
+ result = node->orig.len;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : node = point de départ du parcours à effectuer. *
* points = points capitaux de l'arborescence. [OUT] *
* *
@@ -327,9 +357,25 @@ char *g_scan_token_node_plain_get_modifier_path(const GScanTokenNodePlain *node,
static void g_scan_token_node_plain_visit(GScanTokenNodePlain *node, scan_tree_points_t *points)
{
+ GScanTokenNode *candidate; /* Autre version du noeud */
+ float node_weight; /* Poids du noeud courant */
+ float other_weight; /* Poids de l'autre noeud */
+
if (points->first_plain == NULL)
points->first_plain = G_SCAN_TOKEN_NODE(node);
+ else
+ {
+ candidate = G_SCAN_TOKEN_NODE(node);
+
+ node_weight = g_scan_token_node_compute_weight_for_scan(candidate);
+ other_weight = g_scan_token_node_compute_weight_for_scan(points->first_plain);
+
+ if (node_weight >= other_weight)
+ points->first_plain = candidate;
+
+ }
+
}
@@ -349,7 +395,7 @@ static void g_scan_token_node_plain_visit(GScanTokenNodePlain *node, scan_tree_p
* *
******************************************************************************/
-static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *node, GScanContext *context, GEngineBackend *backend, size_t maxsize, size_t *slow)
+static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *node, GEngineBackend *backend, size_t maxsize, size_t *slow)
{
bool result; /* Statut à retourner */
size_t i; /* Boucle de parcours #1 */
@@ -442,7 +488,7 @@ static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *node, GScanConte
/* Enregistrements en masse */
for (i = 0; i < node->count && result; i++)
- result = enroll_prepared_atom(&node->raw[i], context, backend, &node->atoms[i]);
+ result = enroll_prepared_atom(&node->raw[i], backend, &node->atoms[i]);
exit:
@@ -453,6 +499,34 @@ static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *node, GScanConte
/******************************************************************************
* *
+* Paramètres : node = définition de la bribe à peaufiner. *
+* backend = moteur de recherche à préchauffer. *
+* *
+* Description : Récupère un identifiant final pour un atome d'octets. *
+* *
+* Retour : Bilan de l'opération à renvoyer. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_token_node_plain_build_id(GScanTokenNodePlain *node, GEngineBackend *backend)
+{
+ bool result; /* Statut à retourner */
+ size_t i; /* Boucle de parcours #1 */
+
+ result = true;
+
+ for (i = 0; i < node->count && result; i++)
+ result = build_atom_pattern_id(&node->atoms[i], backend);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : raw = contneu brut à retrouver idéalement. *
* atom = contenu brut représentatif ciblé. *
* nocase = marque un éventuel désintérêt pour la casse. *
@@ -478,11 +552,11 @@ static bool check_scan_token_node_plain_content(const sized_binary_t *raw, const
init_vmpa(&pos, start, VMPA_NO_VIRTUAL);
- /* Validation du contenu avant l'atome */
+ /* Validation du motif intégral */
- if (atom->pos > 0)
+ if (atom == NULL)
{
- ptr = g_binary_content_get_raw_access(content, &pos, atom->pos);
+ ptr = g_binary_content_get_raw_access(content, &pos, raw->len);
/**
* Si la partion atomique recherchée est trouvée en début de contenu,
@@ -492,39 +566,67 @@ static bool check_scan_token_node_plain_content(const sized_binary_t *raw, const
if (ptr == NULL) goto done;
if (nocase)
- ret = memcasecmp(raw->data, ptr, atom->pos);
+ ret = memcasecmp(raw->data, ptr, raw->len);
else
- ret = memcmp(raw->data, ptr, atom->pos);
+ ret = memcmp(raw->data, ptr, raw->len);
- if (ret != 0) goto done;
+ result = (ret == 0);
}
- /* Validation du contenu après l'atome */
+ /* Validation des extrémités */
- if (atom->rem > 0)
+ else
{
- advance_vmpa(&pos, atom->len);
+ /* Validation du contenu avant l'atome */
- ptr = g_binary_content_get_raw_access(content, &pos, atom->rem);
+ if (atom->pos > 0)
+ {
+ ptr = g_binary_content_get_raw_access(content, &pos, atom->pos);
- /**
- * Si la partion atomique recherchée est trouvée en fin de contenu,
- * le reste du motif de recherche va déborder. L'accès correspondant
- * est donc refusé, et cette situation est prise en compte ici.
- */
- if (ptr == NULL) goto done;
+ /**
+ * Si la partion atomique recherchée est trouvée en début de contenu,
+ * le reste du motif de recherche va déborder. L'accès correspondant
+ * est donc refusé, et cette situation est prise en compte ici.
+ */
+ if (ptr == NULL) goto done;
- if (nocase)
- ret = memcasecmp(raw->data + atom->pos + atom->len, ptr, atom->rem);
- else
- ret = memcmp(raw->data + atom->pos + atom->len, ptr, atom->rem);
+ if (nocase)
+ ret = memcasecmp(raw->data, ptr, atom->pos);
+ else
+ ret = memcmp(raw->data, ptr, atom->pos);
- if (ret != 0) goto done;
+ if (ret != 0) goto done;
- }
+ }
- result = true;
+ /* Validation du contenu après l'atome */
+
+ if (atom->rem > 0)
+ {
+ advance_vmpa(&pos, atom->len);
+
+ ptr = g_binary_content_get_raw_access(content, &pos, atom->rem);
+
+ /**
+ * Si la partion atomique recherchée est trouvée en fin de contenu,
+ * le reste du motif de recherche va déborder. L'accès correspondant
+ * est donc refusé, et cette situation est prise en compte ici.
+ */
+ if (ptr == NULL) goto done;
+
+ if (nocase)
+ ret = memcasecmp(raw->data + atom->pos + atom->len, ptr, atom->rem);
+ else
+ ret = memcmp(raw->data + atom->pos + atom->len, ptr, atom->rem);
+
+ if (ret != 0) goto done;
+
+ }
+
+ result = true;
+
+ }
done:
@@ -535,13 +637,10 @@ static bool check_scan_token_node_plain_content(const sized_binary_t *raw, const
/******************************************************************************
* *
-* Paramètres : node = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
-* matches = suivi des correspondances à consolider. *
-* offset = tolérance dans les positions à appliquer. *
-* not = indique si les résultats doivent être inversés. *
-* skip = détermine si l'analyse est différée. [OUT] *
+* Paramètres : node = définition de la bribe à manipuler. *
+* params = accès direct aux éléments utiles aux validations. *
+* cflags = altérations de traitement à respecter. *
+* skip = détermine si l'analyse est différée. [OUT] *
* *
* Description : Transforme les correspondances locales en trouvailles. *
* *
@@ -551,236 +650,408 @@ static bool check_scan_token_node_plain_content(const sized_binary_t *raw, const
* *
******************************************************************************/
-static void g_scan_token_node_plain_check_forward(const GScanTokenNodePlain *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip)
+static void g_scan_token_node_plain_check_forward(const GScanTokenNodePlain *node, scan_node_check_params_t *params, TokenNodeCheckFlags cflags, bool *skip)
{
- bool initialized; /* Initialisation du suivi ? */
bool track_path; /* Conservation du chemin */
bool nocase; /* Pas d'intérêt pour la casse */
- size_t ocount; /* Quantité de bornes présentes*/
size_t i; /* Boucle de parcours #1 */
const sized_binary_t *raw; /* Données brutes d'origine */
const tracked_scan_atom_t *atom; /* Atome correspondant */
- size_t count; /* Quantité de bribes trouvées */
- const phys_t *found; /* Localisations des bribes */
- size_t k; /* Boucle de parcours #2 */
- phys_t new_begin; /* Nouveau départ à tester */
+ GUMemSlice *atoms; /* Localisations des bribes */
+ const umem_slice_iter_t *aiter; /* Boucle de parcours #2 */
+ match_area_t *end; /* Borne de fin de parcours */
+ match_area_t *pos; /* Position courante */
bool status; /* Bilan d'une correspondance */
- size_t pcount; /* Nombre de correspondances */
- match_area_t * const *pending_ptr; /* Correspondances actuelles */
- size_t p; /* Boucle de parcours #3 */
- const match_area_t *pending; /* Correspondance à traiter */
+ match_area_t *area; /* Correspondance à valider */
+ match_area_t *next; /* Correspondance suivante */
+ phys_t after; /* Espace disposible après */
+ phys_t min_end; /* Fin la plus proche possible */
+ phys_t max_end; /* Fin la plus éloignée trouvée*/
+ bool updated; /* Existence de correspondance */
+ size_t rcount; /* Quantité de bornes présentes*/
+ const node_offset_range_t *ranges; /* Bornes d'espace à parcourir */
+ size_t r; /* Boucle de parcours #xxxxxxxxxxxx*/
+ phys_t p; /* Boucle de parcours #xxxxxxxxxxxx*/
+ phys_t updated_edge; /* Nouvelle bordure de motif */
+ match_area_t *new_area; /* Copie de correspondance */
+
+ if (0x1) printf("=================== CHECK :: %s (skip? %d)\n", __FUNCTION__, *skip);
if (*skip)
return;
- initialized = are_pending_matches_initialized(matches);
-
track_path = (G_SCAN_TOKEN_NODE(node)->flags & STNF_MAIN);
nocase = (node->flags & SPNF_CASE_INSENSITIVE);
- get_node_search_offset_ranges(offset, &ocount);
-
- for (i = 0; i < node->count; i++)
+ /**
+ * Création de premières marques de correspondances.
+ */
+ if (!params->initialized)
{
- raw = &node->raw[i];
- atom = &node->atoms[i];
+ for (i = 0; i < node->count; i++)
+ {
+ raw = &node->raw[i];
+ atom = &node->atoms[i];
- found = g_scan_context_get_atom_matches(context, atom->pid, &count);
+ atoms = g_scan_context_get_atom_matches(params->context, atom->pid);
- if (!initialized)
- {
- for (k = 0; k < count; k++)
+ if (atom->fast_check)
{
- new_begin = found[k] - atom->pos;
-
- /**
- * Si personne n'a manipulé les pré-résultats, mais qu'un décallage
- * est spécifié par un noeud précédent, une validation sur la base
- * d'une position 0 est menée.
- */
- if (ocount > 0)
+ for (aiter = g_umem_slice_get_iter(atoms); aiter != NULL; aiter = aiter->next)
{
- if (!does_node_search_offset_include_pos_forward(offset, 0, new_begin))
+ end = aiter->data_end;
+
+ for (pos = aiter->data; pos < end; pos++)
{
- if (not)
- add_pending_match(matches, new_begin, raw->len);
+ /**
+ * La modification de la zone d'origine est possible dans tous les cas
+ * car cette zone a été allouée de façon dédiée à un type de correspondances
+ * et ne sera pas réutilisée comme autre source de correspondance ailleurs.
+ */
+ pos->end = pos->start + atom->len;
- continue;
+ if (cflags & TNCF_KEEP_DISCARDED)
+ {
+ add_tail_match_area(pos, &params->kept_areas);
+ params->kept_count++;
+ }
+
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ add_tail_match_area(pos, &params->created_areas);
+ params->created_count++;
+ }
+
+ else
+ {
+ assert(cflags & TNCF_UPDATE_IN_PLACE);
+
+ add_tail_match_area(pos, &params->main_areas);
+ params->main_count++;
+
+ }
}
+
}
- status = check_scan_token_node_plain_content(raw, atom, nocase, new_begin, content);
+ }
- if ((status && !not) || (!status && not))
+ else
+ {
+ for (aiter = g_umem_slice_get_iter(atoms); aiter != NULL; aiter = aiter->next)
{
- /**
- * Il ne peut y avoir qu'une seule séquence d'octets à un même
- * emplacement, donc le couple (new_begin, len) enregistré est
- * unique.
- */
- if (track_path)
- add_pending_match_with_path(matches, new_begin, raw->len, i);
- else
- add_pending_match(matches, new_begin, raw->len);
+ end = aiter->data_end;
+
+ for (pos = aiter->data; pos < end; pos++)
+ {
+ status = check_scan_token_node_plain_content(raw, atom, nocase,
+ pos->start - atom->pos, params->content);
+
+ if (status)
+ {
+ /**
+ * La modification de la zone d'origine est possible dans tous les cas
+ * car cette zone a été allouée de façon dédiée à un type de correspondances
+ * et ne sera pas réutilisée comme autre source de correspondance ailleurs.
+ */
+ pos->start -= atom->pos;
+ pos->end = pos->start + raw->len;
+
+ if (cflags & TNCF_KEEP_DISCARDED)
+ {
+ add_tail_match_area(pos, &params->kept_areas);
+ params->kept_count++;
+ }
+
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ add_tail_match_area(pos, &params->created_areas);
+ params->created_count++;
+ }
+
+ else
+ {
+ assert(cflags & TNCF_UPDATE_IN_PLACE);
+
+ add_tail_match_area(pos, &params->main_areas);
+ params->main_count++;
+
+ }
+
+ }
+
+ }
}
+
}
}
- else
- {
- reset_pending_matches_ttl(matches);
+ }
- pending_ptr = get_all_pending_matches(matches, &pcount);
+ /**
+ * Poursuite des traitements sur des correspondances déjà amorcées, impliquant
+ * des comparaisons entières de motifs.
+ */
+ else
+ {
+ if (0x1) printf(" LIST : %p (sz = %zu)\n", params->main_areas, params->main_count);
- for (p = 0; p < pcount; p++)
+ for_each_match_area_safe(area, &params->main_areas, next)
+ {
+ assert(area->end <= params->content_end);
+
+ after = params->content_end - area->end;
+
+ if (0x1) printf("---------- iter @ %u -> %u\n", (unsigned int)area->start, (unsigned int)area->end);
+
+ /**
+ * Il ne peut y avoir qu'une seule séquence d'octets à un même
+ * emplacement. En revanche, des modificateurs peuvent construire
+ * possédant une même base, mais offrant des suffixes différents
+ * (par exemple, un marqueur nul UTF-16 final en complément).
+ *
+ * L'ensemble des combinaisons produites doit ainsi être exploré.
+ */
+
+ /**
+ * Par ailleurs, même si une base de couples uniques est assurée,
+ * la constitution d'un ensemble de noeuds peut amener une redondance
+ * dans les emplacements de correspondances ; ces doublons éventuels
+ * sont alors filtrés par un appel à sort_match_areas_no_dup().
+ *
+ * Par exemple, pour la séquence d'octets analysés suivante :
+ *
+ * aaa....bbb
+ *
+ * La définition { (61 61 | 61 61 61) [4-5] 62 62 62 } peut établir
+ * les correspondances suivantes :
+ *
+ * aa.....bbb -> couple pending[x] (0;2) puis (0;10)
+ * ^
+ * aa....bbb -> couple pending[y] (1;3) puis (1;10)
+ * ^
+ * aaa....bbb -> couple pending[z] (0;3) puis (0;10)
+ * ^
+ *
+ * Par ailleurs, une même base de départ peut conduire à plusieurs
+ * zones de correspondances.
+ *
+ * Par exemple, pour la séquence d'octets analysés suivante :
+ *
+ * aa..bb..bb
+ *
+ * La définition { 61 61 [2-6] 62 62 } peut établir
+ * les correspondances suivantes :
+ *
+ * aa..bb..bb -> couple pending[x] (0;2) puis (0;6)
+ * ^
+ * aa..bb..bb -> couple pending[x] (0;2) puis (0;10)
+ * ^
+ */
+
+ /**
+ * Dans la première situation, c'est la bribe 62 62 62 qui fait l'objet
+ * d'une recherche de motifs. Les autres bribes sont recherchées
+ * manuellement ici, car l'espace de séparation est léger (inférieur à
+ * MAX_RANGE_FOR_MANUAL_CHECK).
+ *
+ * La seconde situation bénéficie de recherches automatisées pour
+ * l'ensemble des motifs, du fait d'une valeur de séparation plus
+ * importante.
+ *
+ * Dans les deux cas, l'espace de séparation est entièrement considéré.
+ * La sélection de la correspondance à retour s'établit selon un
+ * paramètre de configuation : doit-on être avare sur les distances
+ * consommées ou non ?
+ */
+
+ min_end = params->content_end;
+ max_end = params->content_start;
+
+ updated = false;
+
+ for (i = 0; i < node->count; i++)
{
- pending = (*pending_ptr) + p;
+ raw = &node->raw[i];
- assert(matches->content_start <= pending->start);
-
- for (k = 0; k < count; k++)
+ /* Souplesse dans les positions ? */
+ if (offsets_exist(&params->offset))
{
- new_begin = found[k] - atom->pos;
+ ranges = get_node_search_offset_ranges_2(&params->offset, &rcount);
- /**
- * Si bornes de tolérance il y a, on valide la position.
- *
- * Sinon les correspondances passées et actuelle doivent
- * être jointes.
- */
- if (ocount > 0)
+ for (r = 0; r < rcount; r++)
{
- if (!does_node_search_offset_include_pos_forward(offset, pending->end, new_begin))
+ assert(ranges[r].has_max);
+ assert((ranges[r].max - ranges[r].min) <= MAX_RANGE_FOR_MANUAL_CHECK);
+
+ for (p = ranges[r].min; p <= ranges[r].max; p++)
{
- if (not)
+ /**
+ * Si la fin d'une correspondance potentielle est trop près de
+ * la fin du contenu binaire et ne peut contenir le motif
+ * représenté, alors la corresponance est écartée sans appel.
+ */
+ if ((p + raw->len) > after)
+ break;
+
+ status = check_scan_token_node_plain_content(raw, NULL, nocase,
+ area->end + p, params->content);
+
+ if (status)
{
- extend_pending_match_ending(matches, p, pending->end + raw->len);
+ updated_edge = area->end + p + raw->len;
- /**
- * Comme l'extension a pu conduire à un ajout et donc à une
- * réallocation de la liste, on recharge l'élément pour les
- * itérations suivantes.
- */
- pending = (*pending_ptr) + p;
+ if (updated_edge < min_end)
+ min_end = updated_edge;
- }
+ if (updated_edge > max_end)
+ max_end = updated_edge;
- continue;
+ updated = true;
+
+ }
}
+
}
- else
+
+ }
+
+ /* Position immédiatement attendue */
+ else
+ {
+ /**
+ * Si la fin d'une correspondance potentielle est trop près de
+ * la fin du contenu binaire et ne peut contenir le motif
+ * représenté, alors la corresponance est écartée sans appel.
+ */
+ if (raw->len > after)
+ continue;
+
+ status = check_scan_token_node_plain_content(raw, NULL, nocase, area->end, params->content);
+
+ if (status)
{
- if (pending->end != new_begin)
- {
- if (not)
- {
- extend_pending_match_ending(matches, p, pending->end + raw->len);
+ updated_edge = area->end + raw->len;
- /**
- * Comme l'extension a pu conduire à un ajout et donc à une
- * réallocation de la liste, on recharge l'élément pour les
- * itérations suivantes.
- */
- pending = (*pending_ptr) + p;
+ if (updated_edge < min_end)
+ min_end = updated_edge;
- }
+ if (updated_edge > max_end)
+ max_end = updated_edge;
- continue;
+ updated = true;
- }
}
- status = check_scan_token_node_plain_content(raw, atom, nocase, new_begin, content);
+ }
- if ((status && !not) || (!status && not))
+ }
+
+ if (updated)
+ {
+ /**
+ * Si seuls les rejets sont d'intérêt, les correspondances établies
+ * ne se voient pas mises à jours ni retirées.
+ */
+
+ if ((cflags & TNCF_KEEP_DISCARDED) == 0)
+ {
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ area->end = (1 /* greedy */ ? min_end : max_end);
+
+ else if (cflags & TNCF_CREATE_NEW)
{
- /**
- * Même si une base de couples uniques est assurée,
- * la constitution d'un ensemble de noeuds peut amener une
- * redondance dans les emplacements de correspondances.
- *
- * Par exemple, pour la séquence d'octets analysés suivante :
- *
- * aaa....bbb
- *
- * La définition { (61 61 | 61 61 61) [4-5] 62 62 62 } peut établir
- * les correspondances suivantes :
- *
- * aa.....bbb -> couple pending[x] (0;2) puis (0;10)
- * ^
- * aa....bbb -> couple pending[y] (1;3) puis (1;10)
- * ^
- * aaa....bbb -> couple pending[z] (0;3) puis (0;10)
- * ^
- *
- * Par ailleurs, une même base de départ peut conduire
- * à plusieurs zone de correspondances.
- *
- * Par exemple, pour la séquence d'octets analysés suivante :
- *
- * aa..bb..bb
- *
- * La définition { 61 61 [2-6] 62 62 } peut établir
- * les correspondances suivantes :
- *
- * aa..bb..bb -> couple pending[x] (0;2) puis (0;6)
- * ^
- * aa..bb..bb -> couple pending[x] (0;2) puis (0;10)
- * ^
- */
+ new_area = g_umem_slice_alloc(params->allocator);
- /**
- * La seconde situation est prise en compte par la fonction
- * extend_pending_match_ending() qui s'appuie sur le TTL pour
- * dupliquer la correspondance pending[x] initiale. Le nouvel
- * élément est placé en fin de liste, ce qui ne boulverse pas
- * le parcours de liste courant, la valeur de pcount n'étant
- * pas actualisée.
- */
+ *new_area = *area;
- extend_pending_match_ending(matches, p, new_begin + raw->len);
+ new_area->end = (1 /* greedy */ ? min_end : max_end);
- /**
- * Comme l'extension a pu conduire à un ajout et donc à une
- * réallocation de la liste, on recharge l'élément pour les
- * itérations suivantes.
- */
- pending = (*pending_ptr) + p;
+ add_tail_match_area(new_area, &params->created_areas);
+ params->created_count++;
}
+#ifndef NDEBUG
+ else
+ assert(false);
+#endif
+
}
}
- purge_pending_matches(matches);
+ else
+ {
+ /**
+ * Si la liste principale doit être mise à jour...
+ */
+
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ {
+ del_match_area(area, &params->main_areas);
+ assert(params->main_count > 0);
+ params->main_count--;
+ }
+
+ /**
+ * Au cas où le rejet est d'intérêt, l'absence de correspondance
+ * est conservée dans une liste dédiée.
+ */
+
+ if (cflags & TNCF_KEEP_DISCARDED)
+ {
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ {
+ add_tail_match_area(area, &params->kept_areas);
+ params->kept_count++;
+ }
+
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ new_area = g_umem_slice_alloc(params->allocator);
+
+ *new_area = *area;
+
+ new_area->end = (1 /* greedy */ ? min_end : max_end);
+
+ add_tail_match_area(new_area, &params->kept_areas);
+ params->kept_count++;
+
+ }
+
+#ifndef NDEBUG
+ else
+ assert(false);
+#endif
+
+ }
+
+ }
}
}
- set_pending_matches_initialized(matches);
+ params->initialized = true;
- disable_all_ranges_in_node_search_offset(offset);
+ disable_all_ranges_in_node_search_offset(&params->offset);
}
/******************************************************************************
* *
-* Paramètres : node = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
-* matches = suivi des correspondances à consolider. *
-* offset = tolérance dans les positions à appliquer. *
-* not = indique si les résultats doivent être inversés. *
-* skip = détermine si l'analyse est différée. [OUT] *
+* Paramètres : node = définition de la bribe à manipuler. *
+* params = accès direct aux éléments utiles aux validations. *
+* cflags = altérations de traitement à respecter. *
+* skip = détermine si l'analyse est différée. [OUT] *
* *
* Description : Transforme les correspondances locales en trouvailles. *
* *
@@ -790,19 +1061,272 @@ static void g_scan_token_node_plain_check_forward(const GScanTokenNodePlain *nod
* *
******************************************************************************/
-static void g_scan_token_node_plain_check_backward(const GScanTokenNodePlain *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip)
+static void g_scan_token_node_plain_check_backward(const GScanTokenNodePlain *node, scan_node_check_params_t *params, TokenNodeCheckFlags cflags, bool *skip)
{
+
+
+ bool track_path; /* Conservation du chemin */
+ bool nocase; /* Pas d'intérêt pour la casse */
+
+
+
+
+ size_t i; /* Boucle de parcours #1 */
+
+
+ const sized_binary_t *raw; /* Données brutes d'origine */
+
+
+ bool status; /* Bilan d'une correspondance */
+
+
+
+
+
+ match_area_t *area; /* Correspondance à valider */
+ match_area_t *next; /* Correspondance suivante */
+ phys_t before; /* Espace disposible avant */
+ phys_t min_start; /* Début le plus proche trouvé */
+ phys_t max_start; /* Début le plus distant trouvé*/
+ bool updated; /* Existence de correspondance */
+ size_t rcount; /* Quantité de bornes présentes*/
+ const node_offset_range_t *ranges; /* Bornes d'espace à parcourir */
+ size_t r; /* Boucle de parcours #xxxxxxxxxxxx*/
+ phys_t p; /* Boucle de parcours #xxxxxxxxxxxx*/
+ phys_t updated_edge; /* Nouvelle bordure de motif */
+ match_area_t *new_area; /* Copie de correspondance */
+
+ if (0x1) printf("=================== CHECK :: %s (skip? %d)\n", __FUNCTION__, *skip);
+
if (*skip)
return;
+ /**
+ * En lecture à rebourd, au moins un noeud a été solicité pour analyse (lors
+ * du sens de lecture normal). Donc l'initialisation a déjà dû avoir lieu.
+ */
+
+ assert(params->initialized);
+
+ track_path = (G_SCAN_TOKEN_NODE(node)->flags & STNF_MAIN);
+
+ nocase = (node->flags & SPNF_CASE_INSENSITIVE);
+
- printf("TODO\n");
- assert(0);
+ /**
+ * .............
+ */
+ if (0)
+ {
+
+
+ ;
+
+
+
+ }
+
+ /**
+ * Poursuite des traitements sur des correspondances déjà amorcées, impliquant
+ * des comparaisons entières de motifs.
+ */
+ else
+ {
+ if (0x1) printf(" LIST : %p (sz = %zu)\n", params->main_areas, params->main_count);
+
+ for_each_match_area_safe(area, &params->main_areas, next)
+ {
+ assert(params->content_start <= area->start);
+
+ before = area->start - params->content_start;
+
+ if (0x1) printf("---------- iter @ %u -> %u\n", (unsigned int)area->start, (unsigned int)area->end);
+
+ /**
+ * Il ne peut y avoir qu'une seule séquence d'octets à un même
+ * emplacement. En revanche, des modificateurs peuvent construire
+ * possédant une même base, mais offrant des suffixes différents
+ * (par exemple, un marqueur nul UTF-16 final en complément).
+ *
+ * L'ensemble des combinaisons produites doit ainsi être exploré.
+ */
+
+ min_start = params->content_start;
+ max_start = params->content_end;
+
+ updated = false;
+
+ for (i = 0; i < node->count; i++)
+ {
+ raw = &node->raw[i];
+
+ /* Souplesse dans les positions ? */
+ if (offsets_exist(&params->offset))
+ {
+ ranges = get_node_search_offset_ranges_2(&params->offset, &rcount);
+ for (r = 0; r < rcount; r++)
+ {
+ assert(ranges[r].has_max);
+ assert((ranges[r].max - ranges[r].min) <= MAX_RANGE_FOR_MANUAL_CHECK);
+
+ for (p = ranges[r].min; p <= ranges[r].max; p++)
+ {
+ /**
+ * Si la fin d'une correspondance potentielle est trop près de
+ * la fin du contenu binaire et ne peut contenir le motif
+ * représenté, alors la corresponance est écartée sans appel.
+ */
+ if ((p + raw->len) > before)
+ break;
+
+ status = check_scan_token_node_plain_content(raw, NULL, nocase,
+ area->start - raw->len - p,
+ params->content);
+
+ if (status)
+ {
+ updated_edge = area->start - raw->len - p;
+
+ if (updated_edge > min_start)
+ min_start = updated_edge;
+
+ if (updated_edge < max_start)
+ max_start = updated_edge;
+
+ updated = true;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ /* Position immédiatement attendue */
+ else
+ {
+ /**
+ * Si la fin d'une correspondance potentielle est trop près du
+ * début du contenu binaire et ne peut contenir le motif
+ * représenté, alors la corresponance est écartée sans appel.
+ */
+ if (raw->len > before)
+ continue;
+
+ status = check_scan_token_node_plain_content(raw, NULL, nocase,
+ area->start - raw->len,
+ params->content);
+
+ if (status)
+ {
+ updated_edge = area->start - raw->len;
+
+ if (updated_edge > min_start)
+ min_start = updated_edge;
+
+ if (updated_edge < max_start)
+ max_start = updated_edge;
+
+ updated = true;
+
+ }
+
+ }
+
+ }
+
+ if (updated)
+ {
+ /**
+ * Si seuls les rejets sont d'intérêt, les correspondances établies
+ * ne se voient pas mises à jours ni retirées.
+ */
+
+ if ((cflags & TNCF_KEEP_DISCARDED) == 0)
+ {
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ area->start = (1 /* greedy */ ? min_start : max_start);
+
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ new_area = g_umem_slice_alloc(params->allocator);
+
+ *new_area = *area;
+
+ new_area->start = (1 /* greedy */ ? min_start : max_start);
+
+ add_tail_match_area(new_area, &params->created_areas);
+ params->created_count++;
+
+ }
+
+#ifndef NDEBUG
+ else
+ assert(false);
+#endif
+
+ }
+
+ }
+
+ else
+ {
+ /**
+ * Si la liste principale doit être mise à jour...
+ */
+
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ {
+ del_match_area(area, &params->main_areas);
+ assert(params->main_count > 0);
+ params->main_count--;
+ }
+
+ /**
+ * Au cas où le rejet est d'intérêt, l'absence de correspondance
+ * est conservée dans une liste dédiée.
+ */
+
+ if (cflags & TNCF_KEEP_DISCARDED)
+ {
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ {
+ add_tail_match_area(area, &params->kept_areas);
+ params->kept_count++;
+ }
+
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ new_area = g_umem_slice_alloc(params->allocator);
+
+ *new_area = *area;
+
+ new_area->start = (1 /* greedy */ ? min_start : max_start);
+
+ add_tail_match_area(new_area, &params->kept_areas);
+ params->kept_count++;
+
+ }
+
+#ifndef NDEBUG
+ else
+ assert(false);
+#endif
+
+ }
+
+ }
+
+ }
+
+ }
+ disable_all_ranges_in_node_search_offset(&params->offset);
}
diff --git a/src/analysis/scan/patterns/tokens/nodes/sequence.c b/src/analysis/scan/patterns/tokens/nodes/sequence.c
index 91307bf..394c877 100644
--- a/src/analysis/scan/patterns/tokens/nodes/sequence.c
+++ b/src/analysis/scan/patterns/tokens/nodes/sequence.c
@@ -24,6 +24,9 @@
#include "sequence.h"
+#include <assert.h>
+
+
#include "any.h"
#include "sequence-int.h"
@@ -49,17 +52,23 @@ static void g_scan_token_node_sequence_finalize(GScanTokenNodeSequence *);
/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+/* Prend acte d'une nouvelle propriété pour le noeud. */
+static void g_scan_token_node_sequence_apply_flags(GScanTokenNodeSequence *, ScanTokenNodeFlags);
+
/* Parcourt une arborescence de noeuds et y relève des éléments. */
static void g_scan_token_node_sequence_visit(GScanTokenNodeSequence *node, scan_tree_points_t *);
/* Inscrit la définition d'un motif dans un moteur de recherche. */
-static bool g_scan_token_node_sequence_enroll(GScanTokenNodeSequence *, GScanContext *, GEngineBackend *, size_t, size_t *);
+static bool g_scan_token_node_sequence_enroll(GScanTokenNodeSequence *, GEngineBackend *, size_t, size_t *);
+
+/* Récupère un identifiant final pour un atome d'octets. */
+static bool g_scan_token_node_sequence_build_id(GScanTokenNodeSequence *, GEngineBackend *);
/* Transforme les correspondances locales en trouvailles. */
-static void g_scan_token_node_sequence_check_forward(const GScanTokenNodeSequence *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *);
+static void g_scan_token_node_sequence_check_forward(const GScanTokenNodeSequence *, scan_node_check_params_t *, TokenNodeCheckFlags, bool *);
/* Transforme les correspondances locales en trouvailles. */
-static void g_scan_token_node_sequence_check_backward(const GScanTokenNodeSequence *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *);
+static void g_scan_token_node_sequence_check_backward(const GScanTokenNodeSequence *, scan_node_check_params_t *, TokenNodeCheckFlags, bool *);
@@ -76,7 +85,7 @@ G_DEFINE_TYPE(GScanTokenNodeSequence, g_scan_token_node_sequence, G_TYPE_SCAN_TO
* *
* Paramètres : klass = classe à initialiser. *
* *
-* Description : Initialise la classe des décompositions séquentielles. *
+* Description : Initialise la classe des décompositions séquentielles. *
* *
* Retour : - *
* *
@@ -96,8 +105,10 @@ static void g_scan_token_node_sequence_class_init(GScanTokenNodeSequenceClass *k
node = G_SCAN_TOKEN_NODE_CLASS(klass);
+ node->apply = (apply_scan_token_node_flags_fc)g_scan_token_node_sequence_apply_flags;
node->visit = (visit_scan_token_node_fc)g_scan_token_node_sequence_visit;
node->enroll = (enroll_scan_token_node_fc)g_scan_token_node_sequence_enroll;
+ node->build_id = (build_scan_token_node_id_fc)g_scan_token_node_sequence_build_id;
node->check_forward = (check_scan_token_node_fc)g_scan_token_node_sequence_check_forward;
node->check_backward = (check_scan_token_node_fc)g_scan_token_node_sequence_check_backward;
@@ -330,6 +341,40 @@ GScanTokenNode *g_scan_token_node_sequence_get(const GScanTokenNodeSequence *seq
/******************************************************************************
* *
+* Paramètres : node = noeud de motif à mettre à jour. *
+* flags = propriétés particulières à associer au noeud. *
+* *
+* Description : Prend acte d'une nouvelle propriété pour le noeud. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_token_node_sequence_apply_flags(GScanTokenNodeSequence *node, ScanTokenNodeFlags flags)
+{
+ size_t i; /* Boucle de parcours */
+
+ if (node->count == 1)
+ g_scan_token_node_set_flags(node->children[0], flags);
+
+ else if (node->count > 1)
+ {
+ g_scan_token_node_set_flags(node->children[0], flags & ~STNF_LAST);
+
+ for (i = 1; i < (node->count - 1); i++)
+ g_scan_token_node_set_flags(node->children[i], flags & ~(STNF_FIRST | STNF_LAST));
+
+ g_scan_token_node_set_flags(node->children[node->count - 1], flags & ~STNF_FIRST);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : node = point de départ du parcours à effectuer. *
* points = points capitaux de l'arborescence. [OUT] *
* *
@@ -354,7 +399,6 @@ static void g_scan_token_node_sequence_visit(GScanTokenNodeSequence *node, scan_
/******************************************************************************
* *
* Paramètres : node = définition de la bribe à enregistrer. *
-* context = contexte de l'analyse à mener. *
* backend = moteur de recherche à préchauffer. *
* maxsize = taille max. des atomes (mise en commun optimisée). *
* slow = niveau de ralentissement induit (0 = idéal). [OUT] *
@@ -367,7 +411,7 @@ static void g_scan_token_node_sequence_visit(GScanTokenNodeSequence *node, scan_
* *
******************************************************************************/
-static bool g_scan_token_node_sequence_enroll(GScanTokenNodeSequence *node, GScanContext *context, GEngineBackend *backend, size_t maxsize, size_t *slow)
+static bool g_scan_token_node_sequence_enroll(GScanTokenNodeSequence *node, GEngineBackend *backend, size_t maxsize, size_t *slow)
{
bool result; /* Statut à retourner */
size_t i; /* Boucle de parcours */
@@ -375,7 +419,35 @@ static bool g_scan_token_node_sequence_enroll(GScanTokenNodeSequence *node, GSca
result = true;
for (i = 0; i < node->count && result; i++)
- result = _g_scan_token_node_enroll(node->children[i], context, backend, maxsize, slow);
+ result = _g_scan_token_node_enroll(node->children[i], backend, maxsize, slow);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : node = définition de la bribe à peaufiner. *
+* backend = moteur de recherche à préchauffer. *
+* *
+* Description : Récupère un identifiant final pour un atome d'octets. *
+* *
+* Retour : Bilan de l'opération à renvoyer. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_token_node_sequence_build_id(GScanTokenNodeSequence *node, GEngineBackend *backend)
+{
+ bool result; /* Statut à retourner */
+ size_t i; /* Boucle de parcours #1 */
+
+ result = true;
+
+ for (i = 0; i < node->count && result; i++)
+ result = g_scan_token_node_build_id(node->children[i], backend);
return result;
@@ -384,13 +456,10 @@ static bool g_scan_token_node_sequence_enroll(GScanTokenNodeSequence *node, GSca
/******************************************************************************
* *
-* Paramètres : node = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
-* matches = suivi des correspondances à consolider. *
-* offset = tolérance dans les positions à appliquer. *
-* not = indique si les résultats doivent être inversés. *
-* skip = détermine si l'analyse est différée. [OUT] *
+* Paramètres : node = définition de la bribe à manipuler. *
+* params = accès direct aux éléments utiles aux validations. *
+* cflags = altérations de traitement à respecter. *
+* skip = détermine si l'analyse est différée. [OUT] *
* *
* Description : Transforme les correspondances locales en trouvailles. *
* *
@@ -400,25 +469,22 @@ static bool g_scan_token_node_sequence_enroll(GScanTokenNodeSequence *node, GSca
* *
******************************************************************************/
-static void g_scan_token_node_sequence_check_forward(const GScanTokenNodeSequence *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip)
+static void g_scan_token_node_sequence_check_forward(const GScanTokenNodeSequence *node, scan_node_check_params_t *params, TokenNodeCheckFlags cflags, bool *skip)
{
size_t i; /* Boucle de parcours */
for (i = 0; i < node->count; i++)
- _g_scan_token_node_check_forward(node->children[i], context, content, matches, offset, not, skip);
+ _g_scan_token_node_check_forward(node->children[i], params, cflags, skip);
}
/******************************************************************************
* *
-* Paramètres : node = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
-* matches = suivi des correspondances à consolider. *
-* offset = tolérance dans les positions à appliquer. *
-* not = indique si les résultats doivent être inversés. *
-* skip = détermine si l'analyse est différée. [OUT] *
+* Paramètres : node = définition de la bribe à manipuler. *
+* params = accès direct aux éléments utiles aux validations. *
+* cflags = altérations de traitement à respecter. *
+* skip = détermine si l'analyse est différée. [OUT] *
* *
* Description : Transforme les correspondances locales en trouvailles. *
* *
@@ -428,11 +494,11 @@ static void g_scan_token_node_sequence_check_forward(const GScanTokenNodeSequenc
* *
******************************************************************************/
-static void g_scan_token_node_sequence_check_backward(const GScanTokenNodeSequence *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip)
+static void g_scan_token_node_sequence_check_backward(const GScanTokenNodeSequence *node, scan_node_check_params_t *params, TokenNodeCheckFlags cflags, bool *skip)
{
size_t i; /* Boucle de parcours */
for (i = node->count; i > 0 ; i--)
- _g_scan_token_node_check_backward(node->children[i - 1], context, content, matches, offset, not, skip);
+ _g_scan_token_node_check_backward(node->children[i - 1], params, cflags, skip);
}
diff --git a/src/analysis/scan/patterns/tokens/offset.c b/src/analysis/scan/patterns/tokens/offset.c
index 010ec67..0a4fd91 100644
--- a/src/analysis/scan/patterns/tokens/offset.c
+++ b/src/analysis/scan/patterns/tokens/offset.c
@@ -229,6 +229,32 @@ node_offset_range_t * const *get_node_search_offset_ranges(const node_search_off
/******************************************************************************
* *
+* Paramètres : offset = suivi de tolérances bornées à consulter. *
+* count = nombre de bornes enregistrées. [OUT] *
+* *
+* Description : Fournit la liste des tolérances bornées établies à présent. *
+* *
+* Retour : Liste d'intervales en lecture seule. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const node_offset_range_t * const get_node_search_offset_ranges_2(const node_search_offset_t *offset, size_t *count)
+{
+ node_offset_range_t *result; /* Série à renvoyer */
+
+ result = offset->gen_ptr;
+
+ *count = offset->used;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : offset = suivi de tolérances bornées à consulter. *
* min = point de départ pour parcourir une zone. *
* max = point d'arrivée pour parcourir une zone. *
@@ -318,6 +344,66 @@ void add_range_to_node_search_offset(node_search_offset_t *offset, phys_t min, p
/******************************************************************************
* *
+* Paramètres : offset = suivi de tolérances bornées à consulter. *
+* min = point de départ pour parcourir une zone. *
+* max = point d'arrivée pour parcourir une zone. *
+* has_max = validité de la valeur maximale transmise. *
+* *
+* Description : Etend les décalages tolérés avec un nouvel espace. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void extend_node_search_offset(node_search_offset_t *offset, phys_t min, phys_t max, bool has_max)
+{
+ size_t i; /* Boucle de parcours */
+
+ switch (offset->used)
+ {
+ /* Si le réceptacle unique peut être employé... */
+ case 0:
+
+ offset->range.min = min;
+ offset->range.max = max;
+ offset->range.has_max = has_max;
+
+ offset->used = 1;
+
+ offset->gen_ptr = &offset->range;
+
+ break;
+
+ /* Si un espace unique est enregistré */
+ case 1:
+
+ offset->range.min += min;
+ offset->range.max += max;
+ offset->range.has_max &= has_max;
+
+ break;
+
+ /* Sinon le groupe dynamique est sollicité */
+ default:
+
+ for (i = 0; i < offset->used; i++)
+ {
+ offset->ranges[i].min += min;
+ offset->ranges[i].max += max;
+ offset->ranges[i].has_max &= has_max;
+ }
+
+ break;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : offset = suivi de tolérances bornées à consulter. *
* last = dernière position validée. *
* pos = nouvelle position potentielle. *
diff --git a/src/analysis/scan/patterns/tokens/offset.h b/src/analysis/scan/patterns/tokens/offset.h
index b458717..130aaea 100644
--- a/src/analysis/scan/patterns/tokens/offset.h
+++ b/src/analysis/scan/patterns/tokens/offset.h
@@ -36,7 +36,7 @@ typedef struct _node_offset_range_t
{
/**
* Les deux champs ci-après font bien référence à des positions absolues,
- * et non à des bornes d'espace, lors que les résultats de correspondances
+ * et non à des bornes d'espace, lorsque les résultats de correspondances
* sont encore non initialisés.
*
* Ensuite ces bornes représentent bien un espace séparant les résultats
@@ -44,6 +44,7 @@ typedef struct _node_offset_range_t
*/
phys_t min; /* Position minimale */
phys_t max; /* Position maximale */
+ bool has_max; /* Quantité définie ? */
} node_offset_range_t;
@@ -53,6 +54,7 @@ bool get_node_offset_range(const node_offset_range_t *, phys_t, phys_t, phys_t *
+#define MAX_RANGE_FOR_MANUAL_CHECK 5
@@ -83,13 +85,21 @@ void merge_node_search_offset(node_search_offset_t *, const node_search_offset_t
/* Met fin à une mémorisation d'intervales de tolérance. */
void exit_node_search_offset(node_search_offset_t *);
+#define offsets_exist(off) \
+ ((off)->used > 0)
+
+
/* Fournit la liste des tolérances bornées établies à présent. */
/* TODO : supprimer un niveau d'indirection */
node_offset_range_t * const *get_node_search_offset_ranges(const node_search_offset_t *, size_t *);
+const node_offset_range_t * const get_node_search_offset_ranges_2(const node_search_offset_t *, size_t *);
/* Ajoute un nouvel espace borné aux décalages tolérés. */
void add_range_to_node_search_offset(node_search_offset_t *, phys_t, phys_t, const phys_t *);
+/* Etend les décalages tolérés avec un nouvel espace. */
+void extend_node_search_offset(node_search_offset_t *, phys_t, phys_t, bool);
+
#define disable_all_ranges_in_node_search_offset(off) \
(off)->used = 0
diff --git a/src/analysis/scan/rule.c b/src/analysis/scan/rule.c
index 638dae5..14a6d38 100644
--- a/src/analysis/scan/rule.c
+++ b/src/analysis/scan/rule.c
@@ -541,7 +541,6 @@ bool g_scan_rule_setup_backend(GScanRule *rule, GEngineBackend *backend, GScanCo
bool result; /* Statut à retourner */
size_t maxsize; /* Taille maximale des atomes */
GSearchPattern *pattern; /* Motif à intégrer */
- GScanOptions *options; /* Options d'analyse */
size_t i; /* Boucle de parcours */
/* Suivi des conditions de correspondance */
@@ -556,22 +555,42 @@ bool g_scan_rule_setup_backend(GScanRule *rule, GEngineBackend *backend, GScanCo
for (i = 0; i < rule->bytes_used && result; i++)
{
pattern = rule->bytes_locals[i];
- result = g_bytes_token_enroll(G_BYTES_TOKEN(pattern), context, backend, maxsize);
+ result = g_bytes_token_enroll(G_BYTES_TOKEN(pattern), backend, maxsize);
}
- g_engine_backend_warm_up(backend);
+ exit:
- /* Affichage éventuel de statistiques */
+ return result;
- options = g_scan_context_get_options(context);
+}
- if (g_scan_options_get_print_stats(options))
- g_engine_backend_output_stats(backend);
+/******************************************************************************
+* *
+* Paramètres : rule = règle de détection à considérer. *
+* backend = moteur d'analyse pour données brutes. *
+* *
+* Description : Récupère les identifiants finaux pour les motifs recherchés. *
+* *
+* Retour : Bilan de l'opération à renvoyer. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- g_object_unref(G_OBJECT(options));
+bool g_scan_rule_define_pattern_ids(GScanRule *rule, GEngineBackend *backend)
+{
+ bool result; /* Statut à retourner */
+ size_t i; /* Boucle de parcours */
+ GSearchPattern *pattern; /* Motif à intégrer */
- exit:
+ result = true;
+
+ for (i = 0; i < rule->bytes_used && result; i++)
+ {
+ pattern = rule->bytes_locals[i];
+ result = g_bytes_token_build_id(G_BYTES_TOKEN(pattern), backend);
+ }
return result;
@@ -594,55 +613,24 @@ bool g_scan_rule_setup_backend(GScanRule *rule, GEngineBackend *backend, GScanCo
void g_scan_rule_check(GScanRule *rule, GEngineBackend *backend, GScanContext *context)
{
- GBinContent *content; /* Contenu à manipuler */
- vmpa2t start; /* Point de début du contenu */
- vmpa2t end; /* Point de fin du contenu */
- pending_matches_t matches; /* Suivi de correspondances */
- size_t i; /* Boucle de parcours #1 */
+ size_t i; /* Boucle de parcours */
GSearchPattern *pattern; /* Motif à intégrer */
- size_t k; /* Boucle de parcours #2 */
- match_area_t *area; /* Zone à initialiser */
- GScanMatch *match; /* Correspondance à mémoriser */
-
- content = g_scan_context_get_content(context);
-
- g_binary_content_compute_start_pos(content, &start);
- g_binary_content_compute_end_pos(content, &end);
-
- /* Consolidation des résultats */
+ GScanBytesMatches *matches; /* Correspondances établies */
for (i = 0; i < rule->bytes_used; i++)
{
- init_pending_matches(&matches, &start.physical, &end.physical);
-
pattern = rule->bytes_locals[i];
- g_bytes_token_check(G_BYTES_TOKEN(pattern), context, content, &matches);
-
- g_scan_context_prepare_full_match_registration(context, pattern, matches.used);
-
- for (k = 0; k < matches.used; k++)
- {
- area = &matches.areas[k];
-
- match = g_scan_bytes_match_new(pattern, content, area->start, area->end - area->start);
+ matches = g_scan_bytes_matches_new(pattern, context);
- if (area->has_mod_path)
- g_scan_bytes_match_remember_modifier_path(G_SCAN_BYTES_MATCH(match), area->mod_path_index);
+ g_bytes_token_check(G_BYTES_TOKEN(pattern), matches);
- g_scan_context_register_full_match(context, match);
- g_object_unref(G_OBJECT(match));
+ g_scan_context_register_full_matches(context, pattern, matches);
- }
-
- exit_pending_matches(&matches);
+ g_object_unref(G_OBJECT(matches));
}
- /* Sortie propre */
-
- g_object_unref(G_OBJECT(content));
-
}
diff --git a/src/analysis/scan/rule.h b/src/analysis/scan/rule.h
index b73ee1a..ea38655 100644
--- a/src/analysis/scan/rule.h
+++ b/src/analysis/scan/rule.h
@@ -96,6 +96,9 @@ void g_scan_rule_set_match_condition(GScanRule *, GScanExpression *);
/* Prépare le suivi de recherche de motifs pour une règle. */
bool g_scan_rule_setup_backend(GScanRule *, GEngineBackend *, GScanContext *);
+/* Récupère les identifiants finaux pour les motifs recherchés. */
+bool g_scan_rule_define_pattern_ids(GScanRule *, GEngineBackend *);
+
/* Lance une analyse d'un contenu binaire selon une règle. */
void g_scan_rule_check(GScanRule *, GEngineBackend *, GScanContext *);
diff --git a/src/analysis/scan/scanner.c b/src/analysis/scan/scanner.c
index 1f90393..507fa6f 100644
--- a/src/analysis/scan/scanner.c
+++ b/src/analysis/scan/scanner.c
@@ -482,17 +482,50 @@ bool g_content_scanner_add_rule(GContentScanner *scanner, GScanRule *rule)
* Remarques : - *
* *
******************************************************************************/
-
+#include <sched.h>
GScanContext *g_content_scanner_analyze(GContentScanner *scanner, GScanOptions *options, GBinContent *content)
{
GScanContext *result; /* Bilan global à retourner */
bool status; /* Bilan d'opération locale */
size_t i; /* Boucle de parcours */
+ size_t ids_count; /* Quantité de motifs prévus */
bool global; /* Bilan des règles globales */
GScanRule *rule; /* Règle à consulter */
const char *name; /* Désignation de la règle */
- /* Préparations... */
+#if 0
+
+ int policy;
+ struct sched_param sp;
+
+
+ policy = sched_getscheduler(0);
+ /*
+ switch(policy) {
+ case SCHED_OTHER: printf("SCHED_OTHER\n"); break;
+ case SCHED_RR: printf("SCHED_RR\n"); break;
+ case SCHED_FIFO: printf("SCHED_FIFO\n"); break;
+ default: printf("Unknown...\n");
+ }
+
+ int policy;
+ ...
+ if((policy = sched_getscheduler(0) == -1)) {
+ fprintf(stderr, ...
+ }
+ */
+
+
+ if(policy == SCHED_OTHER) {
+ sp.sched_priority = sched_get_priority_max(SCHED_FIFO);
+ sched_setscheduler(0, SCHED_FIFO, &sp);
+ }
+
+#endif
+
+
+
+ /* Préparations... */
result = g_scan_context_new(options);
@@ -512,11 +545,23 @@ GScanContext *g_content_scanner_analyze(GContentScanner *scanner, GScanOptions *
goto exit;
}
+ g_engine_backend_warm_up(scanner->data_backend);
+
+ for (i = 0; i < scanner->rule_count && status; i++)
+ status = g_scan_rule_define_pattern_ids(scanner->rules[i], scanner->data_backend);
+
+ /* Affichage éventuel de statistiques */
+
+ if (g_scan_options_get_print_stats(options))
+ g_engine_backend_output_stats(scanner->data_backend);
+
}
/* Phase d'analyse */
- g_scan_context_set_content(result, content);
+ ids_count = g_engine_backend_count_plain_pattern_ids(scanner->data_backend);
+
+ g_scan_context_set_content(result, content, ids_count);
g_engine_backend_run_scan(scanner->data_backend, result);