diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2023-08-06 16:54:57 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2023-08-06 16:54:57 (GMT) |
commit | 4fcc35a52ccb025b6d803d85e017931cd2452960 (patch) | |
tree | e95920f16c273e41f9cae1ea2f02571c221a514e /src/analysis/scan/exprs/strop.c | |
parent | 74d062d4ec55d7ac3914bbf64b8b6c5ab52227df (diff) |
Extend the ROST grammar with a first batch of new features.
Diffstat (limited to 'src/analysis/scan/exprs/strop.c')
-rw-r--r-- | src/analysis/scan/exprs/strop.c | 207 |
1 files changed, 95 insertions, 112 deletions
diff --git a/src/analysis/scan/exprs/strop.c b/src/analysis/scan/exprs/strop.c index 145e8da..c7c2878 100644 --- a/src/analysis/scan/exprs/strop.c +++ b/src/analysis/scan/exprs/strop.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * strop.c - gestion des opérations booléennes * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -38,27 +38,24 @@ /* Initialise la classe des opérations visant des chaînes. */ -static void g_string_operation_class_init(GStringOperationClass *); +static void g_scan_string_operation_class_init(GScanStringOperationClass *); /* Initialise une instance d'opération visant une chaîne. */ -static void g_string_operation_init(GStringOperation *); +static void g_scan_string_operation_init(GScanStringOperation *); /* Supprime toutes les références externes. */ -static void g_string_operation_dispose(GStringOperation *); +static void g_scan_string_operation_dispose(GScanStringOperation *); /* Procède à la libération totale de la mémoire. */ -static void g_string_operation_finalize(GStringOperation *); +static void g_scan_string_operation_finalize(GScanStringOperation *); /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ -/* Reproduit une expression en place dans une nouvelle instance. */ -static void g_string_operation_copy(GStringOperation *, const GStringOperation *); - /* Réduit une expression à une forme plus simple. */ -static bool g_string_operation_reduce(GStringOperation *, GScanContext *, GScanScope *, GScanExpression **); +static ScanReductionState g_scan_string_operation_reduce(GScanStringOperation *, GScanContext *, GScanScope *, GScanExpression **); @@ -68,7 +65,7 @@ static bool g_string_operation_reduce(GStringOperation *, GScanContext *, GScanS /* Indique le type défini pour une opération traitant une chaîne de caractères. */ -G_DEFINE_TYPE(GStringOperation, g_string_operation, G_TYPE_SCAN_EXPRESSION); +G_DEFINE_TYPE(GScanStringOperation, g_scan_string_operation, G_TYPE_SCAN_EXPRESSION); /****************************************************************************** @@ -83,21 +80,20 @@ G_DEFINE_TYPE(GStringOperation, g_string_operation, G_TYPE_SCAN_EXPRESSION); * * ******************************************************************************/ -static void g_string_operation_class_init(GStringOperationClass *klass) +static void g_scan_string_operation_class_init(GScanStringOperationClass *klass) { GObjectClass *object; /* Autre version de la classe */ GScanExpressionClass *expr; /* Version de classe parente */ object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_string_operation_dispose; - object->finalize = (GObjectFinalizeFunc)g_string_operation_finalize; + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_string_operation_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_string_operation_finalize; expr = G_SCAN_EXPRESSION_CLASS(klass); expr->cmp_rich = (compare_expr_rich_fc)NULL; - expr->copy = (copy_expr_fc)g_string_operation_copy; - expr->reduce = (reduce_expr_fc)g_string_operation_reduce; + expr->reduce = (reduce_expr_fc)g_scan_string_operation_reduce; } @@ -114,7 +110,7 @@ static void g_string_operation_class_init(GStringOperationClass *klass) * * ******************************************************************************/ -static void g_string_operation_init(GStringOperation *op) +static void g_scan_string_operation_init(GScanStringOperation *op) { op->left = NULL; op->right = NULL; @@ -134,12 +130,12 @@ static void g_string_operation_init(GStringOperation *op) * * ******************************************************************************/ -static void g_string_operation_dispose(GStringOperation *op) +static void g_scan_string_operation_dispose(GScanStringOperation *op) { g_clear_object(&op->left); g_clear_object(&op->right); - G_OBJECT_CLASS(g_string_operation_parent_class)->dispose(G_OBJECT(op)); + G_OBJECT_CLASS(g_scan_string_operation_parent_class)->dispose(G_OBJECT(op)); } @@ -156,9 +152,9 @@ static void g_string_operation_dispose(GStringOperation *op) * * ******************************************************************************/ -static void g_string_operation_finalize(GStringOperation *op) +static void g_scan_string_operation_finalize(GScanStringOperation *op) { - G_OBJECT_CLASS(g_string_operation_parent_class)->finalize(G_OBJECT(op)); + G_OBJECT_CLASS(g_scan_string_operation_parent_class)->finalize(G_OBJECT(op)); } @@ -178,13 +174,13 @@ static void g_string_operation_finalize(GStringOperation *op) * * ******************************************************************************/ -GScanExpression *g_string_operation_new(StringOperationType type, GScanExpression *first, GScanExpression *second, bool sensitive) +GScanExpression *g_scan_string_operation_new(StringOperationType type, GScanExpression *first, GScanExpression *second, bool sensitive) { GScanExpression *result; /* Structure à retourner */ - result = g_object_new(G_TYPE_STRING_OPERATION, NULL); + result = g_object_new(G_TYPE_SCAN_STRING_OPERATION, NULL); - if (!g_string_operation_create(G_STRING_OPERATION(result), type, first, second, sensitive)) + if (!g_scan_string_operation_create(G_SCAN_STRING_OPERATION(result), type, first, second, sensitive)) g_clear_object(&result); return result; @@ -198,7 +194,7 @@ GScanExpression *g_string_operation_new(StringOperationType type, GScanExpressio * type = type d'opération booléenne à représenter. * * left = premier opérande concerné. * * right = éventuel second opérande impliqué ou NULL. * -* sensitive = détermine la prise en compte de la casse. * +* sensitive = détermine la prise en compte de la casse. * * * * Description : Met en place une expression d'opération traite une chaîne. * * * @@ -208,22 +204,11 @@ GScanExpression *g_string_operation_new(StringOperationType type, GScanExpressio * * ******************************************************************************/ -bool g_string_operation_create(GStringOperation *op, StringOperationType type, GScanExpression *left, GScanExpression *right, bool sensitive) +bool g_scan_string_operation_create(GScanStringOperation *op, StringOperationType type, GScanExpression *left, GScanExpression *right, bool sensitive) { bool result; /* Bilan à retourner */ - ExprValueType vtype; /* Type de valeur portée */ - - result = false; - - vtype = g_scan_expression_get_value_type(left); - - if (vtype != EVT_STRING && vtype != EVT_PENDING) - goto exit; - - vtype = g_scan_expression_get_value_type(right); - if (vtype != EVT_STRING && vtype != EVT_REG_EXPR && vtype != EVT_PENDING) - goto exit; + result = true; op->type = type; @@ -251,10 +236,6 @@ bool g_string_operation_create(GStringOperation *op, StringOperationType type, G op->right = right; g_object_ref(G_OBJECT(op->right)); - result = true; - - exit: - return result; } @@ -268,36 +249,6 @@ bool g_string_operation_create(GStringOperation *op, StringOperationType type, G /****************************************************************************** * * -* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] * -* src = expression source à copier. * -* * -* Description : Reproduit une expression en place dans une nouvelle instance.* -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_string_operation_copy(GStringOperation *dest, const GStringOperation *src) -{ - GScanExpressionClass *class; /* Classe parente à solliciter */ - - class = G_SCAN_EXPRESSION_CLASS(g_string_operation_parent_class); - - class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src)); - - dest->type = src->type; - dest->case_sensitive = src->case_sensitive; - - dest->left = g_scan_expression_duplicate(src->left); - dest->right = g_scan_expression_duplicate(src->right); - -} - - -/****************************************************************************** -* * * Paramètres : expr = expression à consulter. * * ctx = contexte de suivi de l'analyse courante. * * scope = portée courante des variables locales. * @@ -311,47 +262,65 @@ static void g_string_operation_copy(GStringOperation *dest, const GStringOperati * * ******************************************************************************/ -static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +static ScanReductionState g_scan_string_operation_reduce(GScanStringOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - bool result; /* Bilan à retourner */ + ScanReductionState result; /* Etat synthétisé à retourner */ GScanExpression *new_left; /* Expression réduite (gauche) */ GScanExpression *new_right; /* Expression réduite (droite) */ - GLiteralExpression *op_left; /* Opérande gauche final */ - GLiteralExpression *op_right; /* Opérande droite final */ + ScanReductionState state_left; /* Etat synthétisé #1 */ + ScanReductionState state_right; /* Etat synthétisé #2 */ + GScanLiteralExpression *op_left; /* Opérande gauche final */ + GScanLiteralExpression *op_right; /* Opérande droite final */ const sized_string_t *strings[2]; /* Chaînes en jeu */ const void *found; /* Présence d'une bribe ? */ bool status; /* Bilan de comparaison #1 */ + int ret; /* Bilan de comparaison #2 */ size_t offset; /* Point de départ d'analyse */ const regex_t *preg; /* Expression rationnelle */ - int ret; /* Bilan de comparaison #2 */ /* Réduction des éléments considérés */ new_left = NULL; new_right = NULL; - result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left); - if (!result) goto exit; + state_left = g_scan_expression_reduce(expr->left, ctx, scope, &new_left); + if (state_left == SRS_UNRESOLVABLE) + { + result = SRS_UNRESOLVABLE; + goto exit; + } - result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right); - if (!result) goto exit; + state_right = g_scan_expression_reduce(expr->right, ctx, scope, &new_right); + if (state_right == SRS_UNRESOLVABLE) + { + result = SRS_UNRESOLVABLE; + goto exit; + } /* Construction d'une réduction locale ? */ - if (G_IS_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right)) + if (G_IS_SCAN_LITERAL_EXPRESSION(new_left) && G_IS_SCAN_LITERAL_EXPRESSION(new_right)) { - op_left = G_LITERAL_EXPRESSION(new_left); - op_right = G_LITERAL_EXPRESSION(new_right); + op_left = G_SCAN_LITERAL_EXPRESSION(new_left); + op_right = G_SCAN_LITERAL_EXPRESSION(new_right); + + if (!g_scan_literal_expression_get_string_value(op_left, &strings[0])) + { + result = SRS_UNRESOLVABLE; + goto exit; + } - result = g_literal_expression_get_string_value(op_left, &strings[0]); - if (!result) goto exit; + result = SRS_REDUCED; switch (expr->type) { case SOT_CONTAINS: - result = g_literal_expression_get_string_value(op_right, &strings[1]); - if (!result) goto exit; + if (!g_scan_literal_expression_get_string_value(op_right, &strings[1])) + { + result = SRS_UNRESOLVABLE; + goto exit; + } if (expr->case_sensitive) found = memmem(strings[0]->data, strings[0]->len, strings[1]->data, strings[1]->len); @@ -359,13 +328,16 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx, else found = memcasemem(strings[0]->data, strings[0]->len, strings[1]->data, strings[1]->len); - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { found != NULL }); + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { found != NULL }); break; case SOT_STARTSWITH: - result = g_literal_expression_get_string_value(op_right, &strings[1]); - if (!result) goto exit; + if (!g_scan_literal_expression_get_string_value(op_right, &strings[1])) + { + result = SRS_UNRESOLVABLE; + goto exit; + } if (strings[0]->len < strings[1]->len) status = false; @@ -381,13 +353,16 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx, } - result = g_literal_expression_new(EVT_BOOLEAN, &status); + *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status); break; case SOT_ENDSWITH: - result = g_literal_expression_get_string_value(op_right, &strings[1]); - if (!result) goto exit; + if (!g_scan_literal_expression_get_string_value(op_right, &strings[1])) + { + result = SRS_UNRESOLVABLE; + goto exit; + } if (strings[0]->len < strings[1]->len) status = false; @@ -405,23 +380,29 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx, } - result = g_literal_expression_new(EVT_BOOLEAN, &status); + *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status); break; case SOT_MATCHES: - result = g_literal_expression_get_regex_value(op_right, &preg); - if (!result) goto exit; + if (!g_scan_literal_expression_get_regex_value(op_right, &preg)) + { + result = SRS_UNRESOLVABLE; + goto exit; + } ret = regexec(preg, strings[0]->data, 0, NULL, 0); - *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret != REG_NOMATCH }); + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { ret != REG_NOMATCH }); break; case SOT_IEQUALS: - result = g_literal_expression_get_string_value(op_right, &strings[1]); - if (!result) goto exit; + if (!g_scan_literal_expression_get_string_value(op_right, &strings[1])) + { + result = SRS_UNRESOLVABLE; + goto exit; + } if (strings[0]->len != strings[1]->len) status = false; @@ -432,7 +413,7 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx, status = (ret == 0); } - result = g_literal_expression_new(EVT_BOOLEAN, &status); + *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status); break; } @@ -441,24 +422,26 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx, /* Mise à jour de la progression ? */ - else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right)) + else if (state_left == SRS_WAIT_FOR_SCAN || state_right == SRS_WAIT_FOR_SCAN) { - if (new_left == NULL) - { - new_left = expr->left; - g_object_ref(G_OBJECT(new_left)); - } + if (new_left != expr->left || new_right != expr->right) + *out = g_scan_string_operation_new(expr->type, new_left, new_right, expr->case_sensitive); - if (new_right == NULL) - { - new_right = expr->right; - g_object_ref(G_OBJECT(new_right)); - } + result = SRS_WAIT_FOR_SCAN; - *out = g_string_operation_new(expr->type, new_left, new_right, expr->case_sensitive); + } + + /* Cas des situations où les expressions ne sont pas exploitables (!) */ + else + { + assert(state_left == SRS_REDUCED && state_right == SRS_REDUCED); + + result = SRS_UNRESOLVABLE; } + /* Sortie propre */ + exit: g_clear_object(&new_left); |