summaryrefslogtreecommitdiff
path: root/src/analysis/scan/exprs
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2023-07-07 06:32:43 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2023-07-07 06:32:43 (GMT)
commit4c10dfa2a95cea6fc704d68066d0c284cfd79342 (patch)
tree5827bbc411459800747e21929daecdf99fde7dfd /src/analysis/scan/exprs
parent3f996be1e5858b54740bf92515795982a16b169a (diff)
Rewrite core parts of the ROST API.
Diffstat (limited to 'src/analysis/scan/exprs')
-rw-r--r--src/analysis/scan/exprs/Makefile.am6
-rw-r--r--src/analysis/scan/exprs/access-int.h69
-rw-r--r--src/analysis/scan/exprs/access.c471
-rw-r--r--src/analysis/scan/exprs/access.h63
-rw-r--r--src/analysis/scan/exprs/arithmop-int.h4
-rw-r--r--src/analysis/scan/exprs/arithmop.c210
-rw-r--r--src/analysis/scan/exprs/boolop.c161
-rw-r--r--src/analysis/scan/exprs/call-int.h13
-rw-r--r--src/analysis/scan/exprs/call.c223
-rw-r--r--src/analysis/scan/exprs/call.h7
-rw-r--r--src/analysis/scan/exprs/literal-int.h2
-rw-r--r--src/analysis/scan/exprs/literal.c113
-rw-r--r--src/analysis/scan/exprs/literal.h3
-rw-r--r--src/analysis/scan/exprs/relop-int.h4
-rw-r--r--src/analysis/scan/exprs/relop.c156
-rw-r--r--src/analysis/scan/exprs/strop-int.h (renamed from src/analysis/scan/exprs/str-int.h)15
-rw-r--r--src/analysis/scan/exprs/strop.c (renamed from src/analysis/scan/exprs/str.c)258
-rw-r--r--src/analysis/scan/exprs/strop.h (renamed from src/analysis/scan/exprs/str.h)8
18 files changed, 1208 insertions, 578 deletions
diff --git a/src/analysis/scan/exprs/Makefile.am b/src/analysis/scan/exprs/Makefile.am
index f164864..efe25fc 100644
--- a/src/analysis/scan/exprs/Makefile.am
+++ b/src/analysis/scan/exprs/Makefile.am
@@ -3,6 +3,8 @@ noinst_LTLIBRARIES = libanalysisscanexprs.la
libanalysisscanexprs_la_SOURCES = \
+ access-int.h \
+ access.h access.c \
arithmop-int.h \
arithmop.h arithmop.c \
boolop-int.h \
@@ -13,8 +15,8 @@ libanalysisscanexprs_la_SOURCES = \
literal.h literal.c \
relop-int.h \
relop.h relop.c \
- str-int.h \
- str.h str.c
+ strop-int.h \
+ strop.h strop.c
libanalysisscanexprs_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
diff --git a/src/analysis/scan/exprs/access-int.h b/src/analysis/scan/exprs/access-int.h
new file mode 100644
index 0000000..2212b48
--- /dev/null
+++ b/src/analysis/scan/exprs/access-int.h
@@ -0,0 +1,69 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * access-int.h - prototypes internes pour l'accès à un élément d'expression sous-jacent
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_ACCESS_INT_H
+#define _ANALYSIS_SCAN_EXPRS_ACCESS_INT_H
+
+
+#include "access.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Accès à un élément d'expression sous-jacent (instance) */
+struct _GNamedAccess
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ union
+ {
+ GRegisteredItem *base; /* Base de recherche */
+ GRegisteredItem *resolved; /* Elément ciblé au final */
+ GObject *any; /* Accès indistinct */
+ };
+
+ char *target; /* Cible dans l'espace */
+
+ struct _GNamedAccess *next; /* Evnetuel prochain élément */
+
+};
+
+/* Accès à un élément d'expression sous-jacent (classe) */
+struct _GNamedAccessClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une expression d'accès. */
+bool g_named_access_create(GNamedAccess *, const sized_string_t *);
+
+/* Réduit une expression à une forme plus simple. */
+bool _g_named_access_reduce(GNamedAccess *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_ACCESS_INT_H */
diff --git a/src/analysis/scan/exprs/access.c b/src/analysis/scan/exprs/access.c
new file mode 100644
index 0000000..ad66f60
--- /dev/null
+++ b/src/analysis/scan/exprs/access.c
@@ -0,0 +1,471 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * access.c - accès à un élément d'expression sous-jacent
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "access.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include "access-int.h"
+#include "../../../core/global.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des appels de fonction avec arguments. */
+static void g_named_access_class_init(GNamedAccessClass *);
+
+/* Initialise une instance d'appel de fonction avec arguments. */
+static void g_named_access_init(GNamedAccess *);
+
+/* Supprime toutes les références externes. */
+static void g_named_access_dispose(GNamedAccess *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_named_access_finalize(GNamedAccess *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Reproduit une expression en place dans une nouvelle instance. */
+static void g_named_access_copy(GNamedAccess *, const GNamedAccess *);
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_named_access_reduce(GNamedAccess *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un appel de fonction enregistrée. */
+G_DEFINE_TYPE(GNamedAccess, g_named_access, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des appels de fonction avec arguments. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_named_access_class_init(GNamedAccessClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_named_access_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_named_access_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)NULL;
+ expr->copy = (copy_expr_fc)g_named_access_copy;
+ expr->reduce = (reduce_expr_fc)g_named_access_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : access = instance à initialiser. *
+* *
+* Description : Initialise une instance d'appel de fonction avec arguments. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_named_access_init(GNamedAccess *access)
+{
+ access->any = NULL;
+ access->target = NULL;
+
+ access->next = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : access = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_named_access_dispose(GNamedAccess *access)
+{
+ g_clear_object(&access->any);
+
+ g_clear_object(&access->next);
+
+ G_OBJECT_CLASS(g_named_access_parent_class)->dispose(G_OBJECT(access));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : access = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_named_access_finalize(GNamedAccess *access)
+{
+ if (access->target != NULL)
+ free(access->target);
+
+ G_OBJECT_CLASS(g_named_access_parent_class)->finalize(G_OBJECT(access));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : target = désignation de l'objet d'appel à identifier. *
+* *
+* Description : Organise un accès à un élément d'expression sous-jacent. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_named_access_new(const sized_string_t *target)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_NAMED_ACCESS, NULL);
+
+ if (!g_named_access_create(G_NAMED_ACCESS(result), target))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : access = instance à initialiser pleinement. *
+* target = désignation de l'objet d'appel à identifier. *
+* *
+* Description : Met en place une expression d'accès. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_named_access_create(GNamedAccess *access, const sized_string_t *target)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_scan_expression_create(G_SCAN_EXPRESSION(access), EVT_PENDING);
+ if (!result) goto exit;
+
+ access->target = strndup(target->data, target->len);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : access = expression d'appel à actualiser. *
+* base = zone de recherche pour la résolution à venir. *
+* *
+* Description : Définit une base de recherche pour la cible d'accès. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_named_access_set_base(GNamedAccess *access, GRegisteredItem *base)
+{
+ g_clear_object(&access->base);
+
+ access->base = base;
+ g_object_ref(G_OBJECT(base));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : access = expression d'appel à compléter. *
+* next = expression d'appel suivante dans la chaîne. *
+* *
+* Description : Complète la chaine d'accès à des expressions. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_named_access_attach_next(GNamedAccess *access, GNamedAccess *next)
+{
+ if (access->next != NULL)
+ g_named_access_attach_next(access->next, next);
+
+ else
+ {
+ access->next = next;
+ g_object_ref(G_OBJECT(next));
+ }
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* 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_named_access_copy(GNamedAccess *dest, const GNamedAccess *src)
+{
+ GScanExpressionClass *class; /* Classe parente à solliciter */
+
+ class = G_SCAN_EXPRESSION_CLASS(g_named_access_parent_class);
+
+ class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
+
+ if (src->any != NULL)
+ {
+ dest->any = src->any;
+ g_object_ref(src->any);
+ }
+
+ if (src->target != NULL)
+ dest->target = strdup(src->target);
+
+ if (src->next != NULL)
+ dest->next = G_NAMED_ACCESS(g_scan_expression_duplicate(G_SCAN_EXPRESSION(src->next)));
+
+}
+
+
+/******************************************************************************
+* *
+* 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 : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool _g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+ GRegisteredItem *base; /* Base de recherche courante */
+ GRegisteredItem *resolved; /* Cible concrète obtenue */
+ GNamedAccess *new; /* Copie mise en place */
+
+ result = true;
+
+ if (expr->target != NULL)
+ {
+ if (expr->base != NULL)
+ {
+ base = expr->base;
+ g_object_ref(G_OBJECT(base));
+ }
+ else
+ base = G_REGISTERED_ITEM(get_rost_root_namespace());
+
+ result = g_registered_item_resolve(base, expr->target, ctx, scope, &resolved);
+
+ g_object_unref(G_OBJECT(base));
+
+ if (result && resolved != NULL)
+ {
+ new = G_NAMED_ACCESS(g_scan_expression_duplicate(G_SCAN_EXPRESSION(expr)));
+
+ g_clear_object(&new->base);
+
+ free(new->target);
+ new->target = NULL;
+
+ new->resolved = resolved;
+
+ *out = G_SCAN_EXPRESSION(new);
+
+ }
+
+ }
+
+ /**
+ * Si plus aucune indication n'est diponible pour avancer dans les réductions,
+ * c'est que l'opération est déjà conclue.
+ */
+ else
+ {
+ assert(expr->resolved != NULL);
+
+ *out = G_SCAN_EXPRESSION(expr);
+ g_object_ref(G_OBJECT(*out));
+
+ }
+
+ 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] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+ GNamedAccess *new; /* Eventuel étage suivant */
+ GScanExpression *final; /* Expression d'évaluation */
+ GScanExpression *new_next; /* Nouvelle version du suivant */
+
+ result = _g_named_access_reduce(expr, ctx, scope, out);
+
+ if (result && *out != NULL)
+ {
+ assert(G_IS_NAMED_ACCESS(*out));
+
+ new = G_NAMED_ACCESS(*out);
+ *out = NULL;
+
+ assert(new->target == NULL);
+ assert(G_IS_NAMED_ACCESS(new));
+ assert(G_IS_REGISTERED_ITEM(new->resolved));
+
+ /**
+ * Si l'élément résolu se trouve en fin de chaîne, alors cet élément
+ * est sollicité pour obtenir une expression d'évaluation classique.
+ * Le produit de cette réduction finale bénéficie d'une promotion et
+ * représente à lui seul la réduction produite pour la chaîne.
+ */
+ if (new->next == NULL)
+ {
+ result = g_registered_item_reduce(new->resolved, ctx, scope, &final);
+
+ if (result && final != NULL)
+ {
+ g_clear_object(out);
+ *out = final;
+ }
+
+ }
+
+ /**
+ * Sinon, l'élément résolu constitue une base pour l'étage suivant de
+ * la chaîne de résolution.
+ */
+ else
+ {
+ new_next = g_scan_expression_duplicate(G_SCAN_EXPRESSION(new->next));
+ assert(G_IS_NAMED_ACCESS(new_next));
+
+ g_named_access_set_base(G_NAMED_ACCESS(new_next), new->resolved);
+
+ g_clear_object(out);
+
+ result = g_scan_expression_reduce(new_next, ctx, scope, out);
+
+ if (result && *out == NULL)
+ *out = new_next;
+
+ }
+
+ g_object_unref(G_OBJECT(new));
+
+ }
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/access.h b/src/analysis/scan/exprs/access.h
new file mode 100644
index 0000000..a04adc7
--- /dev/null
+++ b/src/analysis/scan/exprs/access.h
@@ -0,0 +1,63 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * access.h - prototypes pour l'accès à un élément d'expression sous-jacent
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_EXPRS_ACCESS_H
+#define _ANALYSIS_SCAN_EXPRS_ACCESS_H
+
+
+#include "../expr.h"
+#include "../item.h"
+#include "../../../common/szstr.h"
+
+
+
+#define G_TYPE_NAMED_ACCESS g_named_access_get_type()
+#define G_NAMED_ACCESS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_NAMED_ACCESS, GNamedAccess))
+#define G_IS_NAMED_ACCESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_NAMED_ACCESS))
+#define G_NAMED_ACCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_NAMED_ACCESS, GNamedAccessClass))
+#define G_IS_NAMED_ACCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_NAMED_ACCESS))
+#define G_NAMED_ACCESS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_NAMED_ACCESS, GNamedAccessClass))
+
+
+/* Accès à un élément d'expression sous-jacent (instance) */
+typedef struct _GNamedAccess GNamedAccess;
+
+/* Accès à un élément d'expression sous-jacent (classe) */
+typedef struct _GNamedAccessClass GNamedAccessClass;
+
+
+/* Indique le type défini pour un appel de fonction enregistrée. */
+GType g_named_access_get_type(void);
+
+/* Organise un accès à un élément d'expression sous-jacent. */
+GScanExpression *g_named_access_new(const sized_string_t *);
+
+/* Définit une base de recherche pour la cible d'accès. */
+void g_named_access_set_base(GNamedAccess *, GRegisteredItem *);
+
+/* Complète la chaine d'accès à des expressions. */
+void g_named_access_attach_next(GNamedAccess *, GNamedAccess *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_ACCESS_H */
diff --git a/src/analysis/scan/exprs/arithmop-int.h b/src/analysis/scan/exprs/arithmop-int.h
index 75f1dbb..031de84 100644
--- a/src/analysis/scan/exprs/arithmop-int.h
+++ b/src/analysis/scan/exprs/arithmop-int.h
@@ -39,8 +39,8 @@ struct _GArithmOperation
ArithmeticExpressionOperator operator; /* Type d'opération menée */
- GScanExpression *first; /* Expression impactée #1 */
- GScanExpression *second; /* Expression impactée #2 */
+ GScanExpression *left; /* Expression impactée #1 */
+ GScanExpression *right; /* Expression impactée #2 */
};
diff --git a/src/analysis/scan/exprs/arithmop.c b/src/analysis/scan/exprs/arithmop.c
index f57e260..5f9e3f1 100644
--- a/src/analysis/scan/exprs/arithmop.c
+++ b/src/analysis/scan/exprs/arithmop.c
@@ -52,11 +52,11 @@ static void g_arithmetic_operation_finalize(GArithmOperation *);
/* Réalise une comparaison entre objets selon un critère précis. */
static bool g_arithmetic_operation_compare_rich(const GArithmOperation *, const GArithmOperation *, RichCmpOperation, bool *);
-/* Initialise une instance d'opération de relation. */
-static GScanExpression *g_arithmetic_operation_duplicate(const GArithmOperation *);
+/* Reproduit une expression en place dans une nouvelle instance. */
+static void g_arithmetic_operation_copy(GArithmOperation *, const GArithmOperation *);
/* Réduit une expression à une forme plus simple. */
-GScanExpression *g_arithmetic_operation_reduce(GArithmOperation *, GScanContext *, bool);
+static bool g_arithmetic_operation_reduce(GArithmOperation *, GScanContext *, GScanScope *, GScanExpression **);
@@ -94,7 +94,7 @@ static void g_arithmetic_operation_class_init(GArithmOperationClass *klass)
expr = G_SCAN_EXPRESSION_CLASS(klass);
expr->cmp_rich = (compare_expr_rich_fc)g_arithmetic_operation_compare_rich;
- expr->dup = (dup_expr_fc)g_arithmetic_operation_duplicate;
+ expr->copy = (copy_expr_fc)g_arithmetic_operation_copy;
expr->reduce = (reduce_expr_fc)g_arithmetic_operation_reduce;
}
@@ -114,8 +114,8 @@ static void g_arithmetic_operation_class_init(GArithmOperationClass *klass)
static void g_arithmetic_operation_init(GArithmOperation *op)
{
- op->first = NULL;
- op->second = NULL;
+ op->left = NULL;
+ op->right = NULL;
}
@@ -134,8 +134,8 @@ static void g_arithmetic_operation_init(GArithmOperation *op)
static void g_arithmetic_operation_dispose(GArithmOperation *op)
{
- g_clear_object(&op->first);
- g_clear_object(&op->second);
+ g_clear_object(&op->left);
+ g_clear_object(&op->right);
G_OBJECT_CLASS(g_arithmetic_operation_parent_class)->dispose(G_OBJECT(op));
@@ -164,8 +164,8 @@ static void g_arithmetic_operation_finalize(GArithmOperation *op)
/******************************************************************************
* *
* Paramètres : operator = type d'opération arithmétique à représenter. *
-* first = premier opérande concerné. *
-* second = éventuel second opérande impliqué ou NULL. *
+* left = premier opérande concerné. *
+* right = éventuel second opérande impliqué ou NULL. *
* *
* Description : Organise une opération arithmétique entre expressions. *
* *
@@ -175,13 +175,13 @@ static void g_arithmetic_operation_finalize(GArithmOperation *op)
* *
******************************************************************************/
-GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operator, GScanExpression *first, GScanExpression *second)
+GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right)
{
GScanExpression *result; /* Structure à retourner */
result = g_object_new(G_TYPE_ARITHMETIC_OPERATION, NULL);
- if (!g_arithmetic_operation_create(G_ARITHMETIC_OPERATION(result), operator, first, second))
+ if (!g_arithmetic_operation_create(G_ARITHMETIC_OPERATION(result), operator, left, right))
g_clear_object(&result);
return result;
@@ -193,8 +193,8 @@ GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operato
* *
* Paramètres : op = instance à initialiser pleinement. *
* operator = type d'opération booléenne à représenter. *
-* first = premier opérande concerné. *
-* second = éventuel second opérande impliqué ou NULL. *
+* left = premier opérande concerné. *
+* right = éventuel second opérande impliqué ou NULL. *
* *
* Description : Met en place une opération arithmétique entre expressions. *
* *
@@ -204,19 +204,19 @@ GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operato
* *
******************************************************************************/
-bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOperator operator, GScanExpression *first, GScanExpression *second)
+bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right)
{
bool result; /* Bilan à retourner */
ExprValueType vtype; /* Type de valeur portée */
result = false;
- vtype = g_scan_expression_get_value_type(first);
+ vtype = g_scan_expression_get_value_type(left);
if (vtype != EVT_INTEGER && vtype != EVT_PENDING)
goto exit;
- vtype = g_scan_expression_get_value_type(second);
+ vtype = g_scan_expression_get_value_type(right);
if (vtype != EVT_INTEGER && vtype != EVT_PENDING)
goto exit;
@@ -226,11 +226,11 @@ bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOpe
op->operator = operator;
- op->first = first;
- g_object_ref(G_OBJECT(op->first));
+ op->left = left;
+ g_object_ref(G_OBJECT(op->left));
- op->second = second;
- g_object_ref(G_OBJECT(op->second));
+ op->right = right;
+ g_object_ref(G_OBJECT(op->right));
result = true;
@@ -265,9 +265,9 @@ bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOpe
static bool g_arithmetic_operation_compare_rich(const GArithmOperation *item, const GArithmOperation *other, RichCmpOperation op, bool *status)
{
bool result; /* Etat à retourner */
- bool equal; /* Bilan intermédiaire */
- result = true; // TODO : cmp parent()->type
+ result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_ARITHMETIC_OPERATION);
+ if (!result) goto done;
if (item->operator != other->operator)
{
@@ -275,18 +275,16 @@ static bool g_arithmetic_operation_compare_rich(const GArithmOperation *item, co
goto done;
}
- equal = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
+ if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
- if (!equal)
- {
- result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first),
- G_COMPARABLE_ITEM(other->first),
- op, status);
- goto done;
- }
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->left),
+ G_COMPARABLE_ITEM(other->left),
+ op, status);
+ if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
- result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second),
- G_COMPARABLE_ITEM(other->second),
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->right),
+ G_COMPARABLE_ITEM(other->right),
op, status);
done:
@@ -298,23 +296,29 @@ static bool g_arithmetic_operation_compare_rich(const GArithmOperation *item, co
/******************************************************************************
* *
-* Paramètres : expr = expression à copier. *
+* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
+* src = expression source à copier. *
* *
* Description : Reproduit une expression en place dans une nouvelle instance.*
* *
-* Retour : Nouvelle instance d'expression. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static GScanExpression *g_arithmetic_operation_duplicate(const GArithmOperation *expr)
+static void g_arithmetic_operation_copy(GArithmOperation *dest, const GArithmOperation *src)
{
- GScanExpression *result; /* Instance copiée à retourner */
+ GScanExpressionClass *class; /* Classe parente à solliciter */
- result = g_arithmetic_operation_new(expr->operator, expr->first, expr->second);
+ class = G_SCAN_EXPRESSION_CLASS(g_arithmetic_operation_parent_class);
- return result;
+ class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
+
+ dest->operator = src->operator;
+
+ dest->left = g_scan_expression_duplicate(src->left);
+ dest->right = g_scan_expression_duplicate(src->right);
}
@@ -323,92 +327,110 @@ static GScanExpression *g_arithmetic_operation_duplicate(const GArithmOperation
* *
* Paramètres : expr = expression à consulter. *
* ctx = contexte de suivi de l'analyse courante. *
-* final = impose une conversion finale de dernier tour. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
* *
* Description : Réduit une expression à une forme plus simple. *
* *
-* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
* *
* Remarques : - *
* *
******************************************************************************/
-GScanExpression *g_arithmetic_operation_reduce(GArithmOperation *expr, GScanContext *ctx, bool final)
+static bool g_arithmetic_operation_reduce(GArithmOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- GScanExpression *result; /* Instance à renvoyer */
- GScanExpression *new; /* Nouvelle expression obtenue */
+ bool result; /* Bilan à 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 */
unsigned long long val_1; /* Première valeur à traiter */
- unsigned long long val_2; /* Second valeur à traiter */
- bool valid; /* Validité de ce bilan obtenu */
+ unsigned long long val_2; /* Seconde valeur à traiter */
unsigned long long reduced; /* Valeur réduite finale */
- result = NULL;
-
/* Réduction des éléments considérés */
- new = g_scan_expression_reduce(expr->first, ctx, final);
-
- if (new != NULL)
- {
- g_object_unref(G_OBJECT(expr->first));
- expr->first = new;
- }
+ new_left = NULL;
+ new_right = NULL;
- if (expr->second != NULL)
- {
- new = g_scan_expression_reduce(expr->second, ctx, final);
+ result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
+ if (!result) goto exit;
- if (new != NULL)
- {
- g_object_unref(G_OBJECT(expr->second));
- expr->second = new;
- }
-
- }
+ result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
+ if (!result) goto exit;
/* Construction d'une réduction locale ? */
- if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second))
+ if (G_IS_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right))
{
- valid = g_literal_expression_get_integer_value(G_LITERAL_EXPRESSION(expr->first), &val_1);
+ op_left = G_LITERAL_EXPRESSION(new_left);
+ op_right = G_LITERAL_EXPRESSION(new_right);
- if (valid)
- valid = g_literal_expression_get_integer_value(G_LITERAL_EXPRESSION(expr->second), &val_2);
+ result = g_literal_expression_get_integer_value(op_left, &val_1);
+ if (!result) goto exit;
- if (valid)
- switch (expr->operator)
- {
- case AEO_PLUS:
- reduced = val_1 + val_2;
- break;
+ result = g_literal_expression_get_integer_value(op_right, &val_2);
+ if (!result) goto exit;
- case AEO_MINUS:
- reduced = val_1 - val_2;
- break;
+ switch (expr->operator)
+ {
+ case AEO_PLUS:
+ reduced = val_1 + val_2;
+ break;
+
+ case AEO_MINUS:
+ reduced = val_1 - val_2;
+ break;
+
+ case AEO_MUL:
+ reduced = val_1 * val_2;
+ break;
+
+ case AEO_DIV:
+ result = (val_2 != 0);
+ if (result)
+ reduced = val_1 / val_2;
+ break;
+
+ case AEO_MOD:
+ result = (val_2 != 0);
+ if (result)
+ reduced = val_1 % val_2;
+ break;
- case AEO_MUL:
- reduced = val_1 * val_2;
- break;
+ }
- case AEO_DIV:
- valid = (val_2 != 0);
- if (valid)
- reduced = val_1 / val_2;
- break;
+ if (result)
+ *out = g_literal_expression_new(EVT_INTEGER, &reduced);
- case AEO_MOD:
- valid = (val_2 != 0);
- if (valid)
- reduced = val_1 % val_2;
- break;
+ }
- }
+ /* Mise à jour de la progression ? */
- if (valid)
- result = g_literal_expression_new(EVT_INTEGER, &reduced);
+ else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right))
+ {
+ if (new_left == NULL)
+ {
+ new_left = expr->left;
+ g_object_ref(G_OBJECT(new_left));
+ }
+
+ if (new_right == NULL)
+ {
+ new_right = expr->right;
+ g_object_ref(G_OBJECT(new_right));
+ }
+
+ *out = g_arithmetic_operation_new(expr->operator, new_left, new_right);
}
+ exit:
+
+ g_clear_object(&new_left);
+ g_clear_object(&new_right);
+
return result;
}
diff --git a/src/analysis/scan/exprs/boolop.c b/src/analysis/scan/exprs/boolop.c
index 2902fdd..f6a80dd 100644
--- a/src/analysis/scan/exprs/boolop.c
+++ b/src/analysis/scan/exprs/boolop.c
@@ -56,10 +56,10 @@ static void g_boolean_operation_finalize(GBoolOperation *);
static bool g_boolean_operation_compare_rich(const GBoolOperation *, const GBoolOperation *, RichCmpOperation, bool *);
/* Reproduit une expression en place dans une nouvelle instance. */
-static GScanExpression *g_boolean_operation_duplicate(const GBoolOperation *);
+static void g_boolean_operation_copy(GBoolOperation *, const GBoolOperation *);
/* Réduit une expression à une forme plus simple. */
-GScanExpression *g_boolean_operation_reduce(GBoolOperation *, GScanContext *, bool);
+static bool g_boolean_operation_reduce(GBoolOperation *, GScanContext *, GScanScope *, GScanExpression **);
@@ -97,7 +97,7 @@ static void g_boolean_operation_class_init(GBoolOperationClass *klass)
expr = G_SCAN_EXPRESSION_CLASS(klass);
expr->cmp_rich = (compare_expr_rich_fc)g_boolean_operation_compare_rich;
- expr->dup = (dup_expr_fc)g_boolean_operation_duplicate;
+ expr->copy = (copy_expr_fc)g_boolean_operation_copy;
expr->reduce = (reduce_expr_fc)g_boolean_operation_reduce;
}
@@ -278,9 +278,9 @@ bool g_boolean_operation_create(GBoolOperation *op, BooleanOperationType type, G
static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const GBoolOperation *other, RichCmpOperation op, bool *status)
{
bool result; /* Etat à retourner */
- bool equal; /* Bilan intermédiaire */
- result = true;
+ result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_BOOLEAN_OPERATION);
+ if (!result) goto done;
if (item->type != other->type)
{
@@ -288,15 +288,13 @@ static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const G
goto done;
}
- equal = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
+ if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
- if (!equal)
- {
- *status = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first),
- G_COMPARABLE_ITEM(other->first),
- op, status);
- goto done;
- }
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first),
+ G_COMPARABLE_ITEM(other->first),
+ op, status);
+ if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
if (item->second == NULL)
{
@@ -321,9 +319,9 @@ static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const G
}
else
- *status = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second),
- G_COMPARABLE_ITEM(other->second),
- op, status);
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second),
+ G_COMPARABLE_ITEM(other->second),
+ op, status);
done:
@@ -334,23 +332,31 @@ static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const G
/******************************************************************************
* *
-* Paramètres : expr = expression à copier. *
+* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
+* src = expression source à copier. *
* *
* Description : Reproduit une expression en place dans une nouvelle instance.*
* *
-* Retour : Nouvelle instance d'expression. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static GScanExpression *g_boolean_operation_duplicate(const GBoolOperation *expr)
+static void g_boolean_operation_copy(GBoolOperation *dest, const GBoolOperation *src)
{
- GScanExpression *result; /* Instance copiée à retourner */
+ GScanExpressionClass *class; /* Classe parente à solliciter */
- result = g_boolean_operation_new(expr->type, expr->first, expr->second);
+ class = G_SCAN_EXPRESSION_CLASS(g_boolean_operation_parent_class);
- return result;
+ class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
+
+ dest->type = src->type;
+
+ dest->first = g_scan_expression_duplicate(src->first);
+
+ if (src->second != NULL)
+ dest->second = g_scan_expression_duplicate(src->second);
}
@@ -359,92 +365,115 @@ static GScanExpression *g_boolean_operation_duplicate(const GBoolOperation *expr
* *
* Paramètres : expr = expression à consulter. *
* ctx = contexte de suivi de l'analyse courante. *
-* final = impose une conversion finale de dernier tour. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
* *
* Description : Réduit une expression à une forme plus simple. *
* *
-* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
* *
* Remarques : - *
* *
******************************************************************************/
-GScanExpression *g_boolean_operation_reduce(GBoolOperation *expr, GScanContext *ctx, bool final)
+static bool g_boolean_operation_reduce(GBoolOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- GScanExpression *result; /* Instance à renvoyer */
- GScanExpression *new; /* Nouvelle expression obtenue */
+ bool result; /* Bilan à retourner */
+ GScanExpression *new_first; /* Expression réduite (gauche) */
+ GScanExpression *new_second; /* Expression réduite (droite) */
bool values[2]; /* Valeurs des éléments portés */
bool valid[2]; /* Validité de ces valeurs */
- result = NULL;
-
/* Réduction des éléments considérés */
- new = g_scan_expression_reduce(expr->first, ctx, final);
+ new_first = NULL;
+ new_second = NULL;
+
+ result = g_scan_expression_reduce(expr->first, ctx, scope, &new_first);
+ if (!result) goto exit;
- if (new != NULL)
+ if (expr->second == NULL)
+ new_second = NULL;
+ else
{
- g_object_unref(G_OBJECT(expr->first));
- expr->first = new;
+ result = g_scan_expression_reduce(expr->second, ctx, scope, &new_second);
+ if (!result) goto exit;
}
- if (expr->second != NULL)
- {
- new = g_scan_expression_reduce(expr->second, ctx, final);
+ /* Construction d'une réduction locale ? */
- if (new != NULL)
- {
- g_object_unref(G_OBJECT(expr->second));
- expr->second = new;
- }
+ valid[0] = G_IS_LITERAL_EXPRESSION(new_first);
- }
+ if (valid[0])
+ valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(new_first), &values[0]);
- /* Construction d'une réduction locale ? */
+ valid[1] = G_IS_LITERAL_EXPRESSION(new_second);
+
+ if (valid[1])
+ valid[1] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(new_second), &values[1]);
switch (expr->type)
{
case BOT_AND:
- if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second))
- {
- valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->first), &values[0]);
- valid[1] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->second), &values[1]);
+ if (valid[0] && valid[1])
+ *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] && values[1] });
- if (valid[0] && valid[1])
- result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] && values[1] });
+ else if (valid[0] && !values[0])
+ *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false });
- else
- /* Etre malin si 0 && x => bilan (si ctx->quick) */
- ;
+ else if (valid[1] && !values[1])
+ *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false });
- }
break;
case BOT_OR:
- if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second))
- {
- valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->first), &values[0]);
- valid[1] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->second), &values[1]);
+ if (valid[0] && valid[1])
+ *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] || values[1] });
- if (valid[0] && valid[1])
- result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] || values[1] });
+ else if (valid[0] && values[0])
+ *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { true });
+
+ else if (valid[1] && values[1])
+ *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { true });
- }
break;
case BOT_NOT:
- if (G_IS_LITERAL_EXPRESSION(expr->first))
- {
- valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->first), &values[0]);
+ if (valid[0])
+ *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { !values[0] });
+ break;
- if (valid[0])
- result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { !values[1] });
+ }
+
+ /* Mise à jour de la progression ? */
+
+ if (*out == NULL)
+ {
+ if ((new_first != NULL && new_first != expr->first) || (new_second != NULL && new_second != expr->second))
+ {
+ if (new_first == NULL)
+ {
+ new_first = expr->first;
+ g_object_ref(G_OBJECT(new_first));
+ }
+ if (new_second == NULL)
+ {
+ new_second = expr->second;
+ g_object_ref(G_OBJECT(new_second));
}
- break;
+
+ *out = g_boolean_operation_new(expr->type, new_first, new_second);
+
+ }
}
+ exit:
+
+ g_clear_object(&new_first);
+ g_clear_object(&new_second);
+
return result;
}
diff --git a/src/analysis/scan/exprs/call-int.h b/src/analysis/scan/exprs/call-int.h
index d68977f..631a25b 100644
--- a/src/analysis/scan/exprs/call-int.h
+++ b/src/analysis/scan/exprs/call-int.h
@@ -28,35 +28,30 @@
#include "call.h"
-#include "../expr-int.h"
+#include "access-int.h"
/* Exécution d'une fonction auxiliaire d'analyse (instance) */
struct _GPendingCall
{
- GScanExpression parent; /* A laisser en premier */
-
- GRegisteredItem *base; /* Base de recherche */
- char *target; /* Cible dans l'espace */
+ GNamedAccess parent; /* A laisser en premier */
GScanExpression **args; /* Arguments d'appel fournis */
size_t count; /* Quantité de ces arguments */
- struct _GPendingCall *next; /* Evnetuel prochain élément */
-
};
/* Exécution d'une fonction auxiliaire d'analyse (classe) */
struct _GPendingCallClass
{
- GScanExpressionClass parent; /* A laisser en premier */
+ GNamedAccessClass parent; /* A laisser en premier */
};
/* Met en place une expression d'appel. */
-bool g_pending_call_create(GPendingCall *, const char *, size_t, GScanExpression **, size_t);
+bool g_pending_call_create(GPendingCall *, const sized_string_t *, GScanExpression **, size_t);
diff --git a/src/analysis/scan/exprs/call.c b/src/analysis/scan/exprs/call.c
index 76f5fc3..dde627c 100644
--- a/src/analysis/scan/exprs/call.c
+++ b/src/analysis/scan/exprs/call.c
@@ -24,6 +24,7 @@
#include "call.h"
+#include <assert.h>
#include <malloc.h>
#include <string.h>
@@ -48,19 +49,16 @@ static void g_pending_call_dispose(GPendingCall *);
/* Procède à la libération totale de la mémoire. */
static void g_pending_call_finalize(GPendingCall *);
-/* Définit une base de recherche pour la cible d'appel. */
-static void g_pending_call_set_base(GPendingCall *, GRegisteredItem *);
-
/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
/* Reproduit une expression en place dans une nouvelle instance. */
-static GScanExpression *g_pending_call_duplicate(const GPendingCall *);
+static void g_pending_call_copy(GPendingCall *, const GPendingCall *);
/* Réduit une expression à une forme plus simple. */
-GScanExpression *g_pending_call_reduce(GPendingCall *, GScanContext *, bool);
+static bool g_pending_call_reduce(GPendingCall *, GScanContext *, GScanScope *, GScanExpression **);
@@ -70,7 +68,7 @@ GScanExpression *g_pending_call_reduce(GPendingCall *, GScanContext *, bool);
/* Indique le type défini pour un appel de fonction enregistrée. */
-G_DEFINE_TYPE(GPendingCall, g_pending_call, G_TYPE_SCAN_EXPRESSION);
+G_DEFINE_TYPE(GPendingCall, g_pending_call, G_TYPE_NAMED_ACCESS);
/******************************************************************************
@@ -98,7 +96,7 @@ static void g_pending_call_class_init(GPendingCallClass *klass)
expr = G_SCAN_EXPRESSION_CLASS(klass);
expr->cmp_rich = (compare_expr_rich_fc)NULL;
- expr->dup = (dup_expr_fc)g_pending_call_duplicate;
+ expr->copy = (copy_expr_fc)g_pending_call_copy;
expr->reduce = (reduce_expr_fc)g_pending_call_reduce;
}
@@ -118,14 +116,9 @@ static void g_pending_call_class_init(GPendingCallClass *klass)
static void g_pending_call_init(GPendingCall *call)
{
- call->base = NULL;
- call->target = NULL;
-
call->args = NULL;
call->count = 0;
- call->next = NULL;
-
}
@@ -145,13 +138,9 @@ static void g_pending_call_dispose(GPendingCall *call)
{
size_t i; /* Boucle de parcours */
- g_clear_object(&call->base);
-
for (i = 0; i < call->count; i++)
g_clear_object(&call->args[i]);
- g_clear_object(&call->next);
-
G_OBJECT_CLASS(g_pending_call_parent_class)->dispose(G_OBJECT(call));
}
@@ -171,9 +160,6 @@ static void g_pending_call_dispose(GPendingCall *call)
static void g_pending_call_finalize(GPendingCall *call)
{
- if (call->target != NULL)
- free(call->target);
-
if (call->args != NULL)
free(call->args);
@@ -185,7 +171,6 @@ static void g_pending_call_finalize(GPendingCall *call)
/******************************************************************************
* *
* Paramètres : target = désignation de l'objet d'appel à identifier. *
-* len = taille de cette désignation. *
* args = éventuelle liste d'arguments à actionner. *
* count = quantité de ces arguments. *
* *
@@ -197,13 +182,13 @@ static void g_pending_call_finalize(GPendingCall *call)
* *
******************************************************************************/
-GScanExpression *g_pending_call_new(const char *target, size_t len, GScanExpression **args, size_t count)
+GScanExpression *g_pending_call_new(const sized_string_t *target, GScanExpression **args, size_t count)
{
GScanExpression *result; /* Structure à retourner */
result = g_object_new(G_TYPE_PENDING_CALL, NULL);
- if (!g_pending_call_create(G_PENDING_CALL(result), target, len, args, count))
+ if (!g_pending_call_create(G_PENDING_CALL(result), target, args, count))
g_clear_object(&result);
return result;
@@ -215,7 +200,6 @@ GScanExpression *g_pending_call_new(const char *target, size_t len, GScanExpress
* *
* Paramètres : call = instance à initialiser pleinement. *
* target = désignation de l'objet d'appel à identifier. *
-* len = taille de cette désignation. *
* args = éventuelle liste d'arguments à actionner. *
* count = quantité de ces arguments. *
* *
@@ -227,16 +211,14 @@ GScanExpression *g_pending_call_new(const char *target, size_t len, GScanExpress
* *
******************************************************************************/
-bool g_pending_call_create(GPendingCall *call, const char *target, size_t len, GScanExpression **args, size_t count)
+bool g_pending_call_create(GPendingCall *call, const sized_string_t *target, GScanExpression **args, size_t count)
{
bool result; /* Bilan à retourner */
size_t i; /* Boucle de parcours */
- result = g_scan_expression_create(G_SCAN_EXPRESSION(call), EVT_PENDING);
+ result = g_named_access_create(G_NAMED_ACCESS(call), target);
if (!result) goto exit;
- call->target = strndup(target, len);
-
call->args = malloc(count * sizeof(GScanExpression *));
call->count = count;
@@ -253,48 +235,6 @@ bool g_pending_call_create(GPendingCall *call, const char *target, size_t len, G
}
-/******************************************************************************
-* *
-* Paramètres : call = expression d'appel à actualiser. *
-* base = zone de recherche pour la résolution à venir. *
-* *
-* Description : Définit une base de recherche pour la cible d'appel. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_pending_call_set_base(GPendingCall *call, GRegisteredItem *base)
-{
- call->base = base;
- g_object_ref(G_OBJECT(base));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : call = expression d'appel à compléter. *
-* next = expression d'appel suivante dans la chaîne. *
-* *
-* Description : Complète la chaine d'expressions d'appel. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_pending_call_attach_next(GPendingCall *call, GPendingCall *next)
-{
- call->next = next;
- g_object_ref(G_OBJECT(next));
-
-}
-
-
/* ---------------------------------------------------------------------------------- */
/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
@@ -303,23 +243,31 @@ void g_pending_call_attach_next(GPendingCall *call, GPendingCall *next)
/******************************************************************************
* *
-* Paramètres : expr = expression à copier. *
+* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
+* src = expression source à copier. *
* *
* Description : Reproduit une expression en place dans une nouvelle instance.*
* *
-* Retour : Nouvelle instance d'expression. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static GScanExpression *g_pending_call_duplicate(const GPendingCall *expr)
+static void g_pending_call_copy(GPendingCall *dest, const GPendingCall *src)
{
- GScanExpression *result; /* Instance copiée à retourner */
+ GScanExpressionClass *class; /* Classe parente à solliciter */
+ size_t i; /* Boucle de parcours */
- result = g_pending_call_new(expr->target, strlen(expr->target), expr->args, expr->count);
+ class = G_SCAN_EXPRESSION_CLASS(g_pending_call_parent_class);
- return result;
+ class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
+
+ dest->args = malloc(src->count * sizeof(GScanExpression *));
+ dest->count = src->count;
+
+ for (i = 0; i < src->count; i++)
+ dest->args[i] = g_scan_expression_duplicate(src->args[i]);
}
@@ -328,99 +276,100 @@ static GScanExpression *g_pending_call_duplicate(const GPendingCall *expr)
* *
* Paramètres : expr = expression à consulter. *
* ctx = contexte de suivi de l'analyse courante. *
-* final = indique une ultime conversion dans le cycle en cours.*
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
* *
* Description : Réduit une expression à une forme plus simple. *
* *
-* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
* *
* Remarques : - *
* *
******************************************************************************/
-GScanExpression *g_pending_call_reduce(GPendingCall *expr, GScanContext *ctx, bool final)
+static bool g_pending_call_reduce(GPendingCall *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- GScanExpression *result; /* Instance à renvoyer */
+ bool result; /* Bilan à retourner */
+ GNamedAccess *new; /* Eventuel étage suivant */
+ GPendingCall *new_call; /* Version en appel */
size_t i; /* Boucle de parcours */
- GScanExpression *new; /* Nouvelle expression obtenue */
- bool last; /* Détection de fin de chaîne */
- GRegisteredItem *base; /* Base de recherche courante */
- GRegisteredItem *rebase; /* Nouvelle base résolue */
+ GScanExpression *arg; /* Argument réduit à échanger */
+ GObject *final; /* Expression ou élément ? */
GScanExpression *new_next; /* Nouvelle version du suivant */
- for (i = 0; i < expr->count; i++)
+ result = _g_named_access_reduce(G_NAMED_ACCESS(expr), ctx, scope, out);
+
+ if (result && *out != NULL)
{
- new = g_scan_expression_reduce(expr->args[i], ctx, final);
+ assert(G_IS_NAMED_ACCESS(*out));
- if (new != NULL)
- {
- g_object_unref(G_OBJECT(expr->args[i]));
- expr->args[i] = new;
- }
+ new = G_NAMED_ACCESS(*out);
+ *out = NULL;
- }
+ assert(new->target == NULL);
+ assert(G_IS_PENDING_CALL(new));
+ assert(G_IS_REGISTERED_ITEM(new->resolved));
- last = (expr->next == NULL);
+ new_call = G_PENDING_CALL(new);
- if (!last)
- new_next = g_scan_expression_duplicate(G_SCAN_EXPRESSION(expr->next));
- else
- new_next = NULL;
-
- if (expr->target != NULL)
- {
- if (expr->base != NULL)
+ for (i = 0; i < new_call->count; i++)
{
- base = expr->base;
- g_object_ref(G_OBJECT(base));
- }
- else
- base = G_REGISTERED_ITEM(get_rost_root_namespace());
+ result = g_scan_expression_reduce(new_call->args[i], ctx, scope, &arg);
+ if (!result) goto exit;
- rebase = g_registered_item_resolve(base, expr->target, ctx,
- last ? NULL : expr->args, last ? 0 : expr->count,
- last, final);
+ if (arg != NULL)
+ {
+ g_object_unref(G_OBJECT(new_call->args[i]));
+ new_call->args[i] = arg;
+ }
- g_object_unref(G_OBJECT(base));
- if (rebase == NULL)
- {
- result = NULL;
- goto done;
}
- if (last)
- {
- g_pending_call_set_base(expr, rebase);
+ result = g_registered_item_run_call(new->resolved,
+ new_call->args,
+ new_call->count,
+ ctx, scope, &final);
- free(expr->target);
- expr->target = NULL;
+ if (result && final != NULL)
+ {
+ /**
+ * Si le produit de l'appel à la fonction est une expression d'évaluation
+ * classique, alors ce produit constitue la réduction finale de la chaîne.
+ *
+ * Ce cas de figure ne se rencontre normalement qu'en bout de chaîne.
+ */
+ if (!G_IS_REGISTERED_ITEM(final))
+ {
+ assert(new->next == NULL);
+ *out = G_SCAN_EXPRESSION(final);
+ }
+ else
+ {
+ assert(new->next != NULL);
+
+ new_next = g_scan_expression_duplicate(G_SCAN_EXPRESSION(new->next));
+ assert(G_IS_NAMED_ACCESS(new_next));
+
+ g_named_access_set_base(G_NAMED_ACCESS(new_next), G_REGISTERED_ITEM(final));
+
+ result = g_scan_expression_reduce(new_next, ctx, scope, out);
+
+ if (result && *out == NULL)
+ *out = new_next;
+ else
+ g_object_unref(G_OBJECT(new_next));
+
+ }
}
- else
- g_pending_call_set_base(G_PENDING_CALL(new_next), rebase);
-
- }
- if (last)
- result = g_registered_item_reduce(expr->base, ctx, expr->args, expr->count, final);
+ exit:
- else
- {
- result = g_scan_expression_reduce(new_next, ctx, final);
-
- if (result == NULL)
- {
- g_object_ref(G_OBJECT(new_next));
- result = new_next;
- }
+ g_object_unref(G_OBJECT(new));
}
- done:
-
- g_clear_object(&new_next);
-
return result;
}
diff --git a/src/analysis/scan/exprs/call.h b/src/analysis/scan/exprs/call.h
index b69ca85..c344036 100644
--- a/src/analysis/scan/exprs/call.h
+++ b/src/analysis/scan/exprs/call.h
@@ -26,7 +26,7 @@
#include "../expr.h"
-#include "../item.h"
+#include "../../../common/szstr.h"
@@ -49,10 +49,7 @@ typedef struct _GPendingCallClass GPendingCallClass;
GType g_pending_call_get_type(void);
/* Organise un appel de fonction avec ses arguments. */
-GScanExpression *g_pending_call_new(const char *, size_t, GScanExpression **, size_t);
-
-/* Complète la chaine d'expressions d'appel. */
-void g_pending_call_attach_next(GPendingCall *, GPendingCall *);
+GScanExpression *g_pending_call_new(const sized_string_t *, GScanExpression **, size_t);
diff --git a/src/analysis/scan/exprs/literal-int.h b/src/analysis/scan/exprs/literal-int.h
index d803d30..875b3de 100644
--- a/src/analysis/scan/exprs/literal-int.h
+++ b/src/analysis/scan/exprs/literal-int.h
@@ -46,7 +46,7 @@ struct _GLiteralExpression
{
bool boolean; /* Valeur booléenne */
unsigned long long integer; /* Valeur entière 64 bits */
- char *string; /* Chaîne de caractères */
+ sized_string_t string; /* Chaîne de caractères */
struct
{
char *regex; /* Formulation d'origine */
diff --git a/src/analysis/scan/exprs/literal.c b/src/analysis/scan/exprs/literal.c
index f40747d..119b871 100644
--- a/src/analysis/scan/exprs/literal.c
+++ b/src/analysis/scan/exprs/literal.c
@@ -57,10 +57,10 @@ static void g_literal_expression_finalize(GLiteralExpression *);
static bool g_literal_expression_compare_rich(const GLiteralExpression *, const GLiteralExpression *, RichCmpOperation, bool *);
/* Reproduit une expression en place dans une nouvelle instance. */
-static GScanExpression *g_literal_expression_duplicate(const GLiteralExpression *);
+static void g_literal_expression_copy(GLiteralExpression *, const GLiteralExpression *);
/* Réduit une expression à une forme plus simple. */
-GScanExpression *g_literal_expression_reduce(GLiteralExpression *, GScanContext *, bool);
+static bool g_literal_expression_reduce(GLiteralExpression *, GScanContext *, GScanScope *, GScanExpression **);
@@ -98,7 +98,7 @@ static void g_literal_expression_class_init(GLiteralExpressionClass *klass)
expr = G_SCAN_EXPRESSION_CLASS(klass);
expr->cmp_rich = (compare_expr_rich_fc)g_literal_expression_compare_rich;
- expr->dup = (dup_expr_fc)g_literal_expression_duplicate;
+ expr->copy = (copy_expr_fc)g_literal_expression_copy;
expr->reduce = (reduce_expr_fc)g_literal_expression_reduce;
}
@@ -215,7 +215,8 @@ bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype,
va_list ap; /* Liste d'arguements */
const bool *boolean; /* Valeur booléenne */
const unsigned long long *integer; /* Valeur entière 64 bits */
- const char *string; /* Chaîne de caractères */
+ 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 */
int cflags; /* Détails de compilation */
unsigned int i; /* Boucle de parcours */
@@ -241,15 +242,15 @@ bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype,
break;
case EVT_STRING:
- string = va_arg(ap, const char *);
- expr->value.string = strdup(string);
+ string = va_arg(ap, const sized_string_t *);
+ szstrdup(&expr->value.string, string);
break;
case EVT_REG_EXPR:
- string = va_arg(ap, const char *);
- len = strlen(string);
+ raw = va_arg(ap, const char *);
+ len = strlen(raw);
- result = (len > 2 && string[0] == '/');
+ result = (len > 2 && raw[0] == '/');
cflags = REG_EXTENDED | REG_NOSUB;
@@ -257,38 +258,38 @@ bool g_literal_expression_create(GLiteralExpression *expr, ExprValueType vtype,
{
result = (len > 2);
- if (string[len - 1] == 'i')
+ if (raw[len - 1] == 'i')
{
cflags |= REG_ICASE;
len -= 1;
}
- else if (string[len - 1] == 's')
+ else if (raw[len - 1] == 's')
{
cflags |= REG_NEWLINE;
len -= 1;
}
- else if (string[len - 1] == '/')
+ else if (raw[len - 1] == '/')
break;
}
if (result)
- result = (string[len - 1] == '/');
+ result = (raw[len - 1] == '/');
if (result)
{
assert(len > 2);
- tmp = strndup(&string[1], len - 2);
+ tmp = strndup(&raw[1], len - 2);
ret = regcomp(&expr->value.preg, tmp, cflags);
free(tmp);
result = (ret == 0);
if (result)
- expr->value.regex = strdup(string);
+ expr->value.regex = strdup(raw);
}
@@ -378,14 +379,14 @@ bool g_literal_expression_get_integer_value(const GLiteralExpression *item, unsi
* *
******************************************************************************/
-bool g_literal_expression_get_string_value(const GLiteralExpression *item, const char **value)
+bool g_literal_expression_get_string_value(const GLiteralExpression *item, const sized_string_t **value)
{
bool result; /* Etat à retourner */
result = (item->value_type == EVT_STRING);
if (result)
- *value = item->value.string;
+ *value = &item->value.string;
return result;
@@ -445,10 +446,12 @@ static bool g_literal_expression_compare_rich(const GLiteralExpression *item, co
bool result; /* Etat à retourner */
int cmp; /* Bilan intermédiaire */
+ result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_LITERAL_EXPRESSION);
+ if (!result) goto done;
+
if (item->value_type != other->value_type)
{
*status = compare_rich_integer_values(item->value_type, other->value_type, op);
- result = true;
goto done;
}
@@ -480,7 +483,7 @@ static bool g_literal_expression_compare_rich(const GLiteralExpression *item, co
break;
case EVT_STRING:
- cmp = strcmp(item->value.string, other->value.string);
+ cmp = szstrcmp(&item->value.string, &other->value.string);
*status = compare_rich_integer_values(cmp, 0, op);
result = true;
break;
@@ -506,51 +509,51 @@ static bool g_literal_expression_compare_rich(const GLiteralExpression *item, co
/******************************************************************************
* *
-* Paramètres : expr = expression à copier. *
+* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
+* src = expression source à copier. *
* *
* Description : Reproduit une expression en place dans une nouvelle instance.*
* *
-* Retour : Nouvelle instance d'expression. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static GScanExpression *g_literal_expression_duplicate(const GLiteralExpression *expr)
+static void g_literal_expression_copy(GLiteralExpression *dest, const GLiteralExpression *src)
{
- GScanExpression *result; /* Instance copiée à retourner */
- const void *ptr; /* Pointeur vers des données */
+ 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));
- switch (expr->value_type)
+ dest->value_type = src->value_type;
+
+ switch (src->value_type)
{
case EVT_BOOLEAN:
- ptr = &expr->value.boolean;
+ dest->value.boolean = src->value.boolean;
break;
case EVT_INTEGER:
- ptr = &expr->value.integer;
+ dest->value.integer = src->value.integer;
break;
case EVT_STRING:
- ptr = &expr->value.string;
+ szstrdup(&dest->value.string, &src->value.string);
break;
case EVT_REG_EXPR:
- ptr = &expr->value.regex;
+ /*ptr = &expr->value.regex*//* FIXME */;
break;
default:
- ptr = NULL;
+ assert(false);
break;
}
- assert(ptr != NULL);
-
- result = g_literal_expression_new(expr->value_type, ptr);
-
- return result;
-
}
@@ -558,47 +561,25 @@ static GScanExpression *g_literal_expression_duplicate(const GLiteralExpression
* *
* Paramètres : expr = expression à consulter. *
* ctx = contexte de suivi de l'analyse courante. *
-* force = impose une conversion en booléen si possible. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
* *
* Description : Réduit une expression à une forme plus simple. *
* *
-* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
* *
* Remarques : - *
* *
******************************************************************************/
-GScanExpression *g_literal_expression_reduce(GLiteralExpression *expr, GScanContext *ctx, bool force)
+static bool g_literal_expression_reduce(GLiteralExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- GScanExpression *result; /* Instance à renvoyer */
-
- if (!force)
- result = NULL;
-
- else
- switch (expr->value_type)
- {
- case EVT_BOOLEAN:
- result = NULL;
- break;
-
- case EVT_INTEGER:
- result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { expr->value.integer > 0 });
- break;
-
- case EVT_STRING:
- result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { strlen(expr->value.string) > 0 });
- break;
-
- case EVT_REG_EXPR:
- result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { strlen(expr->value.regex) > 0 });
- break;
+ bool result; /* Bilan à retourner */
- default:
- result = NULL;
- break;
+ result = true;
- }
+ *out = G_SCAN_EXPRESSION(expr);
+ g_object_ref(G_OBJECT(expr));
return result;
diff --git a/src/analysis/scan/exprs/literal.h b/src/analysis/scan/exprs/literal.h
index ac5724f..7120c07 100644
--- a/src/analysis/scan/exprs/literal.h
+++ b/src/analysis/scan/exprs/literal.h
@@ -29,6 +29,7 @@
#include "../expr.h"
+#include "../../../common/szstr.h"
@@ -60,7 +61,7 @@ bool g_literal_expression_get_boolean_value(const GLiteralExpression *, bool *);
bool g_literal_expression_get_integer_value(const GLiteralExpression *, unsigned long long *);
/* Indique la valeur portée par une expression de chaîne. */
-bool g_literal_expression_get_string_value(const GLiteralExpression *, const char **);
+bool g_literal_expression_get_string_value(const GLiteralExpression *, const sized_string_t **);
/* Indique la valeur portée par une expression rationnelle. */
bool g_literal_expression_get_regex_value(const GLiteralExpression *, const regex_t **);
diff --git a/src/analysis/scan/exprs/relop-int.h b/src/analysis/scan/exprs/relop-int.h
index 273b543..3adbcf0 100644
--- a/src/analysis/scan/exprs/relop-int.h
+++ b/src/analysis/scan/exprs/relop-int.h
@@ -39,8 +39,8 @@ struct _GRelOperation
RichCmpOperation rel_type; /* Type de relation étudiée */
- GScanExpression *first; /* Expression impactée #1 */
- GScanExpression *second; /* Expression impactée #2 */
+ GScanExpression *left; /* Expression impactée #1 */
+ GScanExpression *right; /* Expression impactée #2 */
};
diff --git a/src/analysis/scan/exprs/relop.c b/src/analysis/scan/exprs/relop.c
index 94ce77d..7dc6864 100644
--- a/src/analysis/scan/exprs/relop.c
+++ b/src/analysis/scan/exprs/relop.c
@@ -52,11 +52,11 @@ static void g_relational_operation_finalize(GRelOperation *);
/* Réalise une comparaison entre objets selon un critère précis. */
static bool g_relational_operation_compare_rich(const GRelOperation *, const GRelOperation *, RichCmpOperation, bool *);
-/* Initialise une instance d'opération de relation. */
-static GScanExpression *g_relational_operation_duplicate(const GRelOperation *);
+/* Reproduit une expression en place dans une nouvelle instance. */
+static void g_relational_operation_copy(GRelOperation *, const GRelOperation *);
/* Réduit une expression à une forme plus simple. */
-GScanExpression *g_relational_operation_reduce(GRelOperation *, GScanContext *, bool);
+static bool g_relational_operation_reduce(GRelOperation *, GScanContext *, GScanScope *, GScanExpression **);
@@ -94,7 +94,7 @@ static void g_relational_operation_class_init(GRelOperationClass *klass)
expr = G_SCAN_EXPRESSION_CLASS(klass);
expr->cmp_rich = (compare_expr_rich_fc)g_relational_operation_compare_rich;
- expr->dup = (dup_expr_fc)g_relational_operation_duplicate;
+ expr->copy = (copy_expr_fc)g_relational_operation_copy;
expr->reduce = (reduce_expr_fc)g_relational_operation_reduce;
}
@@ -114,8 +114,8 @@ static void g_relational_operation_class_init(GRelOperationClass *klass)
static void g_relational_operation_init(GRelOperation *op)
{
- op->first = NULL;
- op->second = NULL;
+ op->left = NULL;
+ op->right = NULL;
}
@@ -134,8 +134,8 @@ static void g_relational_operation_init(GRelOperation *op)
static void g_relational_operation_dispose(GRelOperation *op)
{
- g_clear_object(&op->first);
- g_clear_object(&op->second);
+ g_clear_object(&op->left);
+ g_clear_object(&op->right);
G_OBJECT_CLASS(g_relational_operation_parent_class)->dispose(G_OBJECT(op));
@@ -163,9 +163,9 @@ static void g_relational_operation_finalize(GRelOperation *op)
/******************************************************************************
* *
-* Paramètres : type = type d'opération booléenne à représenter. *
-* first = premier opérande concerné. *
-* second = éventuel second opérande impliqué ou NULL. *
+* Paramètres : type = type d'opération booléenne à représenter. *
+* left = premier opérande concerné. *
+* right = éventuel second opérande impliqué ou NULL. *
* *
* Description : Organise une opération relationnelle entre expressions. *
* *
@@ -175,13 +175,13 @@ static void g_relational_operation_finalize(GRelOperation *op)
* *
******************************************************************************/
-GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpression *first, GScanExpression *second)
+GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpression *left, GScanExpression *right)
{
GScanExpression *result; /* Structure à retourner */
result = g_object_new(G_TYPE_RELATIONAL_OPERATION, NULL);
- if (!g_relational_operation_create(G_RELATIONAL_OPERATION(result), type, first, second))
+ if (!g_relational_operation_create(G_RELATIONAL_OPERATION(result), type, left, right))
g_clear_object(&result);
return result;
@@ -191,10 +191,10 @@ GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpressi
/******************************************************************************
* *
-* Paramètres : op = instance à initialiser pleinement. *
-* type = type d'opération booléenne à représenter. *
-* first = premier opérande concerné. *
-* second = éventuel second opérande impliqué ou NULL. *
+* Paramètres : op = instance à initialiser pleinement. *
+* type = type d'opération booléenne à représenter. *
+* left = premier opérande concerné. *
+* right = éventuel second opérande impliqué ou NULL. *
* *
* Description : Met en place une opération relationnelle entre expressions. *
* *
@@ -204,13 +204,13 @@ GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpressi
* *
******************************************************************************/
-bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GScanExpression *first, GScanExpression *second)
+bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GScanExpression *left, GScanExpression *right)
{
bool result; /* Bilan à retourner */
result = false;
- if (g_scan_expression_get_value_type(first) != g_scan_expression_get_value_type(first))
+ if (g_scan_expression_get_value_type(left) != g_scan_expression_get_value_type(left))
goto exit;
if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_BOOLEAN))
@@ -218,11 +218,11 @@ bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GSc
op->rel_type = type;
- op->first = first;
- g_object_ref(G_OBJECT(op->first));
+ op->left = left;
+ g_object_ref(G_OBJECT(op->left));
- op->second = second;
- g_object_ref(G_OBJECT(op->second));
+ op->right = right;
+ g_object_ref(G_OBJECT(op->right));
result = true;
@@ -257,28 +257,26 @@ bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GSc
static bool g_relational_operation_compare_rich(const GRelOperation *item, const GRelOperation *other, RichCmpOperation op, bool *status)
{
bool result; /* Etat à retourner */
- bool equal; /* Bilan intermédiaire */
- result = true; // TODO : cmp parent()->type
+ result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_RELATIONAL_OPERATION);
+ if (!result) goto done;
if (item->rel_type != other->rel_type)
{
- result = compare_rich_integer_values(item->rel_type, other->rel_type, op);
+ *status = compare_rich_integer_values(item->rel_type, other->rel_type, op);
goto done;
}
- equal = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status);
+ if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
- if (!equal)
- {
- result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first),
- G_COMPARABLE_ITEM(other->first),
- op, status);
- goto done;
- }
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->left),
+ G_COMPARABLE_ITEM(other->left),
+ op, status);
+ if (!result || STATUS_NOT_EQUAL(*status, op)) goto done;
- result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second),
- G_COMPARABLE_ITEM(other->second),
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->right),
+ G_COMPARABLE_ITEM(other->right),
op, status);
done:
@@ -290,23 +288,29 @@ static bool g_relational_operation_compare_rich(const GRelOperation *item, const
/******************************************************************************
* *
-* Paramètres : expr = expression à copier. *
+* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
+* src = expression source à copier. *
* *
* Description : Reproduit une expression en place dans une nouvelle instance.*
* *
-* Retour : Nouvelle instance d'expression. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static GScanExpression *g_relational_operation_duplicate(const GRelOperation *expr)
+static void g_relational_operation_copy(GRelOperation *dest, const GRelOperation *src)
{
- GScanExpression *result; /* Instance copiée à retourner */
+ GScanExpressionClass *class; /* Classe parente à solliciter */
- result = g_relational_operation_new(expr->rel_type, expr->first, expr->second);
+ class = G_SCAN_EXPRESSION_CLASS(g_relational_operation_parent_class);
- return result;
+ class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
+
+ dest->rel_type = src->rel_type;
+
+ dest->left = g_scan_expression_duplicate(src->left);
+ dest->right = g_scan_expression_duplicate(src->right);
}
@@ -315,60 +319,74 @@ static GScanExpression *g_relational_operation_duplicate(const GRelOperation *ex
* *
* Paramètres : expr = expression à consulter. *
* ctx = contexte de suivi de l'analyse courante. *
-* final = impose une conversion finale de dernier tour. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
* *
* Description : Réduit une expression à une forme plus simple. *
* *
-* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
* *
* Remarques : - *
* *
******************************************************************************/
-GScanExpression *g_relational_operation_reduce(GRelOperation *expr, GScanContext *ctx, bool final)
+static bool g_relational_operation_reduce(GRelOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- GScanExpression *result; /* Instance à renvoyer */
- GScanExpression *new; /* Nouvelle expression obtenue */
+ bool result; /* Bilan à retourner */
+ GScanExpression *new_left; /* Expression réduite (gauche) */
+ GScanExpression *new_right; /* Expression réduite (droite) */
bool status; /* Bilan d'une comparaison */
bool valid; /* Validité de ce bilan obtenu */
- result = NULL;
-
/* Réduction des éléments considérés */
- new = g_scan_expression_reduce(expr->first, ctx, final);
+ new_left = NULL;
+ new_right = NULL;
- if (new != NULL)
- {
- g_object_unref(G_OBJECT(expr->first));
- expr->first = new;
- }
+ result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
+ if (!result) goto exit;
+
+ result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
+ if (!result) goto exit;
+
+ /* Construction d'une réduction locale ? */
- if (expr->second != NULL)
+ if (G_IS_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right))
{
- new = g_scan_expression_reduce(expr->second, ctx, final);
+ valid = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(new_left),
+ G_COMPARABLE_ITEM(new_right),
+ expr->rel_type, &status);
- if (new != NULL)
- {
- g_object_unref(G_OBJECT(expr->second));
- expr->second = new;
- }
+ if (valid)
+ *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { status });
}
- /* Construction d'une réduction locale ? */
+ /* Mise à jour de la progression ? */
- if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second))
+ else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right))
{
- valid = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(expr->first),
- G_COMPARABLE_ITEM(expr->second),
- expr->rel_type, &status);
+ if (new_left == NULL)
+ {
+ new_left = expr->left;
+ g_object_ref(G_OBJECT(new_left));
+ }
- if (valid)
- result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { status });
+ if (new_right == NULL)
+ {
+ new_right = expr->right;
+ g_object_ref(G_OBJECT(new_right));
+ }
+
+ *out = g_relational_operation_new(expr->rel_type, new_left, new_right);
}
+ exit:
+
+ g_clear_object(&new_left);
+ g_clear_object(&new_right);
+
return result;
}
diff --git a/src/analysis/scan/exprs/str-int.h b/src/analysis/scan/exprs/strop-int.h
index 9bed5cf..234ae8f 100644
--- a/src/analysis/scan/exprs/str-int.h
+++ b/src/analysis/scan/exprs/strop-int.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * str-int.h - prototypes internes pour la gestion des opérations booléennes
+ * strop-int.h - prototypes internes pour la gestion des opérations booléennes
*
* Copyright (C) 2022 Cyrille Bagard
*
@@ -21,14 +21,15 @@
*/
-#ifndef _ANALYSIS_SCAN_EXPRS_STR_INT_H
-#define _ANALYSIS_SCAN_EXPRS_STR_INT_H
+#ifndef _ANALYSIS_SCAN_EXPRS_STROP_INT_H
+#define _ANALYSIS_SCAN_EXPRS_STROP_INT_H
-#include "str.h"
+#include "strop.h"
#include "../expr-int.h"
+#include "../../../common/extstr.h"
@@ -40,8 +41,8 @@ struct _GStringOperation
StringOperationType type; /* Type d'opération menée */
bool case_sensitive; /* Respect de la casse ? */
- GScanExpression *first; /* Expression impactée #1 */
- GScanExpression *second; /* Expression impactée #2 */
+ GScanExpression *left; /* Expression impactée #1 */
+ GScanExpression *right; /* Expression impactée #2 */
};
@@ -58,4 +59,4 @@ bool g_string_operation_create(GStringOperation *, StringOperationType, GScanExp
-#endif /* _ANALYSIS_SCAN_EXPRS_STR_INT_H */
+#endif /* _ANALYSIS_SCAN_EXPRS_STROP_INT_H */
diff --git a/src/analysis/scan/exprs/str.c b/src/analysis/scan/exprs/strop.c
index 675b2f6..145e8da 100644
--- a/src/analysis/scan/exprs/str.c
+++ b/src/analysis/scan/exprs/strop.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * str.c - gestion des opérations booléennes
+ * strop.c - gestion des opérations booléennes
*
* Copyright (C) 2022 Cyrille Bagard
*
@@ -21,7 +21,7 @@
*/
-#include "str.h"
+#include "strop.h"
#include <assert.h>
@@ -29,7 +29,7 @@
#include <strings.h>
-#include "str-int.h"
+#include "strop-int.h"
#include "literal.h"
@@ -55,10 +55,10 @@ static void g_string_operation_finalize(GStringOperation *);
/* Reproduit une expression en place dans une nouvelle instance. */
-static GScanExpression *g_string_operation_duplicate(const GStringOperation *);
+static void g_string_operation_copy(GStringOperation *, const GStringOperation *);
/* Réduit une expression à une forme plus simple. */
-GScanExpression *g_string_operation_reduce(GStringOperation *, GScanContext *, bool);
+static bool g_string_operation_reduce(GStringOperation *, GScanContext *, GScanScope *, GScanExpression **);
@@ -96,7 +96,7 @@ static void g_string_operation_class_init(GStringOperationClass *klass)
expr = G_SCAN_EXPRESSION_CLASS(klass);
expr->cmp_rich = (compare_expr_rich_fc)NULL;
- expr->dup = (dup_expr_fc)g_string_operation_duplicate;
+ expr->copy = (copy_expr_fc)g_string_operation_copy;
expr->reduce = (reduce_expr_fc)g_string_operation_reduce;
}
@@ -116,8 +116,8 @@ static void g_string_operation_class_init(GStringOperationClass *klass)
static void g_string_operation_init(GStringOperation *op)
{
- op->first = NULL;
- op->second = NULL;
+ op->left = NULL;
+ op->right = NULL;
}
@@ -136,8 +136,8 @@ static void g_string_operation_init(GStringOperation *op)
static void g_string_operation_dispose(GStringOperation *op)
{
- g_clear_object(&op->first);
- g_clear_object(&op->second);
+ g_clear_object(&op->left);
+ g_clear_object(&op->right);
G_OBJECT_CLASS(g_string_operation_parent_class)->dispose(G_OBJECT(op));
@@ -196,9 +196,9 @@ GScanExpression *g_string_operation_new(StringOperationType type, GScanExpressio
* *
* Paramètres : op = instance à initialiser pleinement. *
* type = type d'opération booléenne à représenter. *
-* first = premier opérande concerné. *
-* second = éventuel second opérande impliqué ou NULL. *
-* sensitive = détermine la prise en compte de la casse. *
+* left = premier opérande concerné. *
+* right = éventuel second opérande impliqué ou NULL. *
+* sensitive = détermine la prise en compte de la casse. *
* *
* Description : Met en place une expression d'opération traite une chaîne. *
* *
@@ -208,19 +208,19 @@ GScanExpression *g_string_operation_new(StringOperationType type, GScanExpressio
* *
******************************************************************************/
-bool g_string_operation_create(GStringOperation *op, StringOperationType type, GScanExpression *first, GScanExpression *second, bool sensitive)
+bool g_string_operation_create(GStringOperation *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(first);
+ vtype = g_scan_expression_get_value_type(left);
if (vtype != EVT_STRING && vtype != EVT_PENDING)
goto exit;
- vtype = g_scan_expression_get_value_type(second);
+ vtype = g_scan_expression_get_value_type(right);
if (vtype != EVT_STRING && vtype != EVT_REG_EXPR && vtype != EVT_PENDING)
goto exit;
@@ -245,11 +245,11 @@ bool g_string_operation_create(GStringOperation *op, StringOperationType type, G
}
- op->first = first;
- g_object_ref(G_OBJECT(op->first));
+ op->left = left;
+ g_object_ref(G_OBJECT(op->left));
- op->second = second;
- g_object_ref(G_OBJECT(op->second));
+ op->right = right;
+ g_object_ref(G_OBJECT(op->right));
result = true;
@@ -268,170 +268,202 @@ bool g_string_operation_create(GStringOperation *op, StringOperationType type, G
/******************************************************************************
* *
-* Paramètres : op = expression à copier. *
+* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
+* src = expression source à copier. *
* *
* Description : Reproduit une expression en place dans une nouvelle instance.*
* *
-* Retour : Nouvelle instance d'expression. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static GScanExpression *g_string_operation_duplicate(const GStringOperation *op)
+static void g_string_operation_copy(GStringOperation *dest, const GStringOperation *src)
{
- GScanExpression *result; /* Instance copiée à retourner */
+ GScanExpressionClass *class; /* Classe parente à solliciter */
- result = g_string_operation_new(op->type, op->first, op->second, op->case_sensitive);
+ class = G_SCAN_EXPRESSION_CLASS(g_string_operation_parent_class);
- return result;
+ 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 : op = expression à consulter. *
+* Paramètres : expr = expression à consulter. *
* ctx = contexte de suivi de l'analyse courante. *
-* final = impose une conversion finale de dernier tour. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
* *
* Description : Réduit une expression à une forme plus simple. *
* *
-* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
* *
* Remarques : - *
* *
******************************************************************************/
-GScanExpression *g_string_operation_reduce(GStringOperation *op, GScanContext *ctx, bool final)
+static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- GScanExpression *result; /* Instance à renvoyer */
- GScanExpression *new; /* Nouvelle expression obtenue */
- const char *strings[2]; /* Chaînes en jeu */
- bool status; /* Bilan intermédiaire */
- char *found; /* Eventuelle portion trouvée */
- size_t len[2]; /* Tailles max. de comparaison */
- int ret; /* Bilan de comparaison */
+ bool result; /* Bilan à 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 */
+ const sized_string_t *strings[2]; /* Chaînes en jeu */
+ const void *found; /* Présence d'une bribe ? */
+ bool status; /* Bilan de comparaison #1 */
+ size_t offset; /* Point de départ d'analyse */
const regex_t *preg; /* Expression rationnelle */
-
- result = NULL;
+ int ret; /* Bilan de comparaison #2 */
/* Réduction des éléments considérés */
- new = g_scan_expression_reduce(op->first, ctx, final);
+ new_left = NULL;
+ new_right = NULL;
- if (new != NULL)
- {
- g_object_unref(G_OBJECT(op->first));
- op->first = new;
- }
+ result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
+ if (!result) goto exit;
- new = g_scan_expression_reduce(op->second, ctx, final);
-
- if (new != NULL)
- {
- g_object_unref(G_OBJECT(op->second));
- op->second = new;
- }
+ result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
+ if (!result) goto exit;
/* Construction d'une réduction locale ? */
- if (!G_IS_LITERAL_EXPRESSION(op->first))
- goto exit;
+ if (G_IS_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right))
+ {
+ op_left = G_LITERAL_EXPRESSION(new_left);
+ op_right = G_LITERAL_EXPRESSION(new_right);
- if (!G_IS_LITERAL_EXPRESSION(op->second))
- goto exit;
+ result = g_literal_expression_get_string_value(op_left, &strings[0]);
+ if (!result) goto exit;
- status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->first), &strings[0]);
- if (!status) goto exit;
+ switch (expr->type)
+ {
+ case SOT_CONTAINS:
- switch (op->type)
- {
- case SOT_CONTAINS:
+ result = g_literal_expression_get_string_value(op_right, &strings[1]);
+ if (!result) goto exit;
- status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->second), &strings[1]);
- if (!status) goto exit;
+ if (expr->case_sensitive)
+ found = memmem(strings[0]->data, strings[0]->len, strings[1]->data, strings[1]->len);
- if (op->case_sensitive)
- found = strstr(strings[0], strings[1]);
- else
- found = strcasestr(strings[0], strings[1]);
+ 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 });
- break;
+ result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { found != NULL });
+ break;
- case SOT_STARTSWITH:
+ case SOT_STARTSWITH:
- status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->second), &strings[1]);
- if (!status) goto exit;
+ result = g_literal_expression_get_string_value(op_right, &strings[1]);
+ if (!result) goto exit;
- len[1] = strlen(strings[1]);
+ if (strings[0]->len < strings[1]->len)
+ status = false;
- if (op->case_sensitive)
- ret = strncmp(strings[0], strings[1], len[1]);
- else
- ret = strncasecmp(strings[0], strings[1], len[1]);
+ else
+ {
+ if (expr->case_sensitive)
+ ret = memcmp(strings[0]->data, strings[1]->data, strings[1]->len);
+ else
+ ret = memcasecmp(strings[0]->data, strings[1]->data, strings[1]->len);
- result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret == 0 });
- break;
+ status = (ret == 0);
- case SOT_ENDSWITH:
+ }
- len[0] = strlen(strings[0]);
+ result = g_literal_expression_new(EVT_BOOLEAN, &status);
+ break;
- status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->second), &strings[1]);
- if (!status) goto exit;
+ case SOT_ENDSWITH:
- len[1] = strlen(strings[1]);
+ result = g_literal_expression_get_string_value(op_right, &strings[1]);
+ if (!result) goto exit;
- if (len[0] < len[1])
- result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false });
+ if (strings[0]->len < strings[1]->len)
+ status = false;
- else
- {
- if (op->case_sensitive)
- ret = strncmp(strings[0] + (len[0] - len[1]), strings[1], len[1]);
else
- ret = strncasecmp(strings[0] + (len[0] - len[1]), strings[1], len[1]);
+ {
+ offset = strings[0]->len - strings[1]->len;
- result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret == 0 });
+ if (expr->case_sensitive)
+ ret = memcmp(strings[0]->data + offset, strings[1]->data, strings[1]->len);
+ else
+ ret = memcasecmp(strings[0]->data + offset, strings[1]->data, strings[1]->len);
- }
- break;
+ status = (ret == 0);
- case SOT_MATCHES:
+ }
- status = g_literal_expression_get_regex_value(G_LITERAL_EXPRESSION(op->second), &preg);
- if (!status) goto exit;
+ result = g_literal_expression_new(EVT_BOOLEAN, &status);
+ break;
- ret = regexec(preg, strings[0], 0, NULL, 0);
+ case SOT_MATCHES:
- result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret != REG_NOMATCH });
- break;
+ result = g_literal_expression_get_regex_value(op_right, &preg);
+ if (!result) goto exit;
- case SOT_IEQUALS:
+ ret = regexec(preg, strings[0]->data, 0, NULL, 0);
- len[0] = strlen(strings[0]);
+ *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret != REG_NOMATCH });
+ break;
- status = g_literal_expression_get_string_value(G_LITERAL_EXPRESSION(op->second), &strings[1]);
- if (!status) goto exit;
+ case SOT_IEQUALS:
- len[1] = strlen(strings[1]);
+ result = g_literal_expression_get_string_value(op_right, &strings[1]);
+ if (!result) goto exit;
- if (len[0] != len[1])
- result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false });
+ if (strings[0]->len != strings[1]->len)
+ status = false;
- else
- {
- ret = strcasecmp(strings[0], strings[1]);
- result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret == 0 });
- }
- break;
+ else
+ {
+ ret = memcasecmp(strings[0]->data, strings[1]->data, strings[1]->len);
+ status = (ret == 0);
+ }
+
+ result = g_literal_expression_new(EVT_BOOLEAN, &status);
+ break;
+
+ }
+
+ }
+
+ /* Mise à jour de la progression ? */
+
+ else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right))
+ {
+ if (new_left == NULL)
+ {
+ new_left = expr->left;
+ g_object_ref(G_OBJECT(new_left));
+ }
+
+ if (new_right == NULL)
+ {
+ new_right = expr->right;
+ g_object_ref(G_OBJECT(new_right));
+ }
+
+ *out = g_string_operation_new(expr->type, new_left, new_right, expr->case_sensitive);
}
exit:
+ g_clear_object(&new_left);
+ g_clear_object(&new_right);
+
return result;
}
diff --git a/src/analysis/scan/exprs/str.h b/src/analysis/scan/exprs/strop.h
index 195f941..c7c0813 100644
--- a/src/analysis/scan/exprs/str.h
+++ b/src/analysis/scan/exprs/strop.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * str.h - prototypes pour la gestion des opérations booléennes
+ * strop.h - prototypes pour la gestion des opérations booléennes
*
* Copyright (C) 2022 Cyrille Bagard
*
@@ -21,8 +21,8 @@
*/
-#ifndef _ANALYSIS_SCAN_EXPRS_STR_H
-#define _ANALYSIS_SCAN_EXPRS_STR_H
+#ifndef _ANALYSIS_SCAN_EXPRS_STROP_H
+#define _ANALYSIS_SCAN_EXPRS_STROP_H
#include "../expr.h"
@@ -64,4 +64,4 @@ GScanExpression *g_string_operation_new(StringOperationType, GScanExpression *,
-#endif /* _ANALYSIS_SCAN_EXPRS_STR_H */
+#endif /* _ANALYSIS_SCAN_EXPRS_STROP_H */