diff options
Diffstat (limited to 'src/analysis/scan/patterns/tokens/nodes/plain.c')
| -rw-r--r-- | src/analysis/scan/patterns/tokens/nodes/plain.c | 244 | 
1 files changed, 209 insertions, 35 deletions
| diff --git a/src/analysis/scan/patterns/tokens/nodes/plain.c b/src/analysis/scan/patterns/tokens/nodes/plain.c index ee87c73..5a7f976 100644 --- a/src/analysis/scan/patterns/tokens/nodes/plain.c +++ b/src/analysis/scan/patterns/tokens/nodes/plain.c @@ -24,7 +24,11 @@  #include "plain.h" +#include <assert.h> + +  #include "plain-int.h" +#include "../../../../../common/extstr.h" @@ -32,7 +36,7 @@  /* Initialise la classe des noeuds pour motif textuel. */ -static void g_scan_token_node_plain_class_init(GScanTokenNodePlainClass *klass); +static void g_scan_token_node_plain_class_init(GScanTokenNodePlainClass *);  /* Initialise une instance de noeud pour motif textuel. */  static void g_scan_token_node_plain_init(GScanTokenNodePlain *); @@ -48,14 +52,20 @@ static void g_scan_token_node_plain_finalize(GScanTokenNodePlain *);  /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ +/* 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 ); +static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *, GScanContext *, GEngineBackend *, size_t, size_t *);  /* 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 *, phys_t, GBinContent *); +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_plain_bytes_check(const GScanTokenNodePlain *, GScanContext *, GBinContent *, pending_matches_t *, const node_search_offset_t *); +static void g_scan_token_node_plain_check_forward(const GScanTokenNodePlain *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, 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 *); @@ -92,8 +102,10 @@ static void g_scan_token_node_plain_class_init(GScanTokenNodePlainClass *klass)      node = G_SCAN_TOKEN_NODE_CLASS(klass); +    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->check = (check_scan_token_node_fc)g_scan_plain_bytes_check; +    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;  } @@ -112,6 +124,8 @@ 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; @@ -203,6 +217,7 @@ GScanTokenNode *g_scan_token_node_plain_new(const sized_binary_t *text, GScanTok  } +  /******************************************************************************  *                                                                             *  *  Paramètres  : plain    = encadrement de motif à initialiser pleinement.    * @@ -210,7 +225,7 @@ GScanTokenNode *g_scan_token_node_plain_new(const sized_binary_t *text, GScanTok  *                modifier = transformateur éventuel à solliciter.             *  *                flags    = particularités à prendre en considération.        *  *                                                                             * -*  Description : Met en place un un noeud représentant un motif textuel.      * +*  Description : Met en place un noeud représentant un motif textuel.         *  *                                                                             *  *  Retour      : Bilan de l'opération.                                        *  *                                                                             * @@ -239,6 +254,29 @@ bool g_scan_token_node_plain_create(GScanTokenNodePlain *plain, const sized_bina  } +/****************************************************************************** +*                                                                             * +*  Paramètres  : plain = noeud de motif textuel à consulter.                  * +*                                                                             * +*  Description : Indique les propriétés particulières d'un noeud de texte.    * +*                                                                             * +*  Retour      : Propriétés particulières associées au noeud.                 * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +ScanPlainNodeFlags g_scan_token_node_plain_get_flags(const GScanTokenNodePlain *plain) +{ +    ScanPlainNodeFlags result;              /* Statut à retourner          */ + +    result = plain->flags; + +    return result; + +} + +  /* ---------------------------------------------------------------------------------- */  /*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ @@ -247,10 +285,32 @@ bool g_scan_token_node_plain_create(GScanTokenNodePlain *plain, const sized_bina  /******************************************************************************  *                                                                             * +*  Paramètres  : node   = point de départ du parcours à effectuer.            * +*                points = points capitaux de l'arborescence. [OUT]            * +*                                                                             * +*  Description : Parcourt une arborescence de noeuds et y relève des éléments.* +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_plain_visit(GScanTokenNodePlain *node, scan_tree_points_t *points) +{ +    if (points->first_plain == NULL) +        points->first_plain = G_SCAN_TOKEN_NODE(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] *  *                                                                             *  *  Description : Inscrit la définition d'un motif dans un moteur de recherche.*  *                                                                             * @@ -260,7 +320,7 @@ bool g_scan_token_node_plain_create(GScanTokenNodePlain *plain, const sized_bina  *                                                                             *  ******************************************************************************/ -static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *node, GScanContext *context, GEngineBackend *backend, size_t maxsize) +static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *node, GScanContext *context, GEngineBackend *backend, size_t maxsize, size_t *slow)  {      bool result;                            /* Statut à retourner          */      size_t i;                               /* Boucle de parcours #1       */ @@ -312,13 +372,14 @@ static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *node, GScanConte              if (letters == 0)                  node->atoms[i] = atom; -            /* Insertion des combinaisons pour couvrir toutes les casses */ +            /* Insertion des nouvelles combinaisons pour couvrir toutes les casses */              else              { -                for (k = 0, extra_count = 1; k < letters; k++, extra_count *= 2) +                /* extra_count = 2^letters */ +                for (k = 1, extra_count = 2; k < letters; k++, extra_count *= 2)                      ; -                extra = make_atoms_case_insensitive(&node->raw[i], extra_count); +                extra = make_atoms_case_insensitive(&node->raw[i], &atom, extra_count);                  remaining = node->count - i - 1; @@ -333,7 +394,7 @@ static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *node, GScanConte                  free(extra); -                node->atoms = realloc(node->raw, node->count * sizeof(tracked_scan_atom_t)); +                node->atoms = realloc(node->atoms, node->count * sizeof(tracked_scan_atom_t));                  for (k = 0; k < extra_count; k++)                      node->atoms[i + k] = atom; @@ -365,6 +426,7 @@ static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *node, GScanConte  *                                                                             *  *  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.       *  *                start   = point d'analyse à respecter.                       *  *                content = accès au contenu brut pour vérifications (optim.)  *  *                                                                             * @@ -376,7 +438,7 @@ static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *node, GScanConte  *                                                                             *  ******************************************************************************/ -static bool check_scan_token_node_plain_content(const sized_binary_t *raw, const tracked_scan_atom_t *atom, phys_t start, GBinContent *content) +static bool check_scan_token_node_plain_content(const sized_binary_t *raw, const tracked_scan_atom_t *atom, bool nocase, phys_t start, GBinContent *content)  {      bool result;                            /* Bilan à retourner           */      vmpa2t pos;                             /* Position dans les données   */ @@ -393,7 +455,11 @@ static bool check_scan_token_node_plain_content(const sized_binary_t *raw, const      {          ptr = g_binary_content_get_raw_access(content, &pos, atom->pos); -        ret = memcmp(raw->data, ptr, atom->pos); +        if (nocase) +            ret = memcasecmp(raw->data, ptr, atom->pos); +        else +            ret = memcmp(raw->data, ptr, atom->pos); +          if (ret != 0) goto done;      } @@ -406,7 +472,11 @@ static bool check_scan_token_node_plain_content(const sized_binary_t *raw, const          ptr = g_binary_content_get_raw_access(content, &pos, atom->rem); -        ret = memcmp(raw->data + atom->pos + atom->len, ptr, atom->rem); +        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;      } @@ -427,6 +497,8 @@ static bool check_scan_token_node_plain_content(const sized_binary_t *raw, const  *                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]         *  *                                                                             *  *  Description : Transforme les correspondances locales en trouvailles.       *  *                                                                             * @@ -436,22 +508,33 @@ static bool check_scan_token_node_plain_content(const sized_binary_t *raw, const  *                                                                             *  ******************************************************************************/ -static void g_scan_plain_bytes_check(const GScanTokenNodePlain *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, const node_search_offset_t *offset) +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)  {      bool initialized;                       /* Initialisation du suivi ?   */ +    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 start;                           /* Point de départ             */ +    phys_t new_begin;                       /* Nouveau départ à tester     */      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    */ + +    if (*skip) +        return;      initialized = are_pending_matches_initialized(matches); +    nocase = (node->flags & SPNF_CASE_INSENSITIVE); + +    get_node_search_offset_ranges(offset, &ocount); +      for (i = 0; i < node->count; i++)      {          raw = &node->raw[i]; @@ -463,28 +546,34 @@ static void g_scan_plain_bytes_check(const GScanTokenNodePlain *node, GScanConte          {              for (k = 0; k < count; k++)              { -                start = found[k] - atom->pos; +                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 (offset != NULL) +                if (ocount > 0)                  { -                    if (start < offset->min || start > offset->max) +                    if (!does_node_search_offset_include_pos_forward(offset, 0, new_begin)) +                    { +                        if (not) +                            add_pending_match(matches, new_begin, raw->len); +                          continue; + +                    }                  } -                status = check_scan_token_node_plain_content(raw, atom, start, content); +                status = check_scan_token_node_plain_content(raw, atom, nocase, new_begin, content); -                if (status) +                if ((status && !not) || (!status && not))                      /**                       * Il ne peut y avoir qu'une seule séquence d'octets à un même -                     * emplacement, donc le couple (start, len) enregistré est +                     * emplacement, donc le couple (new_begin, len) enregistré est                       * unique.                       */ -                    add_pending_match(matches, start, raw->len); +                    add_pending_match(matches, new_begin, raw->len);              } @@ -494,12 +583,17 @@ static void g_scan_plain_bytes_check(const GScanTokenNodePlain *node, GScanConte          {              reset_pending_matches_ttl(matches); -            pcount = count_pending_matches(matches); +            pending_ptr = get_all_pending_matches(matches, &pcount);              for (p = 0; p < pcount; p++) +            { +                pending = (*pending_ptr) + p; + +                assert(matches->content_start <= pending->start); +                  for (k = 0; k < count; k++)                  { -                    start = found[k] - atom->pos; +                    new_begin = found[k] - atom->pos;                      /**                       * Si bornes de tolérance il y a, on valide la position. @@ -507,20 +601,52 @@ static void g_scan_plain_bytes_check(const GScanTokenNodePlain *node, GScanConte                       * Sinon les correspondances passées et actuelle doivent                       * être jointes.                       */ -                    if (offset != NULL) +                    if (ocount > 0)                      { -                        if (!has_pending_match_ending_between(matches, p, start, offset->min, offset->max)) +                        if (!does_node_search_offset_include_pos_forward(offset, pending->end, new_begin)) +                        { +                            if (not) +                            { +                                extend_pending_match_ending(matches, p, pending->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; + +                            } +                              continue; + +                        }                      }                      else                      { -                        if (!has_pending_match_ending_at(matches, p, start)) +                        if (pending->end != new_begin) +                        { +                            if (not) +                            { +                                extend_pending_match_ending(matches, p, pending->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; + +                            } +                              continue; + +                        }                      } -                    status = check_scan_token_node_plain_content(raw, atom, start, content); +                    status = check_scan_token_node_plain_content(raw, atom, nocase, new_begin, content); -                    if (status) +                    if ((status && !not) || (!status && not))                      {                          /**                           * Même si une base de couples uniques est assurée, @@ -559,18 +685,28 @@ static void g_scan_plain_bytes_check(const GScanTokenNodePlain *node, GScanConte                          /**                           * La seconde situation est prise en compte par la fonction -                         * extend_pending_match() 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. +                         * 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.                           */ -                        extend_pending_match(matches, p, start + raw->len); +                        extend_pending_match_ending(matches, p, new_begin + 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;                      }                  } +            } +              purge_pending_matches(matches);          } @@ -579,4 +715,42 @@ static void g_scan_plain_bytes_check(const GScanTokenNodePlain *node, GScanConte      set_pending_matches_initialized(matches); +    disable_all_ranges_in_node_search_offset(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]         * +*                                                                             * +*  Description : Transforme les correspondances locales en trouvailles.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +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) +{ + + + +    if (*skip) +        return; + + + +    printf("TODO\n"); +    assert(0); + + +  } | 
