From 26f93f593542cc550107744e92f95e9516e7435e Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Tue, 20 Feb 2024 09:11:17 +0100
Subject: Share GObject instances between scan contexts and matches.

---
 src/analysis/scan/context.c           |  2 +
 src/analysis/scan/matches-int.h       |  8 ++-
 src/analysis/scan/matches.c           | 55 +++++++++++++++++++-
 src/analysis/scan/matches.h           |  6 +++
 src/analysis/scan/matches/bytes-int.h | 10 ----
 src/analysis/scan/matches/bytes.c     | 98 ++++-------------------------------
 src/analysis/scan/matches/bytes.h     |  5 +-
 src/analysis/scan/patterns/token.c    | 66 +++++++++--------------
 src/analysis/scan/patterns/token.h    |  2 +-
 src/analysis/scan/rule.c              | 26 ++++++++--
 10 files changed, 127 insertions(+), 151 deletions(-)

diff --git a/src/analysis/scan/context.c b/src/analysis/scan/context.c
index 55311c4..fc4194b 100644
--- a/src/analysis/scan/context.c
+++ b/src/analysis/scan/context.c
@@ -430,6 +430,8 @@ void g_scan_context_register_full_matches(GScanContext *context, GSearchPattern
 
     g_hash_table_insert(context->full_trackers, pattern, matches);
 
+    g_scan_matches_attach(matches, context, pattern);
+
 }
 
 
diff --git a/src/analysis/scan/matches-int.h b/src/analysis/scan/matches-int.h
index 674fe03..4e6a244 100644
--- a/src/analysis/scan/matches-int.h
+++ b/src/analysis/scan/matches-int.h
@@ -44,7 +44,13 @@ struct _GScanMatches
 {
     GObject parent;                         /* A laisser en premier        */
 
-    GSearchPattern *source;                 /* Motif d'origine recherché   */
+    /**
+     * L'aspect constant des instances marque seulement le fait que les
+     * pointeurs sont partagés avec un contexte, qui est le réel propriétaire
+     * de ces instances.
+     */
+    const GScanContext *context;            /* Contexte de rattachement    */
+    const GSearchPattern *source;           /* Motif d'origine recherché   */
 
 };
 
diff --git a/src/analysis/scan/matches.c b/src/analysis/scan/matches.c
index 3dc15f9..d83114c 100644
--- a/src/analysis/scan/matches.c
+++ b/src/analysis/scan/matches.c
@@ -84,6 +84,7 @@ static void g_scan_matches_class_init(GScanMatchesClass *klass)
 
 static void g_scan_matches_init(GScanMatches *matches)
 {
+    matches->context = NULL;
     matches->source = NULL;
 
 }
@@ -103,7 +104,10 @@ static void g_scan_matches_init(GScanMatches *matches)
 
 static void g_scan_matches_dispose(GScanMatches *matches)
 {
-    g_clear_object(&matches->source);
+    /**
+     * Contexte et source sont des instances partagées. Leur propriété n'est
+     * donc pas à modifier avec un appel à g_clear_object() ici.
+     */
 
     G_OBJECT_CLASS(g_scan_matches_parent_class)->dispose(G_OBJECT(matches));
 
@@ -131,6 +135,53 @@ static void g_scan_matches_finalize(GScanMatches *matches)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : matches = instance dont l'initialisation est à compléter.    *
+*                context = contexte associé au scan courant.                  *
+*                source  = lien vers le motif recherché d'origine.            *
+*                                                                             *
+*  Description : Associe des éléments de contexte à des correspondances.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : Aucun transfert de propriété n'a lieu ici !                  *
+*                                                                             *
+******************************************************************************/
+
+void g_scan_matches_attach(GScanMatches *matches, const GScanContext *context, const GSearchPattern *source)
+{
+    matches->context = context;
+    matches->source = source;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : matches = informations de correspondances à consulter.       *
+*                                                                             *
+*  Description : Fournit le contexte du scan associé aux correspondances.     *
+*                                                                             *
+*  Retour      : Contexte de scan courant.                                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GScanContext *g_scan_bytes_matches_get_context(const GScanMatches *matches)
+{
+    GScanContext *result;                   /* Instance à retourner        */
+
+    result = (GScanContext *)matches->context;
+
+    g_object_ref(G_OBJECT(result));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : matches = définition de correspondance à consulter.          *
 *                                                                             *
 *  Description : Indique la source du motif d'origine recherché.              *
@@ -145,7 +196,7 @@ GSearchPattern *g_scan_matches_get_source(const GScanMatches *matches)
 {
     GSearchPattern *result;                 /* Source à retourner          */
 
-    result = matches->source;
+    result = (GSearchPattern *)matches->source;
 
     g_object_ref(G_OBJECT(result));
 
diff --git a/src/analysis/scan/matches.h b/src/analysis/scan/matches.h
index 345db96..26e54ed 100644
--- a/src/analysis/scan/matches.h
+++ b/src/analysis/scan/matches.h
@@ -51,6 +51,12 @@ typedef struct _GScanMatchesClass GScanMatchesClass;
 /* Indique le type défini pour une série de correspondances identifiées. */
 GType g_scan_matches_get_type(void);
 
+/* Associe des éléments de contexte à des correspondances. */
+void g_scan_matches_attach(GScanMatches *, const GScanContext *, const GSearchPattern *);
+
+/* Fournit le contexte du scan associé aux correspondances. */
+GScanContext *g_scan_bytes_matches_get_context(const GScanMatches *);
+
 /* Indique la source du motif d'origine recherché. */
 GSearchPattern *g_scan_matches_get_source(const GScanMatches *);
 
diff --git a/src/analysis/scan/matches/bytes-int.h b/src/analysis/scan/matches/bytes-int.h
index d356208..f6239e3 100644
--- a/src/analysis/scan/matches/bytes-int.h
+++ b/src/analysis/scan/matches/bytes-int.h
@@ -37,12 +37,6 @@ struct _GScanBytesMatches
 {
     GScanMatches parent;                    /* A laisser en premier        */
 
-    GScanContext *context;                  /* Contexte de rattachement    */
-
-    // TODO : if NDEBUG ?
-    phys_t content_start;                   /* Point de début du contenu   */
-    phys_t content_end;                     /* Point de fin du contenu     */
-
     match_area_t *areas;                    /* Zones couvertes             */
     size_t count;                           /* Nombre de zones             */
 
@@ -56,9 +50,5 @@ struct _GScanBytesMatchesClass
 };
 
 
-/* Met en place une série de correspondances avec des octets. */
-bool g_scan_bytes_matches_create(GScanBytesMatches *, GSearchPattern *, GScanContext *);
-
-
 
 #endif  /* _ANALYSIS_SCAN_MATCHES_BYTES_INT_H */
diff --git a/src/analysis/scan/matches/bytes.c b/src/analysis/scan/matches/bytes.c
index c4c43bc..218121d 100644
--- a/src/analysis/scan/matches/bytes.c
+++ b/src/analysis/scan/matches/bytes.c
@@ -117,11 +117,6 @@ static void g_scan_bytes_matches_class_init(GScanBytesMatchesClass *klass)
 
 static void g_scan_bytes_matches_init(GScanBytesMatches *matches)
 {
-    matches->context = NULL;
-
-    matches->content_start = VMPA_NO_PHYSICAL;
-    matches->content_end = VMPA_NO_PHYSICAL;
-
     matches->areas = NULL;
     matches->count = 0;
 
@@ -142,8 +137,6 @@ static void g_scan_bytes_matches_init(GScanBytesMatches *matches)
 
 static void g_scan_bytes_matches_dispose(GScanBytesMatches *matches)
 {
-    //g_clear_object(&matches->context);
-
     G_OBJECT_CLASS(g_scan_bytes_matches_parent_class)->dispose(G_OBJECT(matches));
 
 }
@@ -170,8 +163,7 @@ static void g_scan_bytes_matches_finalize(GScanBytesMatches *matches)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : source  = lien vers le motif recherché d'origine.            *
-*                context = contexte associé au scan courant.                  *
+*  Paramètres  : -                                                            *
 *                                                                             *
 *  Description : Crée un suivi pour série de correspondances avec des octets. *
 *                                                                             *
@@ -181,87 +173,12 @@ static void g_scan_bytes_matches_finalize(GScanBytesMatches *matches)
 *                                                                             *
 ******************************************************************************/
 
-GScanMatches *g_scan_bytes_matches_new(GSearchPattern *source, GScanContext *context)
+GScanMatches *g_scan_bytes_matches_new(void)
 {
     GScanMatches *result;                   /* Structure à retourner       */
 
     result = g_object_new(G_TYPE_SCAN_BYTES_MATCHES, NULL);
 
-    if (!g_scan_bytes_matches_create(G_SCAN_BYTES_MATCHES(result), source, context))
-        g_clear_object(&result);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : matches = instance à initialiser pleinement.                 *
-*                source  = lien vers le motif recherché d'origine.            *
-*                context = contexte associé au scan courant.                  *
-*                                                                             *
-*  Description : Met en place une série de correspondances avec des octets.   *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool g_scan_bytes_matches_create(GScanBytesMatches *matches, GSearchPattern *source, GScanContext *context)
-{
-    bool result;                            /* Bilan à retourner           */
-    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_MATCHES(matches);
-
-    base->source = source;
-    g_object_ref(G_OBJECT(source));
-
-    matches->context = context;
-    //g_object_ref(G_OBJECT(context));
-
-    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;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : matches = informations de correspondances à consulter.       *
-*                                                                             *
-*  Description : Fournit le contexte du scan associé aux correspondances.     *
-*                                                                             *
-*  Retour      : Contexte de scan courant.                                    *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GScanContext *g_scan_bytes_matches_get_context(const GScanBytesMatches *matches)
-{
-    GScanContext *result;                   /* Instance à retourner        */
-
-    result = matches->context;
-
-    g_object_ref(G_OBJECT(result));
-
     return result;
 
 }
@@ -433,8 +350,8 @@ char *g_scan_bytes_matches_get_modifier_path(const GScanBytesMatches *matches)
 
 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 */
+    GBinContent *content;                   /* Contenu binaire analysé     */
     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   */
@@ -444,10 +361,10 @@ static void g_scan_bytes_matches_output_to_text(const GScanBytesMatches *matches
     const bin_t *data;                      /* Accès aux données brutes    */
     phys_t k;                               /* Boucle de parcours #2       */
 
-    content = g_scan_context_get_content(matches->context);
-
     base = G_SCAN_MATCHES(matches);
 
+    content = g_scan_context_get_content(base->context);
+
     name = g_search_pattern_get_name(base->source);
 
     for_each_match_area(iter, matches->areas)
@@ -547,6 +464,7 @@ static void g_scan_bytes_matches_output_to_json(const GScanBytesMatches *matches
     unsigned int i;                         /* Boucle de parcours #1       */
     char value[4 + ULLONG_MAXLEN];          /* Impression de la position   */
     int ret;                                /* Bilan d'une conversion      */
+    GScanMatches *base;                     /* Lien vers les infos de base */
     GBinContent *content;                   /* Contenu binaire analysé     */
     match_area_t *iter;                     /* Boucle de parcours #1       */
     vmpa2t pos;                             /* Tête de lecture             */
@@ -581,7 +499,9 @@ static void g_scan_bytes_matches_output_to_json(const GScanBytesMatches *matches
 
     write(fd, "\"matches\": [\n", 13);
 
-    content = g_scan_context_get_content(matches->context);
+    base = G_SCAN_MATCHES(matches);
+
+    content = g_scan_context_get_content(base->context);
 
     for_each_match_area(iter, matches->areas)
     {
diff --git a/src/analysis/scan/matches/bytes.h b/src/analysis/scan/matches/bytes.h
index 9e046aa..50f60a4 100644
--- a/src/analysis/scan/matches/bytes.h
+++ b/src/analysis/scan/matches/bytes.h
@@ -56,10 +56,7 @@ typedef struct _GScanBytesMatchesClass GScanBytesMatchesClass;
 GType g_scan_bytes_matches_get_type(void);
 
 /* 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 *);
+GScanMatches *g_scan_bytes_matches_new(void);
 
 /* Intègre une liste de correspondances vérifiées. */
 void g_scan_bytes_matches_set_list(GScanBytesMatches *, match_area_t *, size_t);
diff --git a/src/analysis/scan/patterns/token.c b/src/analysis/scan/patterns/token.c
index 76a5e66..b3c6d53 100644
--- a/src/analysis/scan/patterns/token.c
+++ b/src/analysis/scan/patterns/token.c
@@ -300,6 +300,7 @@ bool g_bytes_token_build_id(GBytesToken *token, GEngineBackend *backend)
 *                                                                             *
 *  Paramètres  : token   = définition de la bribe à manipuler.                *
 *                matches = suivi des correspondances à consolider.            *
+*                params  = paramètres des opérations de validation.           *
 *                                                                             *
 *  Description : Transforme les correspondances locales en trouvailles.       *
 *                                                                             *
@@ -309,83 +310,70 @@ bool g_bytes_token_build_id(GBytesToken *token, GEngineBackend *backend)
 *                                                                             *
 ******************************************************************************/
 
-void g_bytes_token_check(const GBytesToken *token, GScanBytesMatches *matches)
+void g_bytes_token_check(const GBytesToken *token, GScanBytesMatches *matches, scan_node_check_params_t *params)
 {
-    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             */
 
-    /* Définition d'un contexte */
+    /* Réinitialisation */
 
-    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));
+    // TODO: offset
 
-    g_binary_content_compute_start_pos(params.content, &start);
-    g_binary_content_compute_end_pos(params.content, &end);
+    params->initialized = false;
 
-    params.content_start = start.physical;
-    params.content_end = end.physical;
+    params->main_areas = NULL;
+    params->main_count = 0;
 
-    // offset
+    params->created_areas = NULL;
+    params->created_count = 0;
 
-    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;
+    params->kept_areas = NULL;
+    params->kept_count = 0;
 
     /* Lancement des analyses */
 
-    g_scan_token_node_check_forward(token->root, &params);
+    g_scan_token_node_check_forward(token->root, params);
 
     if (token->need_backward)
-        g_scan_token_node_check_backward(token->root, &params);
+        g_scan_token_node_check_backward(token->root, params);
 
     // REMME ? sort_and_filter_pending_matches(matches);
 
     if (token->fullword)
     {
-        for_each_match_area_safe(area, &params.main_areas, next)
+        for_each_match_area_safe(area, &params->main_areas, next)
         {
             /* Validation de l'octet précédent, s'il existe */
-            if (area->start > params.content_start)
+            if (area->start > params->content_start)
             {
                 init_vmpa(&pos, area->start - 1, VMPA_NO_VIRTUAL);
 
-                byte = g_binary_content_get_raw_access(params.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--;
+                    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 (area->end < params.content_end)
+            if (area->end < params->content_end)
             {
                 init_vmpa(&pos, area->end, VMPA_NO_VIRTUAL);
 
-                byte = g_binary_content_get_raw_access(params.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--;
+                    del_match_area(area, &params->main_areas);
+                    assert(&params->main_count > 0);
+                    params->main_count--;
                     continue;
                 }
 
@@ -395,11 +383,7 @@ void g_bytes_token_check(const GBytesToken *token, GScanBytesMatches *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));
+    g_scan_bytes_matches_set_list(matches, params->main_areas, params->main_count);
 
 }
 
diff --git a/src/analysis/scan/patterns/token.h b/src/analysis/scan/patterns/token.h
index 3bc5cb7..f5b78f6 100644
--- a/src/analysis/scan/patterns/token.h
+++ b/src/analysis/scan/patterns/token.h
@@ -65,7 +65,7 @@ bool g_bytes_token_enroll(GBytesToken *, GEngineBackend *, size_t);
 bool g_bytes_token_build_id(GBytesToken *, GEngineBackend *);
 
 /* Transforme les correspondances locales en trouvailles. */
-void g_bytes_token_check(const GBytesToken *, GScanBytesMatches *);
+void g_bytes_token_check(const GBytesToken *, GScanBytesMatches *, scan_node_check_params_t *);
 
 /* 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/rule.c b/src/analysis/scan/rule.c
index 14a6d38..05fc657 100644
--- a/src/analysis/scan/rule.c
+++ b/src/analysis/scan/rule.c
@@ -613,17 +613,34 @@ bool g_scan_rule_define_pattern_ids(GScanRule *rule, GEngineBackend *backend)
 
 void g_scan_rule_check(GScanRule *rule, GEngineBackend *backend, GScanContext *context)
 {
+    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     */
     size_t i;                               /* Boucle de parcours          */
     GSearchPattern *pattern;                /* Motif à intégrer            */
-    GScanBytesMatches *matches;             /* Correspondances établies    */
+    GScanMatches *matches;                  /* Correspondances établies    */
+
+    /* Définition d'un contexte */
+
+    params.context = context;
+    params.content = g_scan_context_get_content(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;
+
+    /* Vérifications */
 
     for (i = 0; i < rule->bytes_used; i++)
     {
         pattern = rule->bytes_locals[i];
 
-        matches = g_scan_bytes_matches_new(pattern, context);
+        matches = g_scan_bytes_matches_new();
 
-        g_bytes_token_check(G_BYTES_TOKEN(pattern), matches);
+        g_bytes_token_check(G_BYTES_TOKEN(pattern), G_SCAN_BYTES_MATCHES(matches), &params);
 
         g_scan_context_register_full_matches(context, pattern, matches);
 
@@ -631,6 +648,9 @@ void g_scan_rule_check(GScanRule *rule, GEngineBackend *backend, GScanContext *c
 
     }
 
+    g_object_unref(G_OBJECT(params.content));
+    //g_object_unref(G_OBJECT(params.allocator));
+
 }
 
 
-- 
cgit v0.11.2-87-g4458