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/literal.c | |
parent | 74d062d4ec55d7ac3914bbf64b8b6c5ab52227df (diff) |
Extend the ROST grammar with a first batch of new features.
Diffstat (limited to 'src/analysis/scan/exprs/literal.c')
-rw-r--r-- | src/analysis/scan/exprs/literal.c | 363 |
1 files changed, 216 insertions, 147 deletions
diff --git a/src/analysis/scan/exprs/literal.c b/src/analysis/scan/exprs/literal.c index 119b871..e468382 100644 --- a/src/analysis/scan/exprs/literal.c +++ b/src/analysis/scan/exprs/literal.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * literal.c - représentation d'une valeur concrète * - * Copyright (C) 2022 Cyrille Bagard + * Copyright (C) 2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -37,16 +37,16 @@ /* Initialise la classe des expressions de valeur concrète. */ -static void g_literal_expression_class_init(GLiteralExpressionClass *); +static void g_scan_literal_expression_class_init(GScanLiteralExpressionClass *); /* Initialise une instance d'expression de valeur concrète. */ -static void g_literal_expression_init(GLiteralExpression *); +static void g_scan_literal_expression_init(GScanLiteralExpression *); /* Supprime toutes les références externes. */ -static void g_literal_expression_dispose(GLiteralExpression *); +static void g_scan_literal_expression_dispose(GScanLiteralExpression *); /* Procède à la libération totale de la mémoire. */ -static void g_literal_expression_finalize(GLiteralExpression *); +static void g_scan_literal_expression_finalize(GScanLiteralExpression *); @@ -54,13 +54,13 @@ static void g_literal_expression_finalize(GLiteralExpression *); /* Réalise une comparaison entre objets selon un critère précis. */ -static bool g_literal_expression_compare_rich(const GLiteralExpression *, const GLiteralExpression *, RichCmpOperation, bool *); +static bool g_scan_literal_expression_compare_rich(const GScanLiteralExpression *, const GScanLiteralExpression *, RichCmpOperation, bool *); -/* Reproduit une expression en place dans une nouvelle instance. */ -static void g_literal_expression_copy(GLiteralExpression *, const GLiteralExpression *); +/* Réduit une expression à une forme booléenne. */ +static bool g_scan_literal_expression_reduce_to_boolean(GScanLiteralExpression *, GScanContext *, GScanScope *, GScanExpression **); -/* Réduit une expression à une forme plus simple. */ -static bool g_literal_expression_reduce(GLiteralExpression *, GScanContext *, GScanScope *, GScanExpression **); +/* Dénombre les éléments portés par une expression. */ +static bool g_scan_literal_expression_count(const GScanLiteralExpression *, size_t *); @@ -70,7 +70,7 @@ static bool g_literal_expression_reduce(GLiteralExpression *, GScanContext *, GS /* Indique le type défini pour un appel de fonction enregistrée. */ -G_DEFINE_TYPE(GLiteralExpression, g_literal_expression, G_TYPE_SCAN_EXPRESSION); +G_DEFINE_TYPE(GScanLiteralExpression, g_scan_literal_expression, G_TYPE_SCAN_EXPRESSION); /****************************************************************************** @@ -85,21 +85,21 @@ G_DEFINE_TYPE(GLiteralExpression, g_literal_expression, G_TYPE_SCAN_EXPRESSION); * * ******************************************************************************/ -static void g_literal_expression_class_init(GLiteralExpressionClass *klass) +static void g_scan_literal_expression_class_init(GScanLiteralExpressionClass *klass) { GObjectClass *object; /* Autre version de la classe */ GScanExpressionClass *expr; /* Version de classe parente */ object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_literal_expression_dispose; - object->finalize = (GObjectFinalizeFunc)g_literal_expression_finalize; + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_literal_expression_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_literal_expression_finalize; expr = G_SCAN_EXPRESSION_CLASS(klass); - expr->cmp_rich = (compare_expr_rich_fc)g_literal_expression_compare_rich; - expr->copy = (copy_expr_fc)g_literal_expression_copy; - expr->reduce = (reduce_expr_fc)g_literal_expression_reduce; + expr->cmp_rich = (compare_expr_rich_fc)g_scan_literal_expression_compare_rich; + expr->reduce_to_bool = (reduce_expr_to_bool_fc)g_scan_literal_expression_reduce_to_boolean; + expr->count = (count_scan_expr_fc)g_scan_literal_expression_count; } @@ -116,8 +116,9 @@ static void g_literal_expression_class_init(GLiteralExpressionClass *klass) * * ******************************************************************************/ -static void g_literal_expression_init(GLiteralExpression *expr) +static void g_scan_literal_expression_init(GScanLiteralExpression *expr) { + G_SCAN_EXPRESSION(expr)->state = SRS_REDUCED; } @@ -134,9 +135,9 @@ static void g_literal_expression_init(GLiteralExpression *expr) * * ******************************************************************************/ -static void g_literal_expression_dispose(GLiteralExpression *expr) +static void g_scan_literal_expression_dispose(GScanLiteralExpression *expr) { - G_OBJECT_CLASS(g_literal_expression_parent_class)->dispose(G_OBJECT(expr)); + G_OBJECT_CLASS(g_scan_literal_expression_parent_class)->dispose(G_OBJECT(expr)); } @@ -153,9 +154,9 @@ static void g_literal_expression_dispose(GLiteralExpression *expr) * * ******************************************************************************/ -static void g_literal_expression_finalize(GLiteralExpression *expr) +static void g_scan_literal_expression_finalize(GScanLiteralExpression *expr) { - G_OBJECT_CLASS(g_literal_expression_parent_class)->finalize(G_OBJECT(expr)); + G_OBJECT_CLASS(g_scan_literal_expression_parent_class)->finalize(G_OBJECT(expr)); } @@ -167,25 +168,25 @@ static void g_literal_expression_finalize(GLiteralExpression *expr) * * * Description : Organise un appel de fonction avec ses arguments. * * * -* Retour : Fonction mise en place. * +* Retour : Expression mise en place. * * * * Remarques : - * * * ******************************************************************************/ -GScanExpression *g_literal_expression_new(ExprValueType vtype, ...) +GScanExpression *g_scan_literal_expression_new(LiteralValueType vtype, ...) { GScanExpression *result; /* Structure à retourner */ va_list ap; /* Liste d'arguements */ void *ptr; /* Vision générique de valeur */ - result = g_object_new(G_TYPE_LITERAL_EXPRESSION, NULL); + result = g_object_new(G_TYPE_SCAN_LITERAL_EXPRESSION, NULL); va_start(ap, vtype); ptr = va_arg(ap, void *); - if (!g_literal_expression_create(G_LITERAL_EXPRESSION(result), vtype, ptr)) + if (!g_scan_literal_expression_create(G_SCAN_LITERAL_EXPRESSION(result), vtype, ptr)) g_clear_object(&result); va_end(ap); @@ -209,12 +210,13 @@ GScanExpression *g_literal_expression_new(ExprValueType vtype, ...) * * ******************************************************************************/ -bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype, ...) +bool g_scan_literal_expression_create(GScanLiteralExpression *expr, LiteralValueType vtype, ...) { bool result; /* Bilan à retourner */ va_list ap; /* Liste d'arguements */ const bool *boolean; /* Valeur booléenne */ - const unsigned long long *integer; /* Valeur entière 64 bits */ + const long long *s_integer; /* Valeur entière 64 bits #1 */ + const unsigned long long *u_integer; /* Valeur entière 64 bits #2 */ const sized_string_t *string; /* Chaîne de caractères */ const char *raw; /* Chaîne de caractères brute */ size_t len; /* Taille de la chaîne */ @@ -223,89 +225,115 @@ bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype, char *tmp; /* Zone de travail temporaire */ int ret; /* Bilan d'une opération */ - result = g_scan_expression_create(G_SCAN_EXPRESSION(expr), vtype); + va_start(ap, vtype); - if (result) + switch (vtype) { - va_start(ap, vtype); + case LVT_BOOLEAN: + boolean = va_arg(ap, const bool *); + expr->value.boolean = *boolean; + result = true; + break; - switch (vtype) - { - case EVT_BOOLEAN: - boolean = va_arg(ap, const bool *); - expr->value.boolean = *boolean; - break; + case LVT_SIGNED_INTEGER: + s_integer = va_arg(ap, const long long *); + expr->value.s_integer = *s_integer; + result = true; + break; - case EVT_INTEGER: - integer = va_arg(ap, const unsigned long long *); - expr->value.integer = *integer; - break; + case LVT_UNSIGNED_INTEGER: + u_integer = va_arg(ap, const unsigned long long *); + expr->value.u_integer = *u_integer; + result = true; + break; + + case LVT_STRING: + string = va_arg(ap, const sized_string_t *); + szstrdup(&expr->value.string, string); + result = true; + break; - case EVT_STRING: - string = va_arg(ap, const sized_string_t *); - szstrdup(&expr->value.string, string); - break; + case LVT_REG_EXPR: + raw = va_arg(ap, const char *); + len = strlen(raw); - case EVT_REG_EXPR: - raw = va_arg(ap, const char *); - len = strlen(raw); + result = (len > 2 && raw[0] == '/'); - result = (len > 2 && raw[0] == '/'); + cflags = REG_EXTENDED | REG_NOSUB; - cflags = REG_EXTENDED | REG_NOSUB; + for (i = 0; i < 2 && result; i++) + { + result = (len > 2); - for (i = 0; i < 2 && result; i++) + if (raw[len - 1] == 'i') { - result = (len > 2); + cflags |= REG_ICASE; + len -= 1; + } - if (raw[len - 1] == 'i') - { - cflags |= REG_ICASE; - len -= 1; - } + else if (raw[len - 1] == 's') + { + cflags |= REG_NEWLINE; + len -= 1; + } - else if (raw[len - 1] == 's') - { - cflags |= REG_NEWLINE; - len -= 1; - } + else if (raw[len - 1] == '/') + break; - else if (raw[len - 1] == '/') - break; + } - } + if (result) + result = (raw[len - 1] == '/'); - if (result) - result = (raw[len - 1] == '/'); + if (result) + { + assert(len > 2); + + tmp = strndup(&raw[1], len - 2); + ret = regcomp(&expr->value.preg, tmp, cflags); + free(tmp); + + result = (ret == 0); if (result) - { - assert(len > 2); + expr->value.regex = strdup(raw); + + } + + break; - tmp = strndup(&raw[1], len - 2); - ret = regcomp(&expr->value.preg, tmp, cflags); - free(tmp); + default: + result = false; + break; - result = (ret == 0); + } - if (result) - expr->value.regex = strdup(raw); + va_end(ap); - } + expr->value_type = vtype; - break; + return result; - default: - result = false; - break; +} - } - va_end(ap); +/****************************************************************************** +* * +* Paramètres : expr = expression à consulter. * +* * +* Description : Indique le type de valeur portée par une expression. * +* * +* Retour : Type de valeur associée à l'expression. * +* * +* Remarques : - * +* * +******************************************************************************/ - } +LiteralValueType g_scan_literal_expression_get_value_type(const GScanLiteralExpression *expr) +{ + LiteralValueType result; /* Type à retourner */ - expr->value_type = vtype; + result = expr->value_type; return result; @@ -314,7 +342,7 @@ bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype, /****************************************************************************** * * -* Paramètres : item = premier objet à consulter pour une comparaison. * +* Paramètres : expr = premier objet à consulter pour une comparaison. * * value = valeur portée portée par l'expression. [OUT] * * * * Description : Indique la valeur portée par une expression booléenne. * @@ -325,14 +353,41 @@ bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype, * * ******************************************************************************/ -bool g_literal_expression_get_boolean_value(const GLiteralExpression *item, bool *value) +bool g_scan_literal_expression_get_boolean_value(const GScanLiteralExpression *expr, bool *value) +{ + bool result; /* Etat à retourner */ + + result = (expr->value_type == LVT_BOOLEAN); + + if (result) + *value = expr->value.boolean; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = premier objet à consulter pour une comparaison. * +* value = valeur portée portée par l'expression. [OUT] * +* * +* Description : Indique la valeur portée par une expression d'entier. * +* * +* Retour : true si l'expression est de type entier, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_scan_literal_expression_get_signed_integer_value(const GScanLiteralExpression *expr, long long *value) { bool result; /* Etat à retourner */ - result = (item->value_type == EVT_BOOLEAN); + result = (expr->value_type == LVT_SIGNED_INTEGER); if (result) - *value = item->value.boolean; + *value = expr->value.u_integer; return result; @@ -341,7 +396,7 @@ bool g_literal_expression_get_boolean_value(const GLiteralExpression *item, bool /****************************************************************************** * * -* Paramètres : item = premier objet à consulter pour une comparaison. * +* Paramètres : expr = premier objet à consulter pour une comparaison. * * value = valeur portée portée par l'expression. [OUT] * * * * Description : Indique la valeur portée par une expression d'entier. * @@ -352,14 +407,14 @@ bool g_literal_expression_get_boolean_value(const GLiteralExpression *item, bool * * ******************************************************************************/ -bool g_literal_expression_get_integer_value(const GLiteralExpression *item, unsigned long long *value) +bool g_scan_literal_expression_get_unsigned_integer_value(const GScanLiteralExpression *expr, unsigned long long *value) { bool result; /* Etat à retourner */ - result = (item->value_type == EVT_INTEGER); + result = (expr->value_type == LVT_UNSIGNED_INTEGER); if (result) - *value = item->value.integer; + *value = expr->value.u_integer; return result; @@ -368,7 +423,7 @@ bool g_literal_expression_get_integer_value(const GLiteralExpression *item, unsi /****************************************************************************** * * -* Paramètres : item = premier objet à consulter pour une comparaison. * +* Paramètres : expr = premier objet à consulter pour une comparaison. * * value = valeur portée portée par l'expression. [OUT] * * * * Description : Indique la valeur portée par une expression de chaîne. * @@ -379,14 +434,14 @@ bool g_literal_expression_get_integer_value(const GLiteralExpression *item, unsi * * ******************************************************************************/ -bool g_literal_expression_get_string_value(const GLiteralExpression *item, const sized_string_t **value) +bool g_scan_literal_expression_get_string_value(const GScanLiteralExpression *expr, const sized_string_t **value) { bool result; /* Etat à retourner */ - result = (item->value_type == EVT_STRING); + result = (expr->value_type == LVT_STRING); if (result) - *value = &item->value.string; + *value = &expr->value.string; return result; @@ -395,7 +450,7 @@ bool g_literal_expression_get_string_value(const GLiteralExpression *item, const /****************************************************************************** * * -* Paramètres : item = premier objet à consulter pour une comparaison. * +* Paramètres : expr = premier objet à consulter pour une comparaison. * * value = valeur portée portée par l'expression. [OUT] * * * * Description : Indique la valeur portée par une expression rationnelle. * @@ -406,14 +461,14 @@ bool g_literal_expression_get_string_value(const GLiteralExpression *item, const * * ******************************************************************************/ -bool g_literal_expression_get_regex_value(const GLiteralExpression *item, const regex_t **value) +bool g_scan_literal_expression_get_regex_value(const GScanLiteralExpression *expr, const regex_t **value) { bool result; /* Etat à retourner */ - result = (item->value_type == EVT_REG_EXPR); + result = (expr->value_type == LVT_REG_EXPR); if (result) - *value = &item->value.preg; + *value = &expr->value.preg; return result; @@ -428,7 +483,7 @@ bool g_literal_expression_get_regex_value(const GLiteralExpression *item, const /****************************************************************************** * * -* Paramètres : item = premier objet à consulter pour une comparaison. * +* Paramètres : expr = premier objet à consulter pour une comparaison. * * other = second objet à consulter pour une comparaison. * * op = opération de comparaison à réaliser. * * status = bilan des opérations de comparaison. [OUT] * @@ -441,32 +496,32 @@ bool g_literal_expression_get_regex_value(const GLiteralExpression *item, const * * ******************************************************************************/ -static bool g_literal_expression_compare_rich(const GLiteralExpression *item, const GLiteralExpression *other, RichCmpOperation op, bool *status) +static bool g_scan_literal_expression_compare_rich(const GScanLiteralExpression *expr, const GScanLiteralExpression *other, RichCmpOperation op, bool *status) { bool result; /* Etat à retourner */ int cmp; /* Bilan intermédiaire */ - result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_LITERAL_EXPRESSION); + result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_SCAN_LITERAL_EXPRESSION); if (!result) goto done; - if (item->value_type != other->value_type) + if (expr->value_type != other->value_type) { - *status = compare_rich_integer_values(item->value_type, other->value_type, op); + *status = compare_rich_integer_values_unsigned(expr->value_type, other->value_type, op); goto done; } - switch (item->value_type) + switch (expr->value_type) { - case EVT_BOOLEAN: + case LVT_BOOLEAN: switch (op) { case RCO_EQ: - *status = (item->value.boolean == other->value.boolean); + *status = (expr->value.boolean == other->value.boolean); result = true; break; case RCO_NE: - *status = (item->value.boolean != other->value.boolean); + *status = (expr->value.boolean != other->value.boolean); result = true; break; @@ -477,20 +532,25 @@ static bool g_literal_expression_compare_rich(const GLiteralExpression *item, co }; break; - case EVT_INTEGER: - *status = compare_rich_integer_values(item->value.integer, other->value.integer, op); + case LVT_SIGNED_INTEGER: + *status = compare_rich_integer_values_signed(expr->value.s_integer, other->value.s_integer, op); result = true; break; - case EVT_STRING: - cmp = szstrcmp(&item->value.string, &other->value.string); - *status = compare_rich_integer_values(cmp, 0, op); + case LVT_UNSIGNED_INTEGER: + *status = compare_rich_integer_values_unsigned(expr->value.u_integer, other->value.u_integer, op); result = true; break; - case EVT_REG_EXPR: - cmp = strcmp(item->value.regex, other->value.regex); - *status = compare_rich_integer_values(cmp, 0, op); + case LVT_STRING: + cmp = szstrcmp(&expr->value.string, &other->value.string); + *status = compare_rich_integer_values_signed(cmp, 0, op); + result = true; + break; + + case LVT_REG_EXPR: + cmp = strcmp(expr->value.regex, other->value.regex); + *status = compare_rich_integer_values_signed(cmp, 0, op); result = true; break; @@ -509,62 +569,63 @@ static bool g_literal_expression_compare_rich(const GLiteralExpression *item, co /****************************************************************************** * * -* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] * -* src = expression source à copier. * +* Paramètres : expr = expression à consulter. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la réduction opérée. [OUT] * * * -* Description : Reproduit une expression en place dans une nouvelle instance.* +* Description : Réduit une expression à une forme booléenne. * * * -* Retour : - * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * * Remarques : - * * * ******************************************************************************/ -static void g_literal_expression_copy(GLiteralExpression *dest, const GLiteralExpression *src) +static bool g_scan_literal_expression_reduce_to_boolean(GScanLiteralExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - GScanExpressionClass *class; /* Classe parente à solliciter */ - - class = G_SCAN_EXPRESSION_CLASS(g_literal_expression_parent_class); - - class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src)); - - dest->value_type = src->value_type; + bool result; /* Bilan à retourner */ - switch (src->value_type) + switch (expr->value_type) { - case EVT_BOOLEAN: - dest->value.boolean = src->value.boolean; + case LVT_BOOLEAN: + *out = G_SCAN_EXPRESSION(expr); + g_object_ref(G_OBJECT(expr)); + result = true; break; - case EVT_INTEGER: - dest->value.integer = src->value.integer; + case LVT_SIGNED_INTEGER: + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->value.s_integer != 0 }); + result = true; break; - case EVT_STRING: - szstrdup(&dest->value.string, &src->value.string); + case LVT_UNSIGNED_INTEGER: + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->value.u_integer != 0 }); + result = true; break; - case EVT_REG_EXPR: - /*ptr = &expr->value.regex*//* FIXME */; + case LVT_STRING: + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->value.string.len > 0 }); + result = true; break; default: - assert(false); + result = false; break; } + return result; + } /****************************************************************************** * * * Paramètres : expr = expression à consulter. * -* ctx = contexte de suivi de l'analyse courante. * -* scope = portée courante des variables locales. * -* out = zone d'enregistrement de la réduction opérée. [OUT] * +* count = quantité d'éléments déterminée. [OUT] * * * -* Description : Réduit une expression à une forme plus simple. * +* Description : Dénombre les éléments portés par une expression. * * * * Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * @@ -572,14 +633,22 @@ static void g_literal_expression_copy(GLiteralExpression *dest, const GLiteralEx * * ******************************************************************************/ -static bool g_literal_expression_reduce(GLiteralExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +static bool g_scan_literal_expression_count(const GScanLiteralExpression *expr, size_t *count) { bool result; /* Bilan à retourner */ - result = true; + switch (expr->value_type) + { + case LVT_STRING: + *count = expr->value.string.len; + result = true; + break; + + default: + result = false; + break; - *out = G_SCAN_EXPRESSION(expr); - g_object_ref(G_OBJECT(expr)); + } return result; |