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); + + + } |