From 72b6d6efcea936ac806528f3453a3107c7807131 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Wed, 8 Nov 2023 08:10:27 +0100 Subject: Make the hexadecimal range processing stronger. --- src/analysis/scan/grammar.y | 35 ++++++++- src/analysis/scan/patterns/tokens/nodes/any-int.h | 2 +- src/analysis/scan/patterns/tokens/nodes/any.c | 28 ++++++- src/analysis/scan/patterns/tokens/nodes/any.h | 3 + src/analysis/scan/patterns/tokens/nodes/sequence.c | 86 +++++++++++++++++++++- src/analysis/scan/patterns/tokens/nodes/sequence.h | 6 ++ tests/analysis/scan/fuzzing.py | 39 +++++++++- 7 files changed, 190 insertions(+), 9 deletions(-) diff --git a/src/analysis/scan/grammar.y b/src/analysis/scan/grammar.y index 84eda7a..801898f 100644 --- a/src/analysis/scan/grammar.y +++ b/src/analysis/scan/grammar.y @@ -274,6 +274,7 @@ YY_DECL; %type hex_pattern %type hex_tokens +%type _hex_tokens %type hex_token %type hex_range %type hex_choices @@ -726,14 +727,37 @@ YY_DECL; } ; - hex_tokens : hex_token + hex_tokens : _hex_tokens + { + $$ = $1; + + if (G_IS_SCAN_TOKEN_NODE_SEQUENCE($$)) + { + if (g_scan_token_node_sequence_count(G_SCAN_TOKEN_NODE_SEQUENCE($$)) == 1) + { + GScanTokenNode *node; + + node = g_scan_token_node_sequence_get(G_SCAN_TOKEN_NODE_SEQUENCE($$), 0); + + g_object_unref(G_OBJECT($$)); + + $$ = node; + + } + + } + + } + ; + + _hex_tokens : hex_token { if ($1 == NULL) YYERROR; $$ = $1; } - | hex_tokens hex_token + | _hex_tokens hex_token { if ($2 == NULL) YYERROR; @@ -793,7 +817,14 @@ YY_DECL; } | hex_range { + if ($1 == NULL) + { + raise_error(_("Unable to build hexadecimal range")); + YYERROR; + } + $$ = $1; + } | "~" hex_token { diff --git a/src/analysis/scan/patterns/tokens/nodes/any-int.h b/src/analysis/scan/patterns/tokens/nodes/any-int.h index 705aab3..dd2e2e7 100644 --- a/src/analysis/scan/patterns/tokens/nodes/any-int.h +++ b/src/analysis/scan/patterns/tokens/nodes/any-int.h @@ -52,7 +52,7 @@ struct _GScanTokenNodeAnyClass }; -/* Met en place un un noeud pointant une série d'octets. */ +/* Met en place un noeud pointant une série d'octets. */ bool g_scan_token_node_any_create(GScanTokenNodeAny *, const phys_t *, const phys_t *); diff --git a/src/analysis/scan/patterns/tokens/nodes/any.c b/src/analysis/scan/patterns/tokens/nodes/any.c index e5fb1d7..6233cb4 100644 --- a/src/analysis/scan/patterns/tokens/nodes/any.c +++ b/src/analysis/scan/patterns/tokens/nodes/any.c @@ -196,7 +196,7 @@ GScanTokenNode *g_scan_token_node_any_new(const phys_t *min, const phys_t *max) * min = éventuelle quantité minimale à retrouver. * * max = éventuelle quantité maximale à retrouver. * * * -* Description : Met en place un un noeud pointant une série d'octets. * +* Description : Met en place un noeud pointant une série d'octets. * * * * Retour : Bilan de l'opération. * * * @@ -221,6 +221,9 @@ bool g_scan_token_node_any_create(GScanTokenNodeAny *any, const phys_t *min, con result = (any->min <= any->max); + if (result && any->min == any->max) + result = (any->min > 0); + } any->has_max = (max != NULL); @@ -230,6 +233,29 @@ bool g_scan_token_node_any_create(GScanTokenNodeAny *any, const phys_t *min, con } +/****************************************************************************** +* * +* Paramètres : any = séquence d'octets quelconques à étendre. * +* extra = étendue supplémentaire à intégrer. * +* * +* Description : Etend un noeud pointant une série d'octets. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_scan_token_node_any_merge(GScanTokenNodeAny *any, GScanTokenNodeAny *extra) +{ + any->min += extra->min; + + if (any->has_max && extra->has_max) + any->max += extra->max; + +} + + /* ---------------------------------------------------------------------------------- */ /* IMPLEMENTATION DES FONCTIONS DE CLASSE */ diff --git a/src/analysis/scan/patterns/tokens/nodes/any.h b/src/analysis/scan/patterns/tokens/nodes/any.h index 6a5628a..9b2233f 100644 --- a/src/analysis/scan/patterns/tokens/nodes/any.h +++ b/src/analysis/scan/patterns/tokens/nodes/any.h @@ -53,6 +53,9 @@ GType g_scan_token_node_any_get_type(void); /* Construit un noeud pointant une série d'octets quelconques. */ GScanTokenNode *g_scan_token_node_any_new(const phys_t *, const phys_t *); +/* Etend un noeud pointant une série d'octets. */ +void g_scan_token_node_any_merge(GScanTokenNodeAny *, GScanTokenNodeAny *); + #endif /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_ANY_H */ diff --git a/src/analysis/scan/patterns/tokens/nodes/sequence.c b/src/analysis/scan/patterns/tokens/nodes/sequence.c index ad332fc..91307bf 100644 --- a/src/analysis/scan/patterns/tokens/nodes/sequence.c +++ b/src/analysis/scan/patterns/tokens/nodes/sequence.c @@ -24,6 +24,7 @@ #include "sequence.h" +#include "any.h" #include "sequence-int.h" @@ -224,7 +225,7 @@ bool g_scan_token_node_sequence_create(GScanTokenNodeSequence *sequence, GScanTo /****************************************************************************** * * * Paramètres : sequence = ensemble de noeuds à compléter. * -* child = nouveau noeud à intégrer. * +* child = nouveau noeud à intégrer. * * * * Description : Ajoute un noeud à aux décompositions séquentielles de motif. * * * @@ -236,10 +237,87 @@ bool g_scan_token_node_sequence_create(GScanTokenNodeSequence *sequence, GScanTo void g_scan_token_node_sequence_add(GScanTokenNodeSequence *sequence, GScanTokenNode *child) { - sequence->children = realloc(sequence->children, ++sequence->count * sizeof(GScanTokenNode *)); + bool processed; /* Intégration traitée ? */ + GScanTokenNode *last; /* Dernier noeud inscrit */ - sequence->children[sequence->count - 1] = child; - g_object_ref(G_OBJECT(child)); + processed = false; + + if (sequence->count > 0) + { + last = sequence->children[sequence->count - 1]; + + if (G_IS_SCAN_TOKEN_NODE_ANY(last) && G_IS_SCAN_TOKEN_NODE_ANY(child)) + { + g_scan_token_node_any_merge(G_SCAN_TOKEN_NODE_ANY(last), G_SCAN_TOKEN_NODE_ANY(child)); + processed = true; + } + + } + + if (!processed) + { + sequence->children = realloc(sequence->children, ++sequence->count * sizeof(GScanTokenNode *)); + + sequence->children[sequence->count - 1] = child; + g_object_ref(G_OBJECT(child)); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : sequence = ensemble de noeuds à consulter. * +* * +* Description : Indique le nombre de noeuds intégrés dans la séquence. * +* * +* Retour : Nombre de noeuds représentés. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_scan_token_node_sequence_count(const GScanTokenNodeSequence *sequence) +{ + size_t result; /* Quantité à retourner */ + + result = sequence->count; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : sequence = ensemble de noeuds à consulter. * +* index = indice du noeud à retourner. * +* * +* Description : Fournit un noeud donné d'une décomposition séquentielle. * +* * +* Retour : Noeud inclus dans l'ensemble ou NULL si mauvais indice. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanTokenNode *g_scan_token_node_sequence_get(const GScanTokenNodeSequence *sequence, size_t index) +{ + GScanTokenNode *result; /* Instance à retourner */ + + assert(index < sequence->count); + + if (index < sequence->count) + { + result = sequence->children[index]; + g_object_ref(G_OBJECT(result)); + } + + else + result = NULL; + + return result; } diff --git a/src/analysis/scan/patterns/tokens/nodes/sequence.h b/src/analysis/scan/patterns/tokens/nodes/sequence.h index fc181c6..12df9d1 100644 --- a/src/analysis/scan/patterns/tokens/nodes/sequence.h +++ b/src/analysis/scan/patterns/tokens/nodes/sequence.h @@ -56,6 +56,12 @@ GScanTokenNode *g_scan_token_node_sequence_new(GScanTokenNode *); /* Ajoute un noeud à aux décompositions séquentielles de motif. */ void g_scan_token_node_sequence_add(GScanTokenNodeSequence *, GScanTokenNode *); +/* Indique le nombre de noeuds intégrés dans la séquence. */ +size_t g_scan_token_node_sequence_count(const GScanTokenNodeSequence *); + +/* Fournit un noeud donné d'une décomposition séquentielle. */ +GScanTokenNode *g_scan_token_node_sequence_get(const GScanTokenNodeSequence *, size_t); + #endif /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_SEQUENCE_H */ diff --git a/tests/analysis/scan/fuzzing.py b/tests/analysis/scan/fuzzing.py index 5d99c35..1957f72 100644 --- a/tests/analysis/scan/fuzzing.py +++ b/tests/analysis/scan/fuzzing.py @@ -176,7 +176,9 @@ rule test { } ''' - self.check_rule_failure(rule) + with self.assertRaisesRegex(ValueError, 'Unable to create content scanner'): + + scanner = ContentScanner(rule) def testAllocations(self): @@ -212,3 +214,38 @@ rule test { ''' self.check_rule_success(rule, cnt) + + + def testValidHexRangeMerge(self): + """Merge valid hexadecimal ranges.""" + + rule = ''' +rule test { + + bytes: + $a = { [0] ?? } + + condition: + $a + +} +''' + + with self.assertRaisesRegex(ValueError, 'Unable to create content scanner'): + + scanner = ContentScanner(rule) + + + rule = ''' +rule test { + + bytes: + $a = { [2] ?? } + + condition: + $a + +} +''' + + self.check_rule_failure(rule) -- cgit v0.11.2-87-g4458