From 0d5c48ea75a88ae03a7ee8b11c7cf29cb6c46c1b Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Tue, 28 Nov 2023 09:33:08 +0100
Subject: Optimize the registration of full matches.

---
 src/analysis/scan/context-int.h |  1 +
 src/analysis/scan/context.c     | 79 ++++++++++++++++++++++++++++++++++++-----
 src/analysis/scan/context.h     |  3 ++
 src/analysis/scan/rule.c        |  5 +--
 4 files changed, 78 insertions(+), 10 deletions(-)

diff --git a/src/analysis/scan/context-int.h b/src/analysis/scan/context-int.h
index 654ecca..613ca73 100644
--- a/src/analysis/scan/context-int.h
+++ b/src/analysis/scan/context-int.h
@@ -82,6 +82,7 @@ struct _GScanContext
 
     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é   */
 
     bool global;                            /* Validation globale          */
 
diff --git a/src/analysis/scan/context.c b/src/analysis/scan/context.c
index 8a9b600..94ea519 100644
--- a/src/analysis/scan/context.c
+++ b/src/analysis/scan/context.c
@@ -50,6 +50,9 @@ 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 *);
 
@@ -161,6 +164,30 @@ static int compare_full_match_trackers(const full_match_tracker_t **a, const ful
 
 /******************************************************************************
 *                                                                             *
+*  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.                   *
 *                                                                             *
@@ -245,6 +272,7 @@ static void g_scan_context_init(GScanContext *context)
 
     context->full_trackers = NULL;
     context->full_count = 0;
+    context->current_tracker = NULL;
 
     context->global = true;
 
@@ -567,10 +595,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.        *
+*  Paramètres  : context  = instance à mettre à jour.                         *
+*                match    = représentation d'une plein ecorrespondance.       *
+*                expected = quantité totale de correspondances attendue.      *
 *                                                                             *
-*  Description : Enregistre une correspondance complète avec un contenu.      *
+*  Description : Prépare les enregistrements de correspondances complètes.    *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -578,15 +607,12 @@ const phys_t *g_scan_context_get_atom_matches(const GScanContext *context, patid
 *                                                                             *
 ******************************************************************************/
 
-void g_scan_context_register_full_match(GScanContext *context, GScanMatch *match)
+void g_scan_context_prepare_full_match_registration(GScanContext *context, GSearchPattern *pattern, size_t expected)
 {
-    GSearchPattern *pattern;                /* Clef d'un suivi             */
     full_match_tracker_t key;               /* Modèle d'identification     */
     full_match_tracker_t **found;           /* Structure à actualiser      */
     full_match_tracker_t *tracker;          /* Nouveau suivi à intégrer    */
 
-    pattern = g_scan_match_get_source(match);
-
     key.pattern = pattern;
 
     found = bsearch((full_match_tracker_t *[]) { &key }, context->full_trackers, context->full_count,
@@ -604,10 +630,47 @@ void g_scan_context_register_full_match(GScanContext *context, GScanMatch *match
     else
         tracker = *found;
 
-    add_match_to_full_match_tracker(tracker, match);
+    prepare_full_match_tracker(tracker, expected);
+
+    context->current_tracker = tracker;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : context = instance à mettre à jour.                          *
+*                match   = représentation d'une plein ecorrespondance.        *
+*                                                                             *
+*  Description : Enregistre une correspondance complète avec un contenu.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_scan_context_register_full_match(GScanContext *context, GScanMatch *match)
+{
+#ifndef NDEBUG
+    GSearchPattern *pattern;                /* Clef d'un suivi             */
+#endif
+
+    assert(context->current_tracker != NULL);
+
+#ifndef NDEBUG
+
+    pattern = g_scan_match_get_source(match);
+
+    assert(context->current_tracker->pattern == pattern);
 
     g_object_unref(G_OBJECT(pattern));
 
+
+#endif
+
+    add_match_to_full_match_tracker(context->current_tracker, match);
+
 }
 
 
diff --git a/src/analysis/scan/context.h b/src/analysis/scan/context.h
index 7fb3dd4..916c618 100644
--- a/src/analysis/scan/context.h
+++ b/src/analysis/scan/context.h
@@ -89,6 +89,9 @@ void g_scan_context_register_atom_match(GScanContext *, patid_t, phys_t);
 /* Retourne tous les correspondances partielles notées. */
 const phys_t *g_scan_context_get_atom_matches(const GScanContext *, patid_t, size_t *);
 
+/* Prépare les enregistrements de correspondances complètes. */
+void g_scan_context_prepare_full_match_registration(GScanContext *, GSearchPattern *, size_t);
+
 /* Enregistre une correspondance complète avec un contenu. */
 void g_scan_context_register_full_match(GScanContext *, GScanMatch *);
 
diff --git a/src/analysis/scan/rule.c b/src/analysis/scan/rule.c
index e3f84d4..638dae5 100644
--- a/src/analysis/scan/rule.c
+++ b/src/analysis/scan/rule.c
@@ -619,12 +619,13 @@ void g_scan_rule_check(GScanRule *rule, GEngineBackend *backend, GScanContext *c
 
         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(G_SEARCH_PATTERN(pattern), content,
-                                           area->start, area->end - area->start);
+            match = g_scan_bytes_match_new(pattern, content, area->start, area->end - area->start);
 
             if (area->has_mod_path)
                 g_scan_bytes_match_remember_modifier_path(G_SCAN_BYTES_MATCH(match), area->mod_path_index);
-- 
cgit v0.11.2-87-g4458