From fad3328dbabccc33e984f2f9a39411e959dc03e1 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 4 Mar 2024 09:11:19 +0100
Subject: Share instances to avoid extra calls to g_object_[un]ref().

---
 src/analysis/scan/exprs/handler-int.h    |  12 ++-
 src/analysis/scan/exprs/handler.c        |  87 +++++++++++++++++---
 src/analysis/scan/exprs/handler.h        |   3 +
 src/analysis/scan/exprs/setcounter-int.h |  11 ++-
 src/analysis/scan/exprs/setcounter.c     | 122 +++++++++++++++++++++++++---
 src/analysis/scan/exprs/setcounter.h     |   8 +-
 src/analysis/scan/grammar.y              | 135 ++++++++++---------------------
 src/analysis/scan/rule.c                 |  77 ++++++++++++++----
 src/analysis/scan/rule.h                 |   4 +-
 9 files changed, 324 insertions(+), 135 deletions(-)

diff --git a/src/analysis/scan/exprs/handler-int.h b/src/analysis/scan/exprs/handler-int.h
index a38dd03..e051b30 100644
--- a/src/analysis/scan/exprs/handler-int.h
+++ b/src/analysis/scan/exprs/handler-int.h
@@ -37,8 +37,13 @@ struct _GScanPatternHandler
 {
     GScanExpression parent;                 /* A laisser en premier        */
 
-    GSearchPattern **patterns;              /* Motifs associés             */
+    union
+    {
+        const GSearchPattern **patterns;    /* Motifs associés             */
+        GSearchPattern **ref_patterns;      /* Motifs associés             */
+    };
     size_t count;                           /* Nombre de ces motifs        */
+    bool shared;                            /* Définition de propriété     */
 
     ScanHandlerType type;                   /* Manipulation attendue       */
 
@@ -53,7 +58,10 @@ struct _GScanPatternHandlerClass
 
 
 /* Met en place une manipulation de correspondances établies. */
-bool g_scan_pattern_handler_create(GScanPatternHandler *, GSearchPattern ** const, size_t, ScanHandlerType);
+bool g_scan_pattern_handler_create_shared(GScanPatternHandler *, const GSearchPattern ** const, size_t, ScanHandlerType);
+
+/* Met en place une manipulation de correspondances établies. */
+bool g_scan_pattern_handler_create_and_ref(GScanPatternHandler *, GSearchPattern ** const, size_t, ScanHandlerType);
 
 
 
diff --git a/src/analysis/scan/exprs/handler.c b/src/analysis/scan/exprs/handler.c
index d40d00f..2706dae 100644
--- a/src/analysis/scan/exprs/handler.c
+++ b/src/analysis/scan/exprs/handler.c
@@ -124,6 +124,7 @@ static void g_scan_pattern_handler_init(GScanPatternHandler *handler)
 {
     handler->patterns = NULL;
     handler->count = 0;
+    handler->shared = true;
 
     handler->type = SHT_RAW;
 
@@ -146,8 +147,9 @@ static void g_scan_pattern_handler_dispose(GScanPatternHandler *handler)
 {
     size_t i;                               /* Boucle de parcours          */
 
-    for (i = 0; i < handler->count; i++)
-         g_clear_object(&handler->patterns[i]);
+    if (!handler->shared)
+        for (i = 0; i < handler->count; i++)
+            g_clear_object(&handler->ref_patterns[i]);
 
     G_OBJECT_CLASS(g_scan_pattern_handler_parent_class)->dispose(G_OBJECT(handler));
 
@@ -190,13 +192,79 @@ static void g_scan_pattern_handler_finalize(GScanPatternHandler *handler)
 *                                                                             *
 ******************************************************************************/
 
+GScanExpression *g_scan_pattern_handler_new_shared(const GSearchPattern ** const patterns, size_t count, ScanHandlerType type)
+{
+    GScanExpression *result;                /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_PATTERN_HANDLER, NULL);
+
+    if (!g_scan_pattern_handler_create_shared(G_SCAN_PATTERN_HANDLER(result), patterns, count, type))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : handler  = instance à initialiser pleinement.                *
+*                patterns = motifs à impliquer.                               *
+*                count    = quantité de ces motifs.                           *
+*                type     = type de manipulation attendue.                    *
+*                                                                             *
+*  Description : Met en place une manipulation de correspondances établies.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_pattern_handler_create_shared(GScanPatternHandler *handler, const GSearchPattern ** const patterns, size_t count, ScanHandlerType type)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = g_scan_expression_create(G_SCAN_EXPRESSION(handler), SRS_WAIT_FOR_SCAN);
+    if (!result) goto exit;
+
+    handler->patterns = malloc(count * sizeof(GSearchPattern *));
+    handler->count = count;
+
+    memcpy(handler->patterns, patterns, count * sizeof(GSearchPattern *));
+
+    handler->shared = true;
+
+    handler->type = type;
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : patterns = motifs à impliquer.                               *
+*                count    = quantité de ces motifs.                           *
+*                type     = type de manipulation attendue.                    *
+*                                                                             *
+*  Description : Met en place une manipulation de correspondances établies.   *
+*                                                                             *
+*  Retour      : Expression mise en place.                                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
 GScanExpression *g_scan_pattern_handler_new(GSearchPattern ** const patterns, size_t count, ScanHandlerType type)
 {
     GScanExpression *result;                /* Structure à retourner       */
 
     result = g_object_new(G_TYPE_SCAN_PATTERN_HANDLER, NULL);
 
-    if (!g_scan_pattern_handler_create(G_SCAN_PATTERN_HANDLER(result), patterns, count, type))
+    if (!g_scan_pattern_handler_create_and_ref(G_SCAN_PATTERN_HANDLER(result), patterns, count, type))
         g_clear_object(&result);
 
     return result;
@@ -219,7 +287,7 @@ GScanExpression *g_scan_pattern_handler_new(GSearchPattern ** const patterns, si
 *                                                                             *
 ******************************************************************************/
 
-bool g_scan_pattern_handler_create(GScanPatternHandler *handler, GSearchPattern ** const patterns, size_t count, ScanHandlerType type)
+bool g_scan_pattern_handler_create_and_ref(GScanPatternHandler *handler, GSearchPattern ** const patterns, size_t count, ScanHandlerType type)
 {
     bool result;                            /* Bilan à retourner           */
     size_t i;                               /* Boucle de parcours          */
@@ -230,11 +298,12 @@ bool g_scan_pattern_handler_create(GScanPatternHandler *handler, GSearchPattern
     handler->patterns = malloc(count * sizeof(GSearchPattern *));
     handler->count = count;
 
+    memcpy(handler->patterns, patterns, count * sizeof(GSearchPattern *));
+
     for (i = 0; i < count; i++)
-    {
-        handler->patterns[i] = patterns[i];
         g_object_ref(G_OBJECT(patterns[i]));
-    }
+
+    handler->shared = false;
 
     handler->type = type;
 
@@ -464,7 +533,7 @@ 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 */
-    GScanBytesMatches *matches;             /* Correspondances d'un motif  */
+    GScanMatches *matches;                  /* Correspondances d'un motif  */
     const match_area_t *area;               /* Zone de correspondance      */
     GBinContent *content;                   /* Contenu binaire à relire    */
     vmpa2t pos;                             /* Tête de lecture             */
@@ -495,7 +564,7 @@ static bool g_scan_pattern_handler_get_item(const GScanPatternHandler *expr, siz
     matches = g_scan_context_get_full_matches(ctx, expr->patterns[i]);
     if (matches == NULL) goto done;
 
-    area = g_scan_bytes_matches_get(matches, index);
+    area = g_scan_bytes_matches_get(G_SCAN_BYTES_MATCHES(matches), index);
     if (area == NULL) goto done_with_matches;
 
     /* Traitement adapté de la requête */
diff --git a/src/analysis/scan/exprs/handler.h b/src/analysis/scan/exprs/handler.h
index 96e9301..a1ddf98 100644
--- a/src/analysis/scan/exprs/handler.h
+++ b/src/analysis/scan/exprs/handler.h
@@ -60,6 +60,9 @@ typedef enum _ScanHandlerType
 GType g_scan_pattern_handler_get_type(void);
 
 /* Met en place une manipulation de correspondances établies. */
+GScanExpression *g_scan_pattern_handler_new_shared(const GSearchPattern ** const, size_t, ScanHandlerType);
+
+/* Met en place une manipulation de correspondances établies. */
 GScanExpression *g_scan_pattern_handler_new(GSearchPattern ** const, size_t, ScanHandlerType);
 
 /* Indique le type de manipulation de correspondances spécifié. */
diff --git a/src/analysis/scan/exprs/setcounter-int.h b/src/analysis/scan/exprs/setcounter-int.h
index fbed209..c9e3da5 100644
--- a/src/analysis/scan/exprs/setcounter-int.h
+++ b/src/analysis/scan/exprs/setcounter-int.h
@@ -37,8 +37,13 @@ struct _GScanSetMatchCounter
 {
     GScanExpression parent;                 /* A laisser en premier        */
 
-    GSearchPattern **patterns;              /* Motifs associés             */
+    union
+    {
+        const GSearchPattern **patterns;    /* Motifs associés             */
+        GSearchPattern **ref_patterns;      /* Motifs associés             */
+    };
     size_t count;                           /* Nombre de ces motifs        */
+    bool shared;                            /* Définition de propriété     */
 
     ScanSetCounterType type;                /* Type de décompte            */
     size_t number;                          /* Eventuel volume associé     */
@@ -53,9 +58,11 @@ struct _GScanSetMatchCounterClass
 };
 
 
+/* Met en place un décompte de motifs avec correspondances. */
+bool g_scan_set_match_counter_create_shared(GScanSetMatchCounter *, const GSearchPattern ** const, size_t);
 
 /* Met en place un décompte de motifs avec correspondances. */
-bool g_scan_set_match_counter_create(GScanSetMatchCounter *, GSearchPattern ** const, size_t);
+bool g_scan_set_match_counter_create_and_ref(GScanSetMatchCounter *, GSearchPattern ** const, size_t);
 
 
 
diff --git a/src/analysis/scan/exprs/setcounter.c b/src/analysis/scan/exprs/setcounter.c
index da37746..bed315e 100644
--- a/src/analysis/scan/exprs/setcounter.c
+++ b/src/analysis/scan/exprs/setcounter.c
@@ -24,6 +24,10 @@
 #include "setcounter.h"
 
 
+#include <assert.h>
+#include <string.h>
+
+
 #include "setcounter-int.h"
 #include "literal.h"
 
@@ -109,6 +113,7 @@ static void g_scan_set_match_counter_init(GScanSetMatchCounter *counter)
 {
     counter->patterns = NULL;
     counter->count = 0;
+    counter->shared = true;
 
     counter->type = SSCT_NONE;
     counter->number = 0;
@@ -132,8 +137,9 @@ static void g_scan_set_match_counter_dispose(GScanSetMatchCounter *counter)
 {
     size_t i;                               /* Boucle de parcours          */
 
-    for (i = 0; i < counter->count; i++)
-         g_clear_object(&counter->patterns[i]);
+    if (!counter->shared)
+        for (i = 0; i < counter->count; i++)
+            g_clear_object(&counter->ref_patterns[i]);
 
     G_OBJECT_CLASS(g_scan_set_match_counter_parent_class)->dispose(G_OBJECT(counter));
 
@@ -175,13 +181,75 @@ static void g_scan_set_match_counter_finalize(GScanSetMatchCounter *counter)
 *                                                                             *
 ******************************************************************************/
 
+GScanExpression *g_scan_set_match_counter_new_shared(const GSearchPattern ** const patterns, size_t count)
+{
+    GScanExpression *result;                /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_SCAN_SET_MATCH_COUNTER, NULL);
+
+    if (!g_scan_set_match_counter_create_shared(G_SCAN_SET_MATCH_COUNTER(result), patterns, count))
+        g_clear_object(&result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : counter  = instance à initialiser pleinement.                *
+*                patterns = motifs à impliquer.                               *
+*                count    = quantité de ces motifs.                           *
+*                                                                             *
+*  Description : Met en place un décompte de motifs avec correspondances.     *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_scan_set_match_counter_create_shared(GScanSetMatchCounter *counter, const GSearchPattern ** const patterns, size_t count)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = g_scan_expression_create(G_SCAN_EXPRESSION(counter), SRS_WAIT_FOR_SCAN);
+    if (!result) goto exit;
+
+    counter->patterns = malloc(count * sizeof(GSearchPattern *));
+    counter->count = count;
+
+    memcpy(counter->patterns, patterns, count * sizeof(GSearchPattern *));
+
+    counter->shared = true;
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : patterns = motifs à impliquer.                               *
+*                count    = quantité de ces motifs.                           *
+*                                                                             *
+*  Description : Constitue un décompte de motifs avec correspondances.        *
+*                                                                             *
+*  Retour      : Expression mise en place.                                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
 GScanExpression *g_scan_set_match_counter_new(GSearchPattern ** const patterns, size_t count)
 {
     GScanExpression *result;                /* Structure à retourner       */
 
     result = g_object_new(G_TYPE_SCAN_SET_MATCH_COUNTER, NULL);
 
-    if (!g_scan_set_match_counter_create(G_SCAN_SET_MATCH_COUNTER(result), patterns, count))
+    if (!g_scan_set_match_counter_create_and_ref(G_SCAN_SET_MATCH_COUNTER(result), patterns, count))
         g_clear_object(&result);
 
     return result;
@@ -203,7 +271,7 @@ GScanExpression *g_scan_set_match_counter_new(GSearchPattern ** const patterns,
 *                                                                             *
 ******************************************************************************/
 
-bool g_scan_set_match_counter_create(GScanSetMatchCounter *counter, GSearchPattern ** const patterns, size_t count)
+bool g_scan_set_match_counter_create_and_ref(GScanSetMatchCounter *counter, GSearchPattern ** const patterns, size_t count)
 {
     bool result;                            /* Bilan à retourner           */
     size_t i;                               /* Boucle de parcours          */
@@ -214,11 +282,12 @@ bool g_scan_set_match_counter_create(GScanSetMatchCounter *counter, GSearchPatte
     counter->patterns = malloc(count * sizeof(GSearchPattern *));
     counter->count = count;
 
+    memcpy(counter->patterns, patterns, count * sizeof(GSearchPattern *));
+
     for (i = 0; i < count; i++)
-    {
-        counter->patterns[i] = patterns[i];
         g_object_ref(G_OBJECT(patterns[i]));
-    }
+
+    counter->shared = false;
 
  exit:
 
@@ -241,21 +310,52 @@ bool g_scan_set_match_counter_create(GScanSetMatchCounter *counter, GSearchPatte
 *                                                                             *
 ******************************************************************************/
 
-void g_scan_set_match_counter_add_extra_patterns(GScanSetMatchCounter *counter, GSearchPattern ** const patterns, size_t count)
+void g_scan_set_match_counter_add_extra_shared_patterns(GScanSetMatchCounter *counter, const GSearchPattern ** const patterns, size_t count)
+{
+    size_t first;                           /* Premier emplacement libre   */
+
+    assert(counter->shared);
+
+    first = counter->count;
+
+    counter->count += count;
+    counter->patterns = realloc(counter->patterns, counter->count * sizeof(GSearchPattern *));
+
+    memcpy(counter->patterns + first, patterns, count * sizeof(GSearchPattern *));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : counter  = décompte à compléter.                             *
+*                patterns = motifs à impliquer.                               *
+*                count    = quantité de ces motifs.                           *
+*                                                                             *
+*  Description : Ajoute de nouveaux motifs à un ensemble à décompter.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_scan_set_match_counter_add_and_ref_extra_patterns(GScanSetMatchCounter *counter, GSearchPattern ** const patterns, size_t count)
 {
     size_t first;                           /* Premier emplacement libre   */
     size_t i;                               /* Boucle de parcours          */
 
+    assert(!counter->shared);
+
     first = counter->count;
 
     counter->count += count;
     counter->patterns = realloc(counter->patterns, counter->count * sizeof(GSearchPattern *));
 
+    memcpy(counter->patterns + first, patterns, count * sizeof(GSearchPattern *));
+
     for (i = 0; i < count; i++)
-    {
-        counter->patterns[first + i] = patterns[i];
         g_object_ref(G_OBJECT(patterns[i]));
-    }
 
 }
 
diff --git a/src/analysis/scan/exprs/setcounter.h b/src/analysis/scan/exprs/setcounter.h
index 59762f9..28c92b4 100644
--- a/src/analysis/scan/exprs/setcounter.h
+++ b/src/analysis/scan/exprs/setcounter.h
@@ -52,10 +52,16 @@ typedef struct _GScanSetMatchCounterClass GScanSetMatchCounterClass;
 GType g_scan_set_match_counter_get_type(void);
 
 /* Met en place un décompte de correspondances obtenues. */
+GScanExpression *g_scan_set_match_counter_new_shared(const GSearchPattern ** const, size_t);
+
+/* Met en place un décompte de correspondances obtenues. */
 GScanExpression *g_scan_set_match_counter_new(GSearchPattern ** const, size_t);
 
 /* Ajoute de nouveaux motifs à un ensemble à décompter. */
-void g_scan_set_match_counter_add_extra_patterns(GScanSetMatchCounter *, GSearchPattern ** const, size_t);
+void g_scan_set_match_counter_add_extra_shared_patterns(GScanSetMatchCounter *, const GSearchPattern ** const, size_t);
+
+/* Ajoute de nouveaux motifs à un ensemble à décompter. */
+void g_scan_set_match_counter_add_and_ref_extra_patterns(GScanSetMatchCounter *, GSearchPattern ** const, size_t);
 
 /* Formes de volume de correspondances */
 typedef enum _ScanSetCounterType
diff --git a/src/analysis/scan/grammar.y b/src/analysis/scan/grammar.y
index 8298855..2d985a7 100644
--- a/src/analysis/scan/grammar.y
+++ b/src/analysis/scan/grammar.y
@@ -1356,15 +1356,17 @@ relational_expr : cexpression "<" cexpression
        pattern_set : "them"
                    {
                        size_t __count;
-                       GSearchPattern **__patterns;
-                       size_t __i;
+                       const GSearchPattern **__patterns;
 
                        __patterns = g_scan_rule_get_local_variables(*built_rule, NULL, &__count);
 
-                       $$ = g_scan_set_match_counter_new(__patterns, __count);
+                       if (__patterns == NULL)
+                       {
+                           raise_error(_("No pattern found for \"them\""));
+                           YYERROR;
+                       }
 
-                       for (__i = 0; __i < __count; __i++)
-                           g_object_unref(G_OBJECT(__patterns[__i]));
+                       $$ = g_scan_set_match_counter_new_shared(__patterns, __count);
 
                        free(__patterns);
 
@@ -1377,7 +1379,7 @@ relational_expr : cexpression "<" cexpression
 
  pattern_set_items : BYTES_ID
                    {
-                       GSearchPattern *__pat;
+                       const GSearchPattern *__pat;
 
                        __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
 
@@ -1397,20 +1399,17 @@ relational_expr : cexpression "<" cexpression
                            YYERROR;
                        }
 
-                       $$ = g_scan_set_match_counter_new((GSearchPattern *[]) { __pat }, 1);
-
-                       g_object_unref(G_OBJECT(__pat));
+                       $$ = g_scan_set_match_counter_new_shared((const GSearchPattern *[]) { __pat }, 1);
 
                    }
                    | BYTES_FUZZY_ID
                    {
                        size_t __count;
-                       GSearchPattern **__patterns;
-                       size_t __i;
+                       const GSearchPattern **__patterns;
 
                        __patterns = g_scan_rule_get_local_variables(*built_rule, $1.data, &__count);
 
-                       if (__count == 0)
+                       if (__patterns == NULL)
                        {
                            char *_msg;
                            int _ret;
@@ -1426,17 +1425,14 @@ relational_expr : cexpression "<" cexpression
                            YYERROR;
                        }
 
-                       $$ = g_scan_set_match_counter_new(__patterns, __count);
-
-                       for (__i = 0; __i < __count; __i++)
-                           g_object_unref(G_OBJECT(__patterns[__i]));
+                       $$ = g_scan_set_match_counter_new_shared(__patterns, __count);
 
                        free(__patterns);
 
                    }
                    | pattern_set_items "," BYTES_ID
                    {
-                       GSearchPattern *__pat;
+                       const GSearchPattern *__pat;
                        GScanSetMatchCounter *__counter;
 
                        __pat = g_scan_rule_get_local_variable(*built_rule, $3.data);
@@ -1458,9 +1454,8 @@ relational_expr : cexpression "<" cexpression
                        }
 
                        __counter = G_SCAN_SET_MATCH_COUNTER($1);
-                       g_scan_set_match_counter_add_extra_patterns(__counter, (GSearchPattern *[]) { __pat }, 1);
-
-                       g_object_unref(G_OBJECT(__pat));
+                       g_scan_set_match_counter_add_extra_shared_patterns(__counter,
+                                                                          (const GSearchPattern *[]) { __pat }, 1);
 
                        $$ = $1;
 
@@ -1468,13 +1463,12 @@ relational_expr : cexpression "<" cexpression
                    | pattern_set_items "," BYTES_FUZZY_ID
                    {
                        size_t __count;
-                       GSearchPattern **__patterns;
+                       const GSearchPattern **__patterns;
                        GScanSetMatchCounter *__counter;
-                       size_t __i;
 
                        __patterns = g_scan_rule_get_local_variables(*built_rule, $3.data, &__count);
 
-                       if (__count == 0)
+                       if (__patterns == NULL)
                        {
                            char *_msg;
                            int _ret;
@@ -1491,10 +1485,7 @@ relational_expr : cexpression "<" cexpression
                        }
 
                        __counter = G_SCAN_SET_MATCH_COUNTER($1);
-                       g_scan_set_match_counter_add_extra_patterns(__counter, __patterns, __count);
-
-                       for (__i = 0; __i < __count; __i++)
-                           g_object_unref(G_OBJECT(__patterns[__i]));
+                       g_scan_set_match_counter_add_extra_shared_patterns(__counter, __patterns, __count);
 
                        free(__patterns);
 
@@ -1567,7 +1558,7 @@ relational_expr : cexpression "<" cexpression
 
   _pattern_handler : BYTES_ID
                    {
-                       GSearchPattern *__pat;
+                       const GSearchPattern *__pat;
 
                        __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
 
@@ -1587,22 +1578,17 @@ relational_expr : cexpression "<" cexpression
                            YYERROR;
                        }
 
-                       else
-                       {
-                           $$ = g_scan_pattern_handler_new((GSearchPattern *[]) { __pat }, 1, SHT_RAW);
-                           g_object_unref(G_OBJECT(__pat));
-                       }
+                       $$ = g_scan_pattern_handler_new_shared((const GSearchPattern *[]) { __pat }, 1, SHT_RAW);
 
                    }
                    | BYTES_FUZZY_ID
                    {
                        size_t __count;
-                       GSearchPattern **__patterns;
-                       size_t __i;
+                       const GSearchPattern **__patterns;
 
                        __patterns = g_scan_rule_get_local_variables(*built_rule, $1.data, &__count);
 
-                       if (__count == 0)
+                       if (__patterns == NULL)
                        {
                            char *_msg;
                            int _ret;
@@ -1618,17 +1604,14 @@ relational_expr : cexpression "<" cexpression
                            YYERROR;
                        }
 
-                       $$ = g_scan_pattern_handler_new(__patterns, __count, SHT_RAW);
-
-                       for (__i = 0; __i < __count; __i++)
-                           g_object_unref(G_OBJECT(__patterns[__i]));
+                       $$ = g_scan_pattern_handler_new_shared(__patterns, __count, SHT_RAW);
 
                        free(__patterns);
 
                    }
                    | BYTES_ID_COUNTER
                    {
-                       GSearchPattern *__pat;
+                       const GSearchPattern *__pat;
 
                        __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
 
@@ -1648,22 +1631,17 @@ relational_expr : cexpression "<" cexpression
                            YYERROR;
                        }
 
-                       else
-                       {
-                           $$ = g_scan_pattern_handler_new((GSearchPattern *[]) { __pat }, 1, SHT_COUNTER);
-                           g_object_unref(G_OBJECT(__pat));
-                       }
+                       $$ = g_scan_pattern_handler_new_shared((const GSearchPattern *[]) { __pat }, 1, SHT_COUNTER);
 
                    }
                    | BYTES_FUZZY_ID_COUNTER
                    {
                        size_t __count;
-                       GSearchPattern **__patterns;
-                       size_t __i;
+                       const GSearchPattern **__patterns;
 
                        __patterns = g_scan_rule_get_local_variables(*built_rule, $1.data, &__count);
 
-                       if (__count == 0)
+                       if (__patterns == NULL)
                        {
                            char *_msg;
                            int _ret;
@@ -1679,17 +1657,14 @@ relational_expr : cexpression "<" cexpression
                            YYERROR;
                        }
 
-                       $$ = g_scan_pattern_handler_new(__patterns, __count, SHT_COUNTER);
-
-                       for (__i = 0; __i < __count; __i++)
-                           g_object_unref(G_OBJECT(__patterns[__i]));
+                       $$ = g_scan_pattern_handler_new_shared(__patterns, __count, SHT_COUNTER);
 
                        free(__patterns);
 
                    }
                    | BYTES_ID_START
                    {
-                       GSearchPattern *__pat;
+                       const GSearchPattern *__pat;
 
                        __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
 
@@ -1709,22 +1684,17 @@ relational_expr : cexpression "<" cexpression
                            YYERROR;
                        }
 
-                       else
-                       {
-                           $$ = g_scan_pattern_handler_new((GSearchPattern *[]) { __pat }, 1, SHT_START);
-                           g_object_unref(G_OBJECT(__pat));
-                       }
+                       $$ = g_scan_pattern_handler_new_shared((const GSearchPattern *[]) { __pat }, 1, SHT_START);
 
                    }
                    | BYTES_FUZZY_ID_START
                    {
                        size_t __count;
-                       GSearchPattern **__patterns;
-                       size_t __i;
+                       const GSearchPattern **__patterns;
 
                        __patterns = g_scan_rule_get_local_variables(*built_rule, $1.data, &__count);
 
-                       if (__count == 0)
+                       if (__patterns == NULL)
                        {
                            char *_msg;
                            int _ret;
@@ -1740,17 +1710,14 @@ relational_expr : cexpression "<" cexpression
                            YYERROR;
                        }
 
-                       $$ = g_scan_pattern_handler_new(__patterns, __count, SHT_START);
-
-                       for (__i = 0; __i < __count; __i++)
-                           g_object_unref(G_OBJECT(__patterns[__i]));
+                       $$ = g_scan_pattern_handler_new_shared(__patterns, __count, SHT_START);
 
                        free(__patterns);
 
                    }
                    | BYTES_ID_LENGTH
                    {
-                       GSearchPattern *__pat;
+                       const GSearchPattern *__pat;
 
                        __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
 
@@ -1770,22 +1737,17 @@ relational_expr : cexpression "<" cexpression
                            YYERROR;
                        }
 
-                       else
-                       {
-                           $$ = g_scan_pattern_handler_new((GSearchPattern *[]) { __pat }, 1, SHT_LENGTH);
-                           g_object_unref(G_OBJECT(__pat));
-                       }
+                       $$ = g_scan_pattern_handler_new_shared((const GSearchPattern *[]) { __pat }, 1, SHT_LENGTH);
 
                    }
                    | BYTES_FUZZY_ID_LENGTH
                    {
                        size_t __count;
-                       GSearchPattern **__patterns;
-                       size_t __i;
+                       const GSearchPattern **__patterns;
 
                        __patterns = g_scan_rule_get_local_variables(*built_rule, $1.data, &__count);
 
-                       if (__count == 0)
+                       if (__patterns == NULL)
                        {
                            char *_msg;
                            int _ret;
@@ -1801,17 +1763,14 @@ relational_expr : cexpression "<" cexpression
                            YYERROR;
                        }
 
-                       $$ = g_scan_pattern_handler_new(__patterns, __count, SHT_LENGTH);
-
-                       for (__i = 0; __i < __count; __i++)
-                           g_object_unref(G_OBJECT(__patterns[__i]));
+                       $$ = g_scan_pattern_handler_new_shared(__patterns, __count, SHT_LENGTH);
 
                        free(__patterns);
 
                    }
                    | BYTES_ID_END
                    {
-                       GSearchPattern *__pat;
+                       const GSearchPattern *__pat;
 
                        __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
 
@@ -1831,22 +1790,17 @@ relational_expr : cexpression "<" cexpression
                            YYERROR;
                        }
 
-                       else
-                       {
-                           $$ = g_scan_pattern_handler_new((GSearchPattern *[]) { __pat }, 1, SHT_END);
-                           g_object_unref(G_OBJECT(__pat));
-                       }
+                       $$ = g_scan_pattern_handler_new_shared((const GSearchPattern *[]) { __pat }, 1, SHT_END);
 
                    }
                    | BYTES_FUZZY_ID_END
                    {
                        size_t __count;
-                       GSearchPattern **__patterns;
-                       size_t __i;
+                       const GSearchPattern **__patterns;
 
                        __patterns = g_scan_rule_get_local_variables(*built_rule, $1.data, &__count);
 
-                       if (__count == 0)
+                       if (__patterns == NULL)
                        {
                            char *_msg;
                            int _ret;
@@ -1862,10 +1816,7 @@ relational_expr : cexpression "<" cexpression
                            YYERROR;
                        }
 
-                       $$ = g_scan_pattern_handler_new(__patterns, __count, SHT_END);
-
-                       for (__i = 0; __i < __count; __i++)
-                           g_object_unref(G_OBJECT(__patterns[__i]));
+                       $$ = g_scan_pattern_handler_new_shared(__patterns, __count, SHT_END);
 
                        free(__patterns);
 
diff --git a/src/analysis/scan/rule.c b/src/analysis/scan/rule.c
index 05fc657..d3acbc2 100644
--- a/src/analysis/scan/rule.c
+++ b/src/analysis/scan/rule.c
@@ -370,13 +370,13 @@ void g_scan_rule_add_local_variable(GScanRule *rule, GSearchPattern *pattern)
 *                                                                             *
 *  Retour      : Motif de détection retrouvé ou NULL en cas d'échec.          *
 *                                                                             *
-*  Remarques   : -                                                            *
+*  Remarques   : La propriétée de l'instance renvoyée est partagée !          *
 *                                                                             *
 ******************************************************************************/
 
-GSearchPattern *g_scan_rule_get_local_variable(GScanRule *rule, const char *target)
+const GSearchPattern *g_scan_rule_get_local_variable(GScanRule *rule, const char *target)
 {
-    GSearchPattern *result;                 /* Variable à retourner        */
+    const GSearchPattern *result;           /* Variable à retourner        */
     size_t i;                               /* Boucle de parcours          */
     const char *name;                       /* Désignation d'un motif      */
 
@@ -394,9 +394,6 @@ GSearchPattern *g_scan_rule_get_local_variable(GScanRule *rule, const char *targ
 
     }
 
-    if (result != NULL)
-        g_object_ref(G_OBJECT(result));
-
     return result;
 
 }
@@ -412,13 +409,16 @@ GSearchPattern *g_scan_rule_get_local_variable(GScanRule *rule, const char *targ
 *                                                                             *
 *  Retour      : Motifs de détection retrouvés ou NULL en cas d'échec.        *
 *                                                                             *
-*  Remarques   : -                                                            *
+*  Remarques   : La propriétée des instances renvoyées est partagée !         *
 *                                                                             *
 ******************************************************************************/
 
-GSearchPattern **g_scan_rule_get_local_variables(GScanRule *rule, const char *target, size_t *count)
+const GSearchPattern **g_scan_rule_get_local_variables(GScanRule *rule, const char *target, size_t *count)
 {
-    GSearchPattern **result;                /* Variables à retourner       */
+    const GSearchPattern **result;          /* Variables à retourner       */
+    size_t target_len;                      /* Nbre de caractères à évaluer*/
+    size_t len_without_star;                /* Taille sans masque          */
+    bool need_regex;                        /* Traitement complexe requis  */
     size_t i;                               /* Boucle de parcours          */
     char *regex;                            /* Définition complète         */
     regex_t preg;                           /* Expression compilée         */
@@ -433,20 +433,68 @@ GSearchPattern **g_scan_rule_get_local_variables(GScanRule *rule, const char *ta
 
     if (target == NULL)
     {
+ need_all_of_them:
+
         *count = rule->bytes_used;
         result = malloc(*count * sizeof(GSearchPattern *));
 
+        memcpy(result, rule->bytes_locals, *count);
+
+    }
+
+    /* Second cas de figure : identification au cas par cas */
+
+    else
+    {
+        target_len = strlen(target);
+
+        len_without_star = 0;
+
+        need_regex = false;
+
+        for (i = 0; i < target_len; i++)
+            if (target[i] == '*')
+                break;
+            else
+                len_without_star++;
+
+        for (i++; i < target_len; i++)
+            if (target[i] != '*')
+            {
+                need_regex = true;
+                goto try_harder;
+            }
+
+        if (len_without_star == 0)
+            goto need_all_of_them;
+
+        result = malloc(rule->bytes_used * sizeof(GSearchPattern *));
+
         for (i = 0; i < rule->bytes_used; i++)
         {
-            result[i] = rule->bytes_locals[i];
-            g_object_ref(G_OBJECT(result[i]));
+            name = g_search_pattern_get_name(rule->bytes_locals[i]);
+
+            if (strncmp(name, target, len_without_star) == 0)
+            {
+                result[*count] = rule->bytes_locals[i];
+                (*count)++;
+            }
+
+        }
+
+        if (*count == 0)
+        {
+            free(result);
+            result = NULL;
         }
 
     }
 
-    /* Second cas de figure : une expression régulière est vraisemblablement de mise */
+ try_harder:
 
-    else
+    /* Dernier cas de figure : une expression régulière est vraisemblablement de mise */
+
+    if (need_regex)
     {
         regex = strdup(target);
 
@@ -473,10 +521,7 @@ GSearchPattern **g_scan_rule_get_local_variables(GScanRule *rule, const char *ta
             if (ret != REG_NOMATCH)
             {
                 result[*count] = rule->bytes_locals[i];
-                g_object_ref(G_OBJECT(result[*count]));
-
                 (*count)++;
-
             }
 
         }
diff --git a/src/analysis/scan/rule.h b/src/analysis/scan/rule.h
index ea38655..c2c58dc 100644
--- a/src/analysis/scan/rule.h
+++ b/src/analysis/scan/rule.h
@@ -85,10 +85,10 @@ const char * const *g_scan_rule_list_tags(const GScanRule *, size_t *);
 void g_scan_rule_add_local_variable(GScanRule *, GSearchPattern *);
 
 /* Fournit une variable locale à une règle selon un nom. */
-GSearchPattern *g_scan_rule_get_local_variable(GScanRule *, const char *);
+const GSearchPattern *g_scan_rule_get_local_variable(GScanRule *, const char *);
 
 /*  Fournit une liste de variables locales à partir d'un nom. */
-GSearchPattern **g_scan_rule_get_local_variables(GScanRule *, const char *, size_t *);
+const GSearchPattern **g_scan_rule_get_local_variables(GScanRule *, const char *, size_t *);
 
 /* Définit l'expression d'une correspondance recherchée. */
 void g_scan_rule_set_match_condition(GScanRule *, GScanExpression *);
-- 
cgit v0.11.2-87-g4458