summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac41
-rw-r--r--plugins/kaitai/parsers/enum.c2
-rw-r--r--plugins/kaitai/parsers/struct.c2
-rw-r--r--plugins/pychrysalide/analysis/scan/scanner.c46
-rw-r--r--src/Makefile.am6
-rw-r--r--src/analysis/scan/context-int.h20
-rw-r--r--src/analysis/scan/context.c325
-rw-r--r--src/analysis/scan/context.h8
-rw-r--r--src/analysis/scan/core.c96
-rw-r--r--src/analysis/scan/expr-int.h28
-rw-r--r--src/analysis/scan/expr.c354
-rw-r--r--src/analysis/scan/expr.h27
-rw-r--r--src/analysis/scan/exprs/Makefile.am20
-rw-r--r--src/analysis/scan/exprs/access-int.h17
-rw-r--r--src/analysis/scan/exprs/access.c269
-rw-r--r--src/analysis/scan/exprs/access.h27
-rw-r--r--src/analysis/scan/exprs/arithmetic-int.h (renamed from src/analysis/scan/exprs/arithmop-int.h)18
-rw-r--r--src/analysis/scan/exprs/arithmetic.c638
-rw-r--r--src/analysis/scan/exprs/arithmetic.h (renamed from src/analysis/scan/exprs/arithmop.h)30
-rw-r--r--src/analysis/scan/exprs/call-int.h12
-rw-r--r--src/analysis/scan/exprs/call.c280
-rw-r--r--src/analysis/scan/exprs/call.h22
-rw-r--r--src/analysis/scan/exprs/counter-int.h57
-rw-r--r--src/analysis/scan/exprs/counter.c248
-rw-r--r--src/analysis/scan/exprs/counter.h59
-rw-r--r--src/analysis/scan/exprs/intersect-int.h58
-rw-r--r--src/analysis/scan/exprs/intersect.c290
-rw-r--r--src/analysis/scan/exprs/intersect.h55
-rw-r--r--src/analysis/scan/exprs/literal-int.h16
-rw-r--r--src/analysis/scan/exprs/literal.c363
-rw-r--r--src/analysis/scan/exprs/literal.h49
-rw-r--r--src/analysis/scan/exprs/logical-int.h (renamed from src/analysis/scan/exprs/boolop-int.h)18
-rw-r--r--src/analysis/scan/exprs/logical.c (renamed from src/analysis/scan/exprs/boolop.c)257
-rw-r--r--src/analysis/scan/exprs/logical.h (renamed from src/analysis/scan/exprs/boolop.h)26
-rw-r--r--src/analysis/scan/exprs/range-int.h58
-rw-r--r--src/analysis/scan/exprs/range.c352
-rw-r--r--src/analysis/scan/exprs/range.h55
-rw-r--r--src/analysis/scan/exprs/relational-int.h (renamed from src/analysis/scan/exprs/relop-int.h)18
-rw-r--r--src/analysis/scan/exprs/relational.c (renamed from src/analysis/scan/exprs/relop.c)200
-rw-r--r--src/analysis/scan/exprs/relational.h56
-rw-r--r--src/analysis/scan/exprs/relop.h56
-rw-r--r--src/analysis/scan/exprs/set-int.h54
-rw-r--r--src/analysis/scan/exprs/set.c (renamed from src/analysis/scan/exprs/arithmop.c)355
-rw-r--r--src/analysis/scan/exprs/set.h58
-rw-r--r--src/analysis/scan/exprs/strop-int.h8
-rw-r--r--src/analysis/scan/exprs/strop.c207
-rw-r--r--src/analysis/scan/exprs/strop.h22
-rw-r--r--src/analysis/scan/grammar.y394
-rw-r--r--src/analysis/scan/items/Makefile.am18
-rw-r--r--src/analysis/scan/items/console/Makefile.am13
-rw-r--r--src/analysis/scan/items/console/log.c303
-rw-r--r--src/analysis/scan/items/console/log.h58
-rw-r--r--src/analysis/scan/items/count.c244
-rw-r--r--src/analysis/scan/items/count.h58
-rw-r--r--src/analysis/scan/items/datasize.c56
-rw-r--r--src/analysis/scan/items/datasize.h22
-rw-r--r--src/analysis/scan/items/magic/Makefile.am16
-rw-r--r--src/analysis/scan/items/magic/cookie.c122
-rw-r--r--src/analysis/scan/items/magic/cookie.h44
-rw-r--r--src/analysis/scan/items/magic/mime-encoding.c270
-rw-r--r--src/analysis/scan/items/magic/mime-encoding.h58
-rw-r--r--src/analysis/scan/items/magic/mime-type.c270
-rw-r--r--src/analysis/scan/items/magic/mime-type.h58
-rw-r--r--src/analysis/scan/items/magic/type.c270
-rw-r--r--src/analysis/scan/items/magic/type.h58
-rw-r--r--src/analysis/scan/items/time/Makefile.am14
-rw-r--r--src/analysis/scan/items/time/make.c350
-rw-r--r--src/analysis/scan/items/time/make.h58
-rw-r--r--src/analysis/scan/items/time/now.c243
-rw-r--r--src/analysis/scan/items/time/now.h58
-rw-r--r--src/analysis/scan/items/uint-int.h8
-rw-r--r--src/analysis/scan/items/uint.c137
-rw-r--r--src/analysis/scan/items/uint.h23
-rw-r--r--src/analysis/scan/rule-int.h1
-rw-r--r--src/analysis/scan/rule.c28
-rw-r--r--src/analysis/scan/rule.h4
-rw-r--r--src/analysis/scan/scanner-int.h2
-rw-r--r--src/analysis/scan/scanner.c180
-rw-r--r--src/analysis/scan/scanner.h15
-rw-r--r--src/analysis/scan/tokens.l40
-rw-r--r--src/common/szstr.h28
-rw-r--r--src/core/core.c11
-rw-r--r--src/glibext/comparison-int.h5
-rw-r--r--src/glibext/comparison.c58
-rw-r--r--src/rost.c22
-rw-r--r--tests/analysis/scan/booleans.py98
-rw-r--r--tests/analysis/scan/common.py52
-rw-r--r--tests/analysis/scan/examples.py70
-rw-r--r--tests/analysis/scan/expr.py169
-rw-r--r--tests/analysis/scan/exprs.py122
-rw-r--r--tests/analysis/scan/func.py16
-rw-r--r--tests/analysis/scan/functions.py104
-rw-r--r--tests/analysis/scan/grammar.py327
-rw-r--r--tests/analysis/scan/matches.py27
-rw-r--r--tests/analysis/scan/options.py16
-rw-r--r--tests/analysis/scan/pyapi.py58
-rw-r--r--tests/analysis/scan/sets.py118
97 files changed, 8146 insertions, 1931 deletions
diff --git a/configure.ac b/configure.ac
index 6b6da96..165cb40 100644
--- a/configure.ac
+++ b/configure.ac
@@ -232,6 +232,10 @@ AC_ARG_ENABLE([curl-support],
AS_HELP_STRING([--disable-curl-support], [disable cURL support [default=no]]),
[], [enable_curl_support=yes])
+AC_ARG_ENABLE([magic-support],
+ AS_HELP_STRING([--disable-magic-support], [disable magic number recognition [default=no]]),
+ [], [enable_magic_support=yes])
+
AC_ARG_ENABLE([python-bindings],
AS_HELP_STRING([--disable-python-bindings], [disable Python bindings [default=no]]),
[], [enable_python_bindings=yes])
@@ -503,6 +507,35 @@ AC_SUBST(LIBYAML_CFLAGS)
AC_SUBST(LIBYAML_LIBS)
+#--- Checks for libmagic
+
+AM_CONDITIONAL([BUILD_MAGIC_SUPPORT], [test "x$enable_magic_support" = "xyes"])
+
+if test "x$BUILD_MAGIC_SUPPORT_TRUE" = "x"; then
+ AC_DEFINE(HAVE_MAGIC_SUPPORT, 1,
+ [Define to 1 if the magic support is available and enabled.])
+fi
+
+
+PKG_CHECK_MODULES(LIBMAGIC,libmagic >= 5.44,[libmagic_found=yes],[libmagic_found=no])
+
+if test "$libmagic_found" = "yes"; then
+ libmagic_version=`pkg-config libmagic --modversion`
+else
+ libmagic_version='-'
+fi
+
+
+if test "x$enable_magic_support" = "xyes"; then
+
+ AC_SUBST(LIBMAGIC_CFLAGS)
+ AC_SUBST(LIBMAGIC_LIBS)
+
+ true # empty if/then body not allowed
+
+fi
+
+
#--- Checks for Python
if test "x$enable_debug" = "xyes"; then
@@ -760,6 +793,7 @@ echo The small, fast and reliable database engine. : $libsqlite_version
echo The cryptography and SSL/TLS toolkit......... : $libssl_version
echo The client URL library....................... : $libcurl_version
echo The YAML support library..................... : $libyaml_version
+echo The magic number recognition library......... : $libmagic_version
echo
echo Available Python programming language........ : $python3_version
@@ -781,6 +815,12 @@ else
disable_curl_support="yes"
fi
+if test "x$enable_magic_support" = "xyes"; then
+ disable_magic_support="no"
+else
+ disable_magic_support="yes"
+fi
+
if test "x$enable_python_bindings" = "xyes"; then
disable_python_bindings="no"
else
@@ -792,6 +832,7 @@ echo Print debugging messages..................... : $enable_debug
echo Consider local resources..................... : $with_local_resources
echo Disable GTK support.......................... : $disable_gtk_support
echo Disable cURL support......................... : $disable_curl_support
+echo Disable Magic support........................ : $disable_magic_support
echo Disable Python bindings...................... : $disable_python_bindings
echo Build a Python binary distribution........... : $build_python_package
diff --git a/plugins/kaitai/parsers/enum.c b/plugins/kaitai/parsers/enum.c
index 267aaba..27e5660 100644
--- a/plugins/kaitai/parsers/enum.c
+++ b/plugins/kaitai/parsers/enum.c
@@ -351,7 +351,7 @@ static int compare_enum_values_by_sized_label(const sized_string_t *l, const enu
{
int result; /* Bilan à retourner */
- result = szstrcmp(l, (*b)->label);
+ result = strncmp(l->data, (*b)->label, l->len); // FIXME
return result;
diff --git a/plugins/kaitai/parsers/struct.c b/plugins/kaitai/parsers/struct.c
index 26089d3..128a788 100644
--- a/plugins/kaitai/parsers/struct.c
+++ b/plugins/kaitai/parsers/struct.c
@@ -578,7 +578,7 @@ GKaitaiEnum *g_kaitai_structure_get_enum(const GKaitaiStruct *kstruct, const siz
{
other = g_kaitai_enum_get_name(kstruct->enums[i]);
- if (szstrcmp(name, other) == 0)
+ if (strncmp(name->data, other, name->len) == 0) // FIXME
{
result = kstruct->enums[i];
g_object_ref(G_OBJECT(result));
diff --git a/plugins/pychrysalide/analysis/scan/scanner.c b/plugins/pychrysalide/analysis/scan/scanner.c
index bf5a5f5..befbc80 100644
--- a/plugins/pychrysalide/analysis/scan/scanner.c
+++ b/plugins/pychrysalide/analysis/scan/scanner.c
@@ -188,6 +188,51 @@ static PyObject *py_content_scanner_analyze(PyObject *self, PyObject *args)
/******************************************************************************
* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique le chemin d'un éventuel fichier de source. *
+* *
+* Retour : Chemin d'un éventuel fichier de définitions ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_content_scanner_get_filename(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GContentScanner *scanner; /* Analyseur à consulter */
+ const char *filename; /* Chemin d'accès à transmettre*/
+
+#define CONTENT_SCANNER_FILENAME_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ filename, py_content_scanner, \
+ "Provide the access path to the source file of the rules'" \
+ " definition, or *None* if these rules have not been loaded"\
+ " from memory." \
+)
+
+ scanner = G_CONTENT_SCANNER(pygobject_get(self));
+
+ filename = g_content_scanner_get_filename(scanner);
+
+ if (filename != NULL)
+ result = PyUnicode_FromString(filename);
+
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : - *
* *
* Description : Fournit un accès à une définition de type à diffuser. *
@@ -206,6 +251,7 @@ PyTypeObject *get_python_content_scanner_type(void)
};
static PyGetSetDef py_content_scanner_getseters[] = {
+ CONTENT_SCANNER_FILENAME_ATTRIB,
{ NULL }
};
diff --git a/src/Makefile.am b/src/Makefile.am
index 1fe76bc..233fc10 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -66,6 +66,12 @@ libchrysacore_la_LDFLAGS += $(LIBCURL_LIBS)
endif
+if BUILD_MAGIC_SUPPORT
+
+libchrysacore_la_LDFLAGS += $(LIBMAGIC_LIBS)
+
+endif
+
############################################################
diff --git a/src/analysis/scan/context-int.h b/src/analysis/scan/context-int.h
index 94302bf..3a971b8 100644
--- a/src/analysis/scan/context-int.h
+++ b/src/analysis/scan/context-int.h
@@ -29,9 +29,12 @@
#include "expr.h"
+#include "../../common/fnv1a.h"
+#define ALLOCATION_STEP 10
+
/* Mémorisation des correspondances partielles */
typedef struct _atom_match_tracker_t
{
@@ -41,12 +44,22 @@ typedef struct _atom_match_tracker_t
} atom_match_tracker_t;
-#define ALLOCATION_STEP 10
+/* Mémorisation des correspondances complètes, par motif */
+typedef struct _full_match_tracker_t
+{
+ GSearchPattern *pattern; /* Motif commun aux trouvailles*/
+
+ GScanMatch **matches; /* Correspondances confirmées */
+ size_t allocated; /* Taille du talbeau préparé */
+ size_t used; /* Nombre d'éléments présents */
+
+} full_match_tracker_t;
/* Condition définissant une règle de correspondance */
typedef struct _rule_condition_t
{
char *name; /* Désignation de la règle */
+ fnv64_t name_hash; /* Empreinte de la désignation */
GScanExpression *expr; /* Condition de correspondance */
bool final_reduced; /* Réduction finale tentée ? */
@@ -66,9 +79,8 @@ struct _GScanContext
atom_match_tracker_t *atom_trackers; /* Correspondances partielles */
- GScanMatch **full_matches; /* Correspondances confirmées */
- size_t full_allocated; /* Taille du talbeau préparé */
- size_t full_used; /* Nombre d'éléments présents */
+ full_match_tracker_t **full_trackers; /* Correspondances confirmées */
+ size_t full_count; /* Quantité de correspondances */
rule_condition_t *conditions; /* Ensemble de règles suivies */
size_t cond_count; /* Quantité de ces conditions */
diff --git a/src/analysis/scan/context.c b/src/analysis/scan/context.c
index c19b76c..1f9c38e 100644
--- a/src/analysis/scan/context.c
+++ b/src/analysis/scan/context.c
@@ -25,11 +25,36 @@
#include <assert.h>
+#include <malloc.h>
+#include <stdlib.h>
#include <string.h>
#include "context-int.h"
#include "exprs/literal.h"
+#include "../../common/sort.h"
+
+
+
+
+
+/* ------------------- ADMINISTRATION DES CORRESPONDANCES TOTALES ------------------- */
+
+
+/* Initialise un suivi de trouvailles pour un premier motif. */
+static full_match_tracker_t *create_full_match_tracker(GSearchPattern *);
+
+/* Termine le suivi de trouvailles pour un motif. */
+static void delete_full_match_tracker(full_match_tracker_t *);
+
+/* Etablit la comparaison entre deux structures de suivi. */
+static int compare_full_match_trackers(const full_match_tracker_t **, const full_match_tracker_t **);
+
+/* Note l'existence d'une nouvelle correspondance pour un motif. */
+static void add_match_to_full_match_tracker(full_match_tracker_t *, GScanMatch *);
+
+
+
@@ -47,6 +72,131 @@ static void g_scan_context_finalize(GScanContext *);
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* ADMINISTRATION DES CORRESPONDANCES TOTALES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : pattern = motif de recherche trouvé. *
+* *
+* Description : Initialise un suivi de trouvailles pour un premier motif. *
+* *
+* Retour : Structure de suivi mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static full_match_tracker_t *create_full_match_tracker(GSearchPattern *pattern)
+{
+ full_match_tracker_t *result; /* Structure à retourner */
+
+ result = malloc(sizeof(full_match_tracker_t));
+
+ result->pattern = pattern;
+ g_object_ref(G_OBJECT(pattern));
+
+ result->matches = malloc(ALLOCATION_STEP * sizeof(GScanMatch *));
+ result->allocated = ALLOCATION_STEP;
+ result->used = 0;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : tracker = structure de gestion à manipuler. *
+* *
+* Description : Termine le suivi de trouvailles pour un motif. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void delete_full_match_tracker(full_match_tracker_t *tracker)
+{
+ size_t i; /* Boucle de parcours */
+
+ g_object_unref(G_OBJECT(tracker->pattern));
+
+ for (i = 0; i < tracker->used; i++)
+ g_object_unref(G_OBJECT(tracker->matches[i]));
+
+ free(tracker->matches);
+
+ free(tracker);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : a = première structure de suivi à consulter. *
+* b = seconde structure de suivi à consulter. *
+* *
+* Description : Etablit la comparaison entre deux structures de suivi. *
+* *
+* Retour : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int compare_full_match_trackers(const full_match_tracker_t **a, const full_match_tracker_t **b)
+{
+ int result; /* Bilan à renvoyer */
+
+ result = sort_unsigned_long((unsigned long)(*a)->pattern, (unsigned long)(*b)->pattern);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : tracker = structure de gestion à manipuler. *
+* match = correspondance complète établie. *
+* *
+* Description : Note l'existence d'une nouvelle correspondance pour un motif.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void add_match_to_full_match_tracker(full_match_tracker_t *tracker, GScanMatch *match)
+{
+ if (tracker->used == tracker->allocated)
+ {
+ tracker->allocated += ALLOCATION_STEP;
+ tracker->matches = realloc(tracker->matches, tracker->allocated * sizeof(GScanMatch *));
+ }
+
+ tracker->matches[tracker->used++] = match;
+ g_object_ref(G_OBJECT(match));
+
+}
+
+
+
+
+
+
+
+
+
/* Indique le type défini pour un contexte de suivi d'analyse. */
G_DEFINE_TYPE(GScanContext, g_scan_context, G_TYPE_OBJECT);
@@ -97,9 +247,8 @@ static void g_scan_context_init(GScanContext *context)
context->atom_trackers = NULL;
- context->full_matches = NULL;
- context->full_allocated = 0;
- context->full_used = 0;
+ context->full_trackers = NULL;
+ context->full_count = 0;
context->conditions = NULL;
context->cond_count = 0;
@@ -127,8 +276,12 @@ static void g_scan_context_dispose(GScanContext *context)
g_clear_object(&context->content);
- for (i = 0; i < context->full_used; i++)
- g_clear_object(&context->full_matches[i]);
+ for (i = 0; i < context->full_count; i++)
+ if (context->full_trackers[i] != NULL)
+ {
+ delete_full_match_tracker(context->full_trackers[i]);
+ context->full_trackers[i] = NULL;
+ }
for (i = 0; i < context->cond_count; i++)
g_clear_object(&context->conditions[i].expr);
@@ -170,8 +323,8 @@ static void g_scan_context_finalize(GScanContext *context)
}
- if (context->full_matches != NULL)
- free(context->full_matches);
+ if (context->full_trackers != NULL)
+ free(context->full_trackers);
if (context->conditions != NULL)
{
@@ -387,14 +540,75 @@ const phys_t *g_scan_context_get_atom_matches(const GScanContext *context, patid
void g_scan_context_register_full_match(GScanContext *context, GScanMatch *match)
{
- if (context->full_used == context->full_allocated)
+ GSearchPattern *pattern; /* Clef d'un suivi */
+ full_match_tracker_t key; /* Modèle d'identification */
+ full_match_tracker_t **found; /* Structure à actualiser */
+ full_match_tracker_t *tracker; /* Nouveau suivi à intégrer */
+
+ pattern = g_scan_match_get_source(match);
+
+ key.pattern = pattern;
+
+ found = bsearch((full_match_tracker_t *[]) { &key }, context->full_trackers, context->full_count,
+ sizeof(full_match_tracker_t *), (__compar_fn_t)compare_full_match_trackers);
+
+ if (found == NULL)
{
- context->full_allocated += ALLOCATION_STEP;
- context->full_matches = realloc(context->full_matches, context->full_allocated * sizeof(GScanMatch *));
+ tracker = create_full_match_tracker(pattern);
+
+ context->full_trackers = qinsert(context->full_trackers, &context->full_count,
+ sizeof(full_match_tracker_t *),
+ (__compar_fn_t)compare_full_match_trackers, &tracker);
+
}
+ else
+ tracker = *found;
- context->full_matches[context->full_used++] = match;
- g_object_ref(G_OBJECT(match));
+ add_match_to_full_match_tracker(tracker, match);
+
+ g_object_unref(G_OBJECT(pattern));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = instance à mettre à jour. *
+* pattern = motif dont des correspondances sont à retrouver. *
+* count = quantité de correspondances enregistrées. [OUT] *
+* *
+* Description : Fournit la liste de toutes les correspondances d'un motif. *
+* *
+* Retour : Liste courante de correspondances établies. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const GScanMatch **g_scan_context_get_full_matches(const GScanContext *context, const GSearchPattern *pattern, size_t *count)
+{
+ GScanMatch **result; /* Correspondance à renvoyer */
+ full_match_tracker_t key; /* Modèle d'identification */
+ full_match_tracker_t **found; /* Structure à actualiser */
+
+ key.pattern = pattern;
+
+ found = bsearch((full_match_tracker_t *[]) { &key }, context->full_trackers, context->full_count,
+ sizeof(full_match_tracker_t *), (__compar_fn_t)compare_full_match_trackers);
+
+ if (found == NULL)
+ {
+ result = NULL;
+ count = 0;
+ }
+
+ else
+ {
+ result = (*found)->matches;
+ *count = (*found)->used;
+ }
+
+ return result;
}
@@ -411,12 +625,25 @@ void g_scan_context_register_full_match(GScanContext *context, GScanMatch *match
* *
******************************************************************************/
-void g_scan_context_display(const GScanContext *context)
+void g_scan_context_display(GScanContext *context)
{
size_t i; /* Boucle de parcours */
+ const rule_condition_t *cond; /* Conditions de orrespondance */
+ /*
+ FIXME : ordre
for (i = 0; i < context->full_used; i++)
g_scan_match_display(context->full_matches[i]);
+ */
+
+ for (i = 0; i < context->cond_count; i++)
+ {
+ cond = &context->conditions[i];
+
+ if (g_scan_context_has_match_for_rule(context, cond->name))
+ fprintf(stderr, "Rule '%s' has matched!\n", cond->name);
+
+ }
}
@@ -445,7 +672,7 @@ bool g_scan_context_set_rule_condition(GScanContext *context, const char *name,
/* Recherche d'antécédent */
- for (i = 0; context->cond_count; i++)
+ for (i = 0; i < context->cond_count; i++)
if (strcmp(name, context->conditions[i].name) == 0)
{
result = false;
@@ -461,8 +688,10 @@ bool g_scan_context_set_rule_condition(GScanContext *context, const char *name,
new = &context->conditions[context->cond_count - 1];
new->name = strdup(name);
+ new->name_hash = fnv_64a_hash(name);
- new->expr = g_scan_expression_duplicate(expr);
+ new->expr = expr;//g_scan_expression_duplicate(expr);
+ g_object_ref(G_OBJECT(expr)); // FIXME => REMME dup()
new->final_reduced = false;
}
@@ -477,6 +706,50 @@ bool g_scan_context_set_rule_condition(GScanContext *context, const char *name,
* Paramètres : context = mémoire de résultats d'analyse à consulter. *
* name = désignation de la règle ciblée. *
* *
+* Description : Indique si un nom donné correspond à une règle. *
+* *
+* Retour : Bilan de la présence d'une règle désignée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_context_has_rule_for_name(const GScanContext *context, const char *name)
+{
+ bool result; /* Bilan à retourner */
+ fnv64_t hash; /* Empreinte du nom à retrouver*/
+ size_t i; /* Boucle de parcours */
+ const rule_condition_t *cond; /* Condition connue du contexte*/
+
+ result = false;
+
+ hash = fnv_64a_hash(name);
+
+ for (i = 0; i < context->cond_count; i++)
+ {
+ cond = context->conditions + i;
+
+ if (cond->name_hash != hash)
+ continue;
+
+ if (strcmp(cond->name, name) == 0)
+ {
+ result = true;
+ break;
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = mémoire de résultats d'analyse à consulter. *
+* name = désignation de la règle ciblée. *
+* *
* Description : Indique si une correspondance globale a pu être établie. *
* *
* Retour : Bilan final d'une analyse (false par défaut). *
@@ -513,21 +786,27 @@ bool g_scan_context_has_match_for_rule(GScanContext *context, const char *name)
if (!cond->final_reduced)
{
- cond->final_reduced = g_scan_expression_reduce(cond->expr, context, NULL, &new);
+ valid = g_scan_expression_reduce(cond->expr, context, NULL, &new);
+ if (!valid || new == NULL) goto exit;
- if (cond->final_reduced && new != NULL)
- {
- g_object_unref(G_OBJECT(cond->expr));
- cond->expr = new;
- }
+ g_object_unref(G_OBJECT(cond->expr));
+ cond->expr = new;
+
+ valid = g_scan_expression_reduce_to_boolean(cond->expr, context, NULL, &new);
+ if (!valid || new == NULL) goto exit;
+
+ g_object_unref(G_OBJECT(cond->expr));
+ cond->expr = new;
+
+ cond->final_reduced = true;
}
/* Tentative de récupération d'un bilan final */
- if (G_IS_LITERAL_EXPRESSION(cond->expr))
+ if (cond->final_reduced)
{
- valid = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(cond->expr), &result);
+ valid = g_scan_literal_expression_get_boolean_value(G_SCAN_LITERAL_EXPRESSION(cond->expr), &result);
if (!valid)
{
diff --git a/src/analysis/scan/context.h b/src/analysis/scan/context.h
index 92522f8..563a53e 100644
--- a/src/analysis/scan/context.h
+++ b/src/analysis/scan/context.h
@@ -86,12 +86,18 @@ const phys_t *g_scan_context_get_atom_matches(const GScanContext *, patid_t, siz
/* Enregistre une correspondance complète avec un contenu. */
void g_scan_context_register_full_match(GScanContext *, GScanMatch *);
+/* Fournit la liste de toutes les correspondances d'un motif. */
+const GScanMatch **g_scan_context_get_full_matches(const GScanContext *, const GSearchPattern *, size_t *);
+
/* Affiche les correspondances identifiées. */
-void g_scan_context_display(const GScanContext *);
+void g_scan_context_display(GScanContext *);
/* Intègre une condition de correspondance pour règle. */
bool g_scan_context_set_rule_condition(GScanContext *, const char *, const GScanExpression *);
+/* Indique si un nom donné correspond à une règle. */
+bool g_scan_context_has_rule_for_name(const GScanContext *, const char *);
+
/* Indique si une correspondance globale a pu être établie. */
bool g_scan_context_has_match_for_rule(GScanContext *, const char *);
diff --git a/src/analysis/scan/core.c b/src/analysis/scan/core.c
index aef9abd..d940ab5 100644
--- a/src/analysis/scan/core.c
+++ b/src/analysis/scan/core.c
@@ -24,8 +24,20 @@
#include "core.h"
+#include <config.h>
+
+
+#include "items/count.h"
#include "items/datasize.h"
#include "items/uint.h"
+#include "items/console/log.h"
+#ifdef HAVE_MAGIC_SUPPORT
+# include "items/magic/type.h"
+# include "items/magic/mime-encoding.h"
+# include "items/magic/mime-type.h"
+#endif
+#include "items/time/make.h"
+#include "items/time/now.h"
@@ -43,25 +55,83 @@
bool populate_main_scan_namespace(GScanNamespace *space)
{
- bool result;
+ bool result; /* Bilan à retourner */
+ GScanNamespace *ns; /* Nouvel espace de noms */
result = true;
-#define REGISTER_FUNC(s, f) \
- ({ \
- bool __result; \
- __result = g_scan_namespace_register_item(s, G_REGISTERED_ITEM(f)); \
- g_object_unref(G_OBJECT(f)); \
- __result; \
+#define REGISTER_FUNC(s, f) \
+ ({ \
+ bool __result; \
+ __result = g_scan_namespace_register_item(s, f); \
+ g_object_unref(G_OBJECT(f)); \
+ __result; \
})
- if (result) result = REGISTER_FUNC(space, g_datasize_function_new());
- //if (result) result = REGISTER_FUNC(space, g_datasize_function_new(), "filesize"); /* Alias */
+ if (result) result = REGISTER_FUNC(space, g_scan_count_function_new());
+ if (result) result = REGISTER_FUNC(space, g_scan_datasize_function_new());
+
+ if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_8_BITS_SIGNED, SRE_LITTLE));
+ if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_8_BITS_UNSIGNED, SRE_LITTLE));
+
+ if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_16_BITS_SIGNED, SRE_LITTLE));
+ if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_16_BITS_SIGNED, SRE_BIG));
+ if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_16_BITS_UNSIGNED, SRE_LITTLE));
+ if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_16_BITS_UNSIGNED, SRE_BIG));
+
+ if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_32_BITS_SIGNED, SRE_LITTLE));
+ if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_32_BITS_SIGNED, SRE_BIG));
+ if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_32_BITS_UNSIGNED, SRE_LITTLE));
+ if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_32_BITS_UNSIGNED, SRE_BIG));
+
+ if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_64_BITS_SIGNED, SRE_LITTLE));
+ if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_64_BITS_SIGNED, SRE_BIG));
+ if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_64_BITS_UNSIGNED, SRE_LITTLE));
+ if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_64_BITS_UNSIGNED, SRE_BIG));
+
+ /* Console */
+
+ if (result)
+ {
+ ns = g_scan_namespace_new("console");
+ result = g_scan_namespace_register_item(space, G_REGISTERED_ITEM(ns));
+
+ if (result) result = REGISTER_FUNC(ns, g_scan_console_log_function_new());
+
+ g_object_unref(G_OBJECT(ns));
+
+ }
+
+ /* Magic */
+
+#ifdef HAVE_MAGIC_SUPPORT
+ if (result)
+ {
+ ns = g_scan_namespace_new("magic");
+ result = g_scan_namespace_register_item(space, G_REGISTERED_ITEM(ns));
+
+ if (result) result = REGISTER_FUNC(ns, g_scan_magic_type_function_new());
+ if (result) result = REGISTER_FUNC(ns, g_scan_mime_encoding_function_new());
+ if (result) result = REGISTER_FUNC(ns, g_scan_mime_type_function_new());
+
+ g_object_unref(G_OBJECT(ns));
+
+ }
+#endif
+
+ /* Time */
+
+ if (result)
+ {
+ ns = g_scan_namespace_new("time");
+ result = g_scan_namespace_register_item(space, G_REGISTERED_ITEM(ns));
+
+ if (result) result = REGISTER_FUNC(ns, g_scan_time_make_function_new());
+ if (result) result = REGISTER_FUNC(ns, g_scan_time_now_function_new());
+
+ g_object_unref(G_OBJECT(ns));
- if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_8_BITS_UNSIGNED));
- if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_16_BITS_UNSIGNED));
- if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_32_BITS_UNSIGNED));
- if (result) result = REGISTER_FUNC(space, g_uint_function_new(MDS_64_BITS_UNSIGNED));
+ }
return result;
diff --git a/src/analysis/scan/expr-int.h b/src/analysis/scan/expr-int.h
index dbfea6e..48668b5 100644
--- a/src/analysis/scan/expr-int.h
+++ b/src/analysis/scan/expr-int.h
@@ -39,16 +39,28 @@
typedef bool (* compare_expr_rich_fc) (const GScanExpression *, const GScanExpression *, RichCmpOperation, bool *);
/* Vérifie la validité d'une expression. */
-typedef bool (* check_expr_validity_fc) (const GScanExpression *);
+typedef bool (* check_expr_validity_fc) (const GScanExpression *); // REMME ?
/* Reproduit une expression en place dans une nouvelle instance. */
-typedef GScanExpression * (* dup_expr_fc) (const GScanExpression *);
+typedef GScanExpression * (* dup_expr_fc) (const GScanExpression *); // REMME ?
/* Reproduit une expression en place dans une nouvelle instance. */
typedef void (* copy_expr_fc) (GScanExpression *, const GScanExpression *);
/* Réduit une expression à une forme plus simple. */
-typedef bool (* reduce_expr_fc) (GScanExpression *, GScanContext *, GScanScope *, GScanExpression **);
+typedef ScanReductionState (* reduce_expr_fc) (GScanExpression *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réduit une expression à une forme booléenne. */
+typedef bool (* reduce_expr_to_bool_fc) (GScanExpression *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Dénombre les éléments portés par une expression. */
+typedef bool (* count_scan_expr_fc) (const GScanExpression *, size_t *);
+
+/* Fournit un élément donné issu d'un ensemble constitué. */
+typedef bool (* get_scan_expr_fc) (const GScanExpression *, size_t, GScanExpression **);
+
+/* Réalise l'intersection entre deux ensembles. */
+typedef GScanExpression * (* intersect_scan_expr_fc) (GScanExpression *, const GScanExpression *, GScanContext *, GScanScope *);
/* Expression d'évaluation généraliste (instance) */
@@ -56,6 +68,8 @@ struct _GScanExpression
{
GObject parent; /* A laisser en premier */
+ ScanReductionState state; /* Etat synthétisé de l'élément*/
+
ExprValueType value_type; /* Type de valeur portée */
};
@@ -67,9 +81,15 @@ struct _GScanExpressionClass
compare_expr_rich_fc cmp_rich; /* Comparaison de façon précise*/
check_expr_validity_fc check; /* Validation de la cohérence */
- copy_expr_fc copy; /* Reproduction d'expression */
+ copy_expr_fc copyXXX; /* Reproduction d'expression */
dup_expr_fc dup; /* Reproduction d'expression */
+
reduce_expr_fc reduce; /* Simplification d'expression */
+ reduce_expr_to_bool_fc reduce_to_bool; /* Conversion en booléen */
+
+ count_scan_expr_fc count; /* Décompte d'éléments */
+ get_scan_expr_fc get; /* Extraction d'un élément */
+ intersect_scan_expr_fc intersect; /* Intersection entre ensembles*/
};
diff --git a/src/analysis/scan/expr.c b/src/analysis/scan/expr.c
index 52d2c42..808b14f 100644
--- a/src/analysis/scan/expr.c
+++ b/src/analysis/scan/expr.c
@@ -28,6 +28,8 @@
#include "expr-int.h"
+#include "exprs/literal.h"
+#include "exprs/set.h"
@@ -52,6 +54,9 @@ static void g_scan_expression_finalize(GScanExpression *);
/* Reproduit une expression en place dans une nouvelle instance. */
static void g_scan_expression_copy(GScanExpression *, const GScanExpression *);
+/* Réalise l'intersection entre deux ensembles. */
+static GScanExpression *_g_scan_expression_intersect(GScanExpression *, const GScanExpression *, GScanContext *, GScanScope *);
+
/* ----------------------- INTERFACE OFFRANT DES COMPARAISONS ----------------------- */
@@ -93,7 +98,8 @@ static void g_scan_expression_class_init(GScanExpressionClass *klass)
object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_expression_dispose;
object->finalize = (GObjectFinalizeFunc)g_scan_expression_finalize;
- klass->copy = g_scan_expression_copy;
+ //klass->copy = g_scan_expression_copy;
+ klass->intersect = _g_scan_expression_intersect;
}
@@ -112,6 +118,7 @@ static void g_scan_expression_class_init(GScanExpressionClass *klass)
static void g_scan_expression_init(GScanExpression *expr)
{
+ expr->state = SRS_PENDING;
}
@@ -292,7 +299,7 @@ GScanExpression *g_scan_expression_duplicate(const GScanExpression *expr)
class = G_SCAN_EXPRESSION_GET_CLASS(expr);
- class->copy(result, expr);
+ //class->copy(result, expr);
return result;
@@ -314,7 +321,200 @@ GScanExpression *g_scan_expression_duplicate(const GScanExpression *expr)
* *
******************************************************************************/
-bool g_scan_expression_reduce(GScanExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+ScanReductionState g_scan_expression_reduce(GScanExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ GScanExpressionClass *class; /* Classe à activer */
+
+ if (expr->state == SRS_REDUCED)
+ {
+ *out = expr;
+ g_object_ref(G_OBJECT(expr));
+ }
+
+ else
+ {
+ *out = NULL;
+
+ class = G_SCAN_EXPRESSION_GET_CLASS(expr);
+
+ if (class->reduce != NULL)
+ {
+ expr->state = class->reduce(expr, ctx, scope, out);
+
+ if (expr->state != SRS_UNRESOLVABLE && *out == NULL)
+ {
+ *out = expr;
+ g_object_ref(G_OBJECT(expr));
+ }
+
+ }
+
+ else
+ expr->state = SRS_UNRESOLVABLE;
+
+#ifndef NDEBUG
+ if (*out != NULL)
+ assert(expr->state != SRS_UNRESOLVABLE);
+#endif
+
+ }
+
+ assert(expr->state != SRS_PENDING);
+
+
+ return expr->state;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 booléenne. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_expression_reduce_to_boolean(GScanExpression *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+ GScanExpression *inter; /* Expression intermédiaire */
+ GScanExpressionClass *class; /* Classe à activer */
+
+ *out = NULL;
+
+ result = g_scan_expression_reduce(expr, ctx, scope, &inter);
+ if (!result) goto exit;
+
+ if (inter != NULL)
+ {
+ class = G_SCAN_EXPRESSION_GET_CLASS(inter);
+
+ if (class->reduce_to_bool != NULL)
+ result = class->reduce_to_bool(inter, ctx, scope, out);
+ else
+ result = false;
+
+ g_object_unref(G_OBJECT(inter));
+
+ /* Validation d'un type booléen */
+ if (result && *out != NULL)
+ {
+ if (!G_IS_SCAN_LITERAL_EXPRESSION(*out))
+ {
+ g_clear_object(out);
+ result = false;
+ }
+
+ if (g_scan_literal_expression_get_value_type(G_SCAN_LITERAL_EXPRESSION(*out)) != LVT_BOOLEAN)
+ {
+ g_clear_object(out);
+ result = false;
+ }
+
+ }
+
+ }
+
+ exit:
+
+#ifndef NDEBUG
+ if (*out != NULL)
+ assert(result);
+#endif
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* *
+* Description : Détermine si l'expression peut représenter un ensemble. *
+* *
+* Retour : Bilan de la consultation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_expression_handle_set_features(const GScanExpression *expr)
+{
+ bool result; /* Bilan à retourner */
+ GScanExpressionClass *class; /* Classe à activer */
+
+ class = G_SCAN_EXPRESSION_GET_CLASS(expr);
+
+ result = (class->count != NULL);
+
+ assert((result && (class->get != NULL)) || (!result && (class->get == NULL)));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* count = quantité d'éléments déterminée. [OUT] *
+* *
+* 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. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_expression_count_items(const GScanExpression *expr, size_t *count)
+{
+ bool result; /* Bilan à retourner */
+ GScanExpressionClass *class; /* Classe à activer */
+
+ *count = -1;
+
+ class = G_SCAN_EXPRESSION_GET_CLASS(expr);
+
+ if (class->count != NULL)
+ result = class->count(expr, count);
+ else
+ result = false;
+
+#ifndef NDEBUG
+ if (*count != -1)
+ assert(result);
+#endif
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* index = indice de l'élément à transférer. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Fournit un élément donné issu d'un ensemble constitué. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_expression_get_item(const GScanExpression *expr, size_t index, GScanExpression **out)
{
bool result; /* Bilan à retourner */
GScanExpressionClass *class; /* Classe à activer */
@@ -323,7 +523,17 @@ bool g_scan_expression_reduce(GScanExpression *expr, GScanContext *ctx, GScanSco
class = G_SCAN_EXPRESSION_GET_CLASS(expr);
- result = class->reduce(expr, ctx, scope, out);
+ if (class->get != NULL)
+ {
+ result = class->get(expr, index, out);
+
+ if (*out != NULL)
+ g_object_ref(G_OBJECT(*out));
+
+ }
+
+ else
+ result = false;
#ifndef NDEBUG
if (*out != NULL)
@@ -335,6 +545,133 @@ bool g_scan_expression_reduce(GScanExpression *expr, GScanContext *ctx, GScanSco
}
+/******************************************************************************
+* *
+* Paramètres : expr = expression à filtrer. *
+* other = expression utilisée pour le filtrage. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* *
+* Description : Réalise l'intersection entre deux ensembles. *
+* *
+* Retour : Intersection entre les deux ensembles ou NULL en cas d'échec.*
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GScanExpression *_g_scan_expression_intersect(GScanExpression *expr, const GScanExpression *other, GScanContext *ctx, GScanScope *scope)
+{
+ GScanExpression *result; /* Instance à retourner */
+ size_t other_count; /* Taille du second ensemble */
+ bool valid; /* Bilan de validité */
+ size_t expr_count; /* Taille du premier ensemble */
+ size_t k; /* Boucle de parcours #1 */
+ GComparableItem *comparable; /* Premier élément à comparer */
+ size_t i; /* Boucle de parcours #2 */
+ GScanExpression *item; /* Elément à comparer */
+ bool status; /* Bilan d'une comparaison */
+
+ result = NULL;
+
+ valid = g_scan_expression_count_items(other, &other_count);
+ if (!valid) goto done;
+
+ /* Intersection entre deux ensembles ? */
+ if (g_scan_expression_handle_set_features(expr))
+ {
+ valid = g_scan_expression_count_items(expr, &expr_count);
+ if (!valid) goto done;
+
+ result = g_scan_generic_set_new();
+
+ for (k = 0; k < expr_count; k++)
+ {
+ valid = g_scan_expression_get_item(expr, k, &item);
+ if (!valid) break;
+
+ comparable = G_COMPARABLE_ITEM(item);
+
+ for (i = 0; i < other_count; i++)
+ {
+ valid = g_scan_expression_get_item(other, i, &item);
+ if (!valid) break;
+
+ valid = g_comparable_item_compare_rich(comparable, G_COMPARABLE_ITEM(item), RCO_EQ, &status);
+
+ if (valid && status)
+ g_scan_generic_set_add_item(G_SCAN_GENERIC_SET(result), item);
+
+ g_object_unref(G_OBJECT(item));
+
+ }
+
+ g_object_unref(G_OBJECT(comparable));
+
+ }
+
+ }
+
+ /* Intersection entre un élément et un ensemble */
+ else
+ {
+ comparable = G_COMPARABLE_ITEM(expr);
+
+ for (i = 0; i < other_count && result == NULL; i++)
+ {
+ valid = g_scan_expression_get_item(other, i, &item);
+ if (!valid) break;
+
+ valid = g_comparable_item_compare_rich(comparable, G_COMPARABLE_ITEM(item), RCO_EQ, &status);
+
+ if (valid && status)
+ result = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { true });
+
+ g_object_unref(G_OBJECT(item));
+
+ }
+
+ if (result && result == NULL)
+ result = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { false });
+
+ }
+
+ done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à filtrer. *
+* other = expression utilisée pour le filtrage. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* *
+* Description : Réalise l'intersection entre deux ensembles. *
+* *
+* Retour : Intersection entre les deux ensembles ou NULL en cas d'échec.*
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_expression_intersect(GScanExpression *expr, const GScanExpression *other, GScanContext *ctx, GScanScope *scope)
+{
+ GScanExpression *result; /* Instance à retourner */
+ GScanExpressionClass *class; /* Classe à activer */
+
+ class = G_SCAN_EXPRESSION_GET_CLASS(expr);
+
+ result = class->intersect(expr, other, ctx, scope);
+
+ return result;
+
+}
+
+
/* ---------------------------------------------------------------------------------- */
/* INTERFACE OFFRANT DES COMPARAISONS */
@@ -364,7 +701,14 @@ static bool g_scan_expression_compare_rich(const GScanExpression *item, const GS
class = G_SCAN_EXPRESSION_GET_CLASS(item);
if (class->cmp_rich != NULL)
- result = class->cmp_rich(item, other, op, status);
+ {
+ result = (G_TYPE_FROM_INSTANCE(item) == G_TYPE_FROM_INSTANCE(other)); // FIXME : subtype ? cf. literal ?
+
+ if (result)
+ result = class->cmp_rich(item, other, op, status);
+
+ }
+
else
result = false;
diff --git a/src/analysis/scan/expr.h b/src/analysis/scan/expr.h
index d596222..dd4bc3f 100644
--- a/src/analysis/scan/expr.h
+++ b/src/analysis/scan/expr.h
@@ -64,6 +64,16 @@ typedef enum _ExprValueType
} ExprValueType;
+/* Etat de l'expression vis à vis des réductions */
+typedef enum _ScanReductionState
+{
+ SRS_PENDING, /* Nature à déterminer */
+ SRS_REDUCED, /* Nature compacte finale */
+ SRS_WAIT_FOR_SCAN, /* Nature vouée à évoluer */
+ SRS_UNRESOLVABLE, /* Nature indéterminable */
+
+} ScanReductionState;
+
/* Indique le type défini pour une expression de validation. */
GType g_scan_expression_get_type(void);
@@ -78,7 +88,22 @@ bool g_scan_expression_check_validity(const GScanExpression *);
GScanExpression *g_scan_expression_duplicate(const GScanExpression *);
/* Réduit une expression à une forme plus simple. */
-bool g_scan_expression_reduce(GScanExpression *, GScanContext *, GScanScope *, GScanExpression **);
+ScanReductionState g_scan_expression_reduce(GScanExpression *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réduit une expression à une forme booléenne. */
+bool g_scan_expression_reduce_to_boolean(GScanExpression *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Détermine si l'expression peut représenter un ensemble. */
+bool g_scan_expression_handle_set_features(const GScanExpression *);
+
+/* Dénombre les éléments portés par une expression. */
+bool g_scan_expression_count_items(const GScanExpression *, size_t *);
+
+/* Fournit un élément donné issu d'un ensemble constitué. */
+bool g_scan_expression_get_item(const GScanExpression *, size_t, GScanExpression **);
+
+/* Réalise l'intersection entre deux ensembles. */
+GScanExpression *g_scan_expression_intersect(GScanExpression *, const GScanExpression *, GScanContext *, GScanScope *);
diff --git a/src/analysis/scan/exprs/Makefile.am b/src/analysis/scan/exprs/Makefile.am
index efe25fc..1266a63 100644
--- a/src/analysis/scan/exprs/Makefile.am
+++ b/src/analysis/scan/exprs/Makefile.am
@@ -5,16 +5,24 @@ noinst_LTLIBRARIES = libanalysisscanexprs.la
libanalysisscanexprs_la_SOURCES = \
access-int.h \
access.h access.c \
- arithmop-int.h \
- arithmop.h arithmop.c \
- boolop-int.h \
- boolop.h boolop.c \
+ arithmetic-int.h \
+ arithmetic.h arithmetic.c \
call-int.h \
call.h call.c \
+ counter-int.h \
+ counter.h counter.c \
+ intersect-int.h \
+ intersect.h intersect.c \
literal-int.h \
literal.h literal.c \
- relop-int.h \
- relop.h relop.c \
+ logical-int.h \
+ logical.h logical.c \
+ range-int.h \
+ range.h range.c \
+ relational-int.h \
+ relational.h relational.c \
+ set-int.h \
+ set.h set.c \
strop-int.h \
strop.h strop.c
diff --git a/src/analysis/scan/exprs/access-int.h b/src/analysis/scan/exprs/access-int.h
index 2212b48..725051c 100644
--- a/src/analysis/scan/exprs/access-int.h
+++ b/src/analysis/scan/exprs/access-int.h
@@ -32,8 +32,11 @@
+/* Reproduit un accès en place dans une nouvelle instance. */
+typedef void (* copy_scan_access_fc) (GScanNamedAccess *, const GScanNamedAccess *);
+
/* Accès à un élément d'expression sous-jacent (instance) */
-struct _GNamedAccess
+struct _GScanNamedAccess
{
GScanExpression parent; /* A laisser en premier */
@@ -46,23 +49,25 @@ struct _GNamedAccess
char *target; /* Cible dans l'espace */
- struct _GNamedAccess *next; /* Evnetuel prochain élément */
+ struct _GScanNamedAccess *next; /* Evnetuel prochain élément */
};
/* Accès à un élément d'expression sous-jacent (classe) */
-struct _GNamedAccessClass
+struct _GScanNamedAccessClass
{
GScanExpressionClass parent; /* A laisser en premier */
+ copy_scan_access_fc copy; /* Reproduction d'accès */
+
};
/* Met en place une expression d'accès. */
-bool g_named_access_create(GNamedAccess *, const sized_string_t *);
+bool g_scan_named_access_create(GScanNamedAccess *, const sized_string_t *);
-/* Réduit une expression à une forme plus simple. */
-bool _g_named_access_reduce(GNamedAccess *, GScanContext *, GScanScope *, GScanExpression **);
+/* Prépare une réduction en menant une résolution locale. */
+GRegisteredItem *_g_scan_named_access_prepare_reduction(GScanNamedAccess *, GScanContext *, GScanScope *);
diff --git a/src/analysis/scan/exprs/access.c b/src/analysis/scan/exprs/access.c
index ad66f60..1c3a880 100644
--- a/src/analysis/scan/exprs/access.c
+++ b/src/analysis/scan/exprs/access.c
@@ -30,6 +30,7 @@
#include "access-int.h"
+#include "literal.h"
#include "../../../core/global.h"
@@ -38,27 +39,27 @@
/* Initialise la classe des appels de fonction avec arguments. */
-static void g_named_access_class_init(GNamedAccessClass *);
+static void g_scan_named_access_class_init(GScanNamedAccessClass *);
/* Initialise une instance d'appel de fonction avec arguments. */
-static void g_named_access_init(GNamedAccess *);
+static void g_scan_named_access_init(GScanNamedAccess *);
/* Supprime toutes les références externes. */
-static void g_named_access_dispose(GNamedAccess *);
+static void g_scan_named_access_dispose(GScanNamedAccess *);
/* Procède à la libération totale de la mémoire. */
-static void g_named_access_finalize(GNamedAccess *);
+static void g_scan_named_access_finalize(GScanNamedAccess *);
+/* Reproduit un accès en place dans une nouvelle instance. */
+static void g_scan_named_access_copy(GScanNamedAccess *, const GScanNamedAccess *);
-/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+/* --------------------- 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 **);
+static ScanReductionState g_scan_named_access_reduce(GScanNamedAccess *, GScanContext *, GScanScope *, GScanExpression **);
@@ -68,7 +69,7 @@ static bool g_named_access_reduce(GNamedAccess *, GScanContext *, GScanScope *,
/* Indique le type défini pour un appel de fonction enregistrée. */
-G_DEFINE_TYPE(GNamedAccess, g_named_access, G_TYPE_SCAN_EXPRESSION);
+G_DEFINE_TYPE(GScanNamedAccess, g_scan_named_access, G_TYPE_SCAN_EXPRESSION);
/******************************************************************************
@@ -83,21 +84,22 @@ G_DEFINE_TYPE(GNamedAccess, g_named_access, G_TYPE_SCAN_EXPRESSION);
* *
******************************************************************************/
-static void g_named_access_class_init(GNamedAccessClass *klass)
+static void g_scan_named_access_class_init(GScanNamedAccessClass *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;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_named_access_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_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;
+ expr->reduce = (reduce_expr_fc)g_scan_named_access_reduce;
+
+ klass->copy = g_scan_named_access_copy;
}
@@ -114,7 +116,7 @@ static void g_named_access_class_init(GNamedAccessClass *klass)
* *
******************************************************************************/
-static void g_named_access_init(GNamedAccess *access)
+static void g_scan_named_access_init(GScanNamedAccess *access)
{
access->any = NULL;
access->target = NULL;
@@ -136,13 +138,13 @@ static void g_named_access_init(GNamedAccess *access)
* *
******************************************************************************/
-static void g_named_access_dispose(GNamedAccess *access)
+static void g_scan_named_access_dispose(GScanNamedAccess *access)
{
g_clear_object(&access->any);
g_clear_object(&access->next);
- G_OBJECT_CLASS(g_named_access_parent_class)->dispose(G_OBJECT(access));
+ G_OBJECT_CLASS(g_scan_named_access_parent_class)->dispose(G_OBJECT(access));
}
@@ -159,12 +161,12 @@ static void g_named_access_dispose(GNamedAccess *access)
* *
******************************************************************************/
-static void g_named_access_finalize(GNamedAccess *access)
+static void g_scan_named_access_finalize(GScanNamedAccess *access)
{
if (access->target != NULL)
free(access->target);
- G_OBJECT_CLASS(g_named_access_parent_class)->finalize(G_OBJECT(access));
+ G_OBJECT_CLASS(g_scan_named_access_parent_class)->finalize(G_OBJECT(access));
}
@@ -181,13 +183,13 @@ static void g_named_access_finalize(GNamedAccess *access)
* *
******************************************************************************/
-GScanExpression *g_named_access_new(const sized_string_t *target)
+GScanExpression *g_scan_named_access_new(const sized_string_t *target)
{
GScanExpression *result; /* Structure à retourner */
- result = g_object_new(G_TYPE_NAMED_ACCESS, NULL);
+ result = g_object_new(G_TYPE_SCAN_NAMED_ACCESS, NULL);
- if (!g_named_access_create(G_NAMED_ACCESS(result), target))
+ if (!g_scan_named_access_create(G_SCAN_NAMED_ACCESS(result), target))
g_clear_object(&result);
return result;
@@ -208,16 +210,14 @@ GScanExpression *g_named_access_new(const sized_string_t *target)
* *
******************************************************************************/
-bool g_named_access_create(GNamedAccess *access, const sized_string_t *target)
+bool g_scan_named_access_create(GScanNamedAccess *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);
+ result = true;
- exit:
+ if (target != NULL)
+ access->target = strndup(target->data, target->len);
return result;
@@ -226,10 +226,10 @@ bool g_named_access_create(GNamedAccess *access, const sized_string_t *target)
/******************************************************************************
* *
-* Paramètres : access = expression d'appel à actualiser. *
-* base = zone de recherche pour la résolution à venir. *
+* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
+* src = expression source à copier. *
* *
-* Description : Définit une base de recherche pour la cible d'accès. *
+* Description : Reproduit un accès en place dans une nouvelle instance. *
* *
* Retour : - *
* *
@@ -237,55 +237,74 @@ bool g_named_access_create(GNamedAccess *access, const sized_string_t *target)
* *
******************************************************************************/
-void g_named_access_set_base(GNamedAccess *access, GRegisteredItem *base)
+static void g_scan_named_access_copy(GScanNamedAccess *dest, const GScanNamedAccess *src)
{
- g_clear_object(&access->base);
+ /**
+ * Les champs suivants sont voués à être remplacés ou supprimés.
+ *
+ * On évite donc une instanciation inutile.
+ */
- access->base = base;
- g_object_ref(G_OBJECT(base));
+ /*
+ 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 = src->next;
+ g_object_ref(src->next);
+ }
}
/******************************************************************************
* *
-* Paramètres : access = expression d'appel à compléter. *
-* next = expression d'appel suivante dans la chaîne. *
+* Paramètres : accès = expression d'accès à copier. *
+* resolved = nouvelle base à imposer. *
* *
-* Description : Complète la chaine d'accès à des expressions. *
+* Description : Reproduit un accès en place dans une nouvelle instance. *
* *
-* Retour : - *
+* Retour : Nouvelle instance d'expression d'accès. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_named_access_attach_next(GNamedAccess *access, GNamedAccess *next)
+GScanExpression *g_scan_named_access_duplicate(const GScanNamedAccess *access, GRegisteredItem *resolved)
{
- if (access->next != NULL)
- g_named_access_attach_next(access->next, next);
+ GScanExpression *result; /* Instance copiée à retourner */
+ GType type; /* Type d'objet à copier */
+ GScanNamedAccessClass *class; /* Classe à activer */
- else
- {
- access->next = next;
- g_object_ref(G_OBJECT(next));
- }
+ type = G_TYPE_FROM_INSTANCE(access);
-}
+ result = g_object_new(type, NULL);
+ class = G_SCAN_NAMED_ACCESS_GET_CLASS(access);
+ class->copy(G_SCAN_NAMED_ACCESS(result), access);
-/* ---------------------------------------------------------------------------------- */
-/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
-/* ---------------------------------------------------------------------------------- */
+ g_scan_named_access_set_base(G_SCAN_NAMED_ACCESS(result), resolved);
+
+ return result;
+
+}
/******************************************************************************
* *
-* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
-* src = expression source à copier. *
+* Paramètres : access = expression d'appel à actualiser. *
+* base = zone de recherche pour la résolution à venir. *
* *
-* Description : Reproduit une expression en place dans une nouvelle instance.*
+* Description : Définit une base de recherche pour la cible d'accès. *
* *
* Retour : - *
* *
@@ -293,27 +312,47 @@ void g_named_access_attach_next(GNamedAccess *access, GNamedAccess *next)
* *
******************************************************************************/
-static void g_named_access_copy(GNamedAccess *dest, const GNamedAccess *src)
+void g_scan_named_access_set_base(GScanNamedAccess *access, GRegisteredItem *base)
{
- GScanExpressionClass *class; /* Classe parente à solliciter */
+ g_clear_object(&access->base);
- class = G_SCAN_EXPRESSION_CLASS(g_named_access_parent_class);
+ access->base = base;
+ g_object_ref(G_OBJECT(base));
- class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
+}
- if (src->any != NULL)
+
+/******************************************************************************
+* *
+* 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_scan_named_access_attach_next(GScanNamedAccess *access, GScanNamedAccess *next)
+{
+ if (access->next != NULL)
+ g_scan_named_access_attach_next(access->next, next);
+
+ else
{
- dest->any = src->any;
- g_object_ref(src->any);
+ access->next = next;
+ g_object_ref(G_OBJECT(next));
}
- 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)));
-}
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
/******************************************************************************
@@ -321,24 +360,21 @@ static void g_named_access_copy(GNamedAccess *dest, const GNamedAccess *src)
* 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. *
+* Description : Prépare une réduction en menant une résolution locale. *
* *
-* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* Retour : Elément résolu avec les moyens du bord ou NULL si échec. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool _g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+GRegisteredItem *_g_scan_named_access_prepare_reduction(GScanNamedAccess *expr, GScanContext *ctx, GScanScope *scope)
{
- bool result; /* Bilan à retourner */
+ GRegisteredItem *result; /* Etat synthétisé à retourner */
GRegisteredItem *base; /* Base de recherche courante */
- GRegisteredItem *resolved; /* Cible concrète obtenue */
- GNamedAccess *new; /* Copie mise en place */
- result = true;
+ result = NULL;
if (expr->target != NULL)
{
@@ -350,24 +386,7 @@ bool _g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *s
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);
-
- }
+ g_registered_item_resolve(base, expr->target, ctx, scope, &result);
}
@@ -379,8 +398,8 @@ bool _g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *s
{
assert(expr->resolved != NULL);
- *out = G_SCAN_EXPRESSION(expr);
- g_object_ref(G_OBJECT(*out));
+ result = expr->resolved;
+ g_object_ref(G_OBJECT(result));
}
@@ -404,25 +423,18 @@ bool _g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *s
* *
******************************************************************************/
-static bool g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static ScanReductionState g_scan_named_access_reduce(GScanNamedAccess *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- bool result; /* Bilan à retourner */
- GNamedAccess *new; /* Eventuel étage suivant */
- GScanExpression *final; /* Expression d'évaluation */
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GRegisteredItem *resolved; /* Cible concrète obtenue */
GScanExpression *new_next; /* Nouvelle version du suivant */
+ bool status; /* Bilan d'une autre règle */
- result = _g_named_access_reduce(expr, ctx, scope, out);
+ resolved = _g_scan_named_access_prepare_reduction(expr, ctx, scope);
- if (result && *out != NULL)
+ if (resolved != 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));
+ result = SRS_PENDING;
/**
* Si l'élément résolu se trouve en fin de chaîne, alors cet élément
@@ -430,15 +442,11 @@ static bool g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanSc
* 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)
+ if (expr->next == NULL)
{
- result = g_registered_item_reduce(new->resolved, ctx, scope, &final);
+ status = g_registered_item_reduce(resolved, ctx, scope, out);
- if (result && final != NULL)
- {
- g_clear_object(out);
- *out = final;
- }
+ result = (status ? SRS_REDUCED : SRS_UNRESOLVABLE);
}
@@ -448,21 +456,34 @@ static bool g_named_access_reduce(GNamedAccess *expr, GScanContext *ctx, GScanSc
*/
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);
+ new_next = g_scan_named_access_duplicate(expr->next, resolved);
result = g_scan_expression_reduce(new_next, ctx, scope, out);
- if (result && *out == NULL)
- *out = new_next;
+ g_object_unref(G_OBJECT(new_next));
}
- g_object_unref(G_OBJECT(new));
+ g_object_unref(G_OBJECT(resolved));
+
+ }
+
+ /**
+ * Si le nom fournit le correspond à aucun élément de la grammaire,
+ * des recherches sont menées ailleurs.
+ */
+ else
+ {
+ result = SRS_UNRESOLVABLE;
+
+ if (g_scan_context_has_rule_for_name(ctx, expr->target))
+ {
+ status = g_scan_context_has_match_for_rule(ctx, expr->target);
+
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
+ result = SRS_REDUCED;
+
+ }
}
diff --git a/src/analysis/scan/exprs/access.h b/src/analysis/scan/exprs/access.h
index a04adc7..7c007a9 100644
--- a/src/analysis/scan/exprs/access.h
+++ b/src/analysis/scan/exprs/access.h
@@ -31,32 +31,35 @@
-#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))
+#define G_TYPE_SCAN_NAMED_ACCESS g_scan_named_access_get_type()
+#define G_SCAN_NAMED_ACCESS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_NAMED_ACCESS, GScanNamedAccess))
+#define G_IS_SCAN_NAMED_ACCESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_NAMED_ACCESS))
+#define G_SCAN_NAMED_ACCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_NAMED_ACCESS, GScanNamedAccessClass))
+#define G_IS_SCAN_NAMED_ACCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_NAMED_ACCESS))
+#define G_SCAN_NAMED_ACCESS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_NAMED_ACCESS, GScanNamedAccessClass))
/* Accès à un élément d'expression sous-jacent (instance) */
-typedef struct _GNamedAccess GNamedAccess;
+typedef struct _GScanNamedAccess GScanNamedAccess;
/* Accès à un élément d'expression sous-jacent (classe) */
-typedef struct _GNamedAccessClass GNamedAccessClass;
+typedef struct _GScanNamedAccessClass GScanNamedAccessClass;
/* Indique le type défini pour un appel de fonction enregistrée. */
-GType g_named_access_get_type(void);
+GType g_scan_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 *);
+GScanExpression *g_scan_named_access_new(const sized_string_t *);
+
+/* Reproduit un accès en place dans une nouvelle instance. */
+GScanExpression *g_scan_named_access_duplicate(const GScanNamedAccess *, GRegisteredItem *);
/* Définit une base de recherche pour la cible d'accès. */
-void g_named_access_set_base(GNamedAccess *, GRegisteredItem *);
+void g_scan_named_access_set_base(GScanNamedAccess *, GRegisteredItem *);
/* Complète la chaine d'accès à des expressions. */
-void g_named_access_attach_next(GNamedAccess *, GNamedAccess *);
+void g_scan_named_access_attach_next(GScanNamedAccess *, GScanNamedAccess *);
diff --git a/src/analysis/scan/exprs/arithmop-int.h b/src/analysis/scan/exprs/arithmetic-int.h
index 031de84..c5010b0 100644
--- a/src/analysis/scan/exprs/arithmop-int.h
+++ b/src/analysis/scan/exprs/arithmetic-int.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * arithmop-int.h - prototypes internes pour la gestion des opérations arithmétiques
+ * arithmetic-int.h - prototypes internes pour la gestion des opérations arithmétiques
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,11 +21,11 @@
*/
-#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMOP_INT_H
-#define _ANALYSIS_SCAN_EXPRS_ARITHMOP_INT_H
+#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMETIC_INT_H
+#define _ANALYSIS_SCAN_EXPRS_ARITHMETIC_INT_H
-#include "arithmop.h"
+#include "arithmetic.h"
#include "../expr-int.h"
@@ -33,7 +33,7 @@
/* Opération arithmétique impliquant deux opérandes (instance) */
-struct _GArithmOperation
+struct _GScanArithmeticOperation
{
GScanExpression parent; /* A laisser en premier */
@@ -45,7 +45,7 @@ struct _GArithmOperation
};
/* Opération arithmétique impliquant deux opérandes (classe) */
-struct _GArithmOperationClass
+struct _GScanArithmeticOperationClass
{
GScanExpressionClass parent; /* A laisser en premier */
@@ -53,8 +53,8 @@ struct _GArithmOperationClass
/* Met en place une opération arithmétique entre expressions. */
-bool g_arithmetic_operation_create(GArithmOperation *, ArithmeticExpressionOperator, GScanExpression *, GScanExpression *);
+bool g_scan_arithmetic_operation_create(GScanArithmeticOperation *, ArithmeticExpressionOperator, GScanExpression *, GScanExpression *);
-#endif /* _ANALYSIS_SCAN_EXPRS_ARITHMOP_INT_H */
+#endif /* _ANALYSIS_SCAN_EXPRS_ARITHMETIC_INT_H */
diff --git a/src/analysis/scan/exprs/arithmetic.c b/src/analysis/scan/exprs/arithmetic.c
new file mode 100644
index 0000000..0c01d2a
--- /dev/null
+++ b/src/analysis/scan/exprs/arithmetic.c
@@ -0,0 +1,638 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * arithmetic.c - gestion des opérations arithmétiques
+ *
+ * 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 "arithmetic.h"
+
+
+#include <assert.h>
+
+
+#include "arithmetic-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des opérations arithmétiques. */
+static void g_scan_arithmetic_operation_class_init(GScanArithmeticOperationClass *);
+
+/* Initialise une instance d'opération arithmétique. */
+static void g_scan_arithmetic_operation_init(GScanArithmeticOperation *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_arithmetic_operation_dispose(GScanArithmeticOperation *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_arithmetic_operation_finalize(GScanArithmeticOperation *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réalise une comparaison entre objets selon un critère précis. */
+static bool g_scan_arithmetic_operation_compare_rich(const GScanArithmeticOperation *, const GScanArithmeticOperation *, RichCmpOperation, bool *);
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_arithmetic_operation_reduce(GScanArithmeticOperation *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une opération de relation entre expressions. */
+G_DEFINE_TYPE(GScanArithmeticOperation, g_scan_arithmetic_operation, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérations arithmétiques. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_arithmetic_operation_class_init(GScanArithmeticOperationClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_arithmetic_operation_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_arithmetic_operation_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)g_scan_arithmetic_operation_compare_rich;
+ expr->reduce = (reduce_expr_fc)g_scan_arithmetic_operation_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opération arithmétique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_arithmetic_operation_init(GScanArithmeticOperation *op)
+{
+ op->left = NULL;
+ op->right = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_arithmetic_operation_dispose(GScanArithmeticOperation *op)
+{
+ g_clear_object(&op->left);
+ g_clear_object(&op->right);
+
+ G_OBJECT_CLASS(g_scan_arithmetic_operation_parent_class)->dispose(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_arithmetic_operation_finalize(GScanArithmeticOperation *op)
+{
+ G_OBJECT_CLASS(g_scan_arithmetic_operation_parent_class)->finalize(G_OBJECT(op));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operator = type d'opération arithmétique à représenter. *
+* left = premier opérande concerné. *
+* right = éventuel second opérande impliqué ou NULL. *
+* *
+* Description : Organise une opération arithmétique entre expressions. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_arithmetic_operation_new(ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_ARITHMETIC_OPERATION, NULL);
+
+ if (!g_scan_arithmetic_operation_create(G_SCAN_ARITHMETIC_OPERATION(result), operator, left, right))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser pleinement. *
+* operator = 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 arithmétique entre expressions. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_arithmetic_operation_create(GScanArithmeticOperation *op, ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ op->operator = operator;
+
+ op->left = left;
+ g_object_ref(G_OBJECT(op->left));
+
+ op->right = right;
+ g_object_ref(G_OBJECT(op->right));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = 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] *
+* *
+* Description : Réalise une comparaison entre objets selon un critère précis.*
+* *
+* Retour : true si la comparaison a pu être effectuée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_arithmetic_operation_compare_rich(const GScanArithmeticOperation *item, const GScanArithmeticOperation *other, RichCmpOperation op, bool *status)
+{
+ bool result; /* Etat à retourner */
+
+ result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_SCAN_ARITHMETIC_OPERATION);
+ if (!result) goto done;
+
+ if (item->operator != other->operator)
+ {
+ result = compare_rich_integer_values_unsigned(item->operator, other->operator, op);
+ goto done;
+ }
+
+ 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;
+
+ 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->right),
+ G_COMPARABLE_ITEM(other->right),
+ op, status);
+
+ done:
+
+ 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 ScanReductionState g_scan_arithmetic_operation_reduce(GScanArithmeticOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanExpression *new_left; /* Expression réduite (gauche) */
+ GScanExpression *new_right; /* Expression réduite (droite) */
+ ScanReductionState state_left; /* Etat synthétisé #1 */
+ ScanReductionState state_right; /* Etat synthétisé #2 */
+ GScanLiteralExpression *op_left; /* Opérande gauche final */
+ GScanLiteralExpression *op_right; /* Opérande droite final */
+ LiteralValueType vtype_left; /* Type de valeur portée #1 */
+ LiteralValueType vtype_right; /* Type de valeur portée #2 */
+ long long val_1_s; /* Première valeur à traiter */
+ unsigned long long val_1_u; /* Première valeur à traiter */
+ long long val_2_s; /* Seconde valeur à traiter */
+ unsigned long long val_2_u; /* Seconde valeur à traiter */
+ LiteralValueType state_final; /* Nature de la valeur finale */
+ long long reduced_s; /* Valeur réduite finale */
+ unsigned long long reduced_u; /* Valeur réduite finale */
+
+ /* Réduction des éléments considérés */
+
+ new_left = NULL;
+ new_right = NULL;
+
+ state_left = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
+ if (state_left == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ state_right = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
+ if (state_right == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ /* Construction d'une réduction locale ? */
+
+ if (G_IS_SCAN_LITERAL_EXPRESSION(new_left) && G_IS_SCAN_LITERAL_EXPRESSION(new_right))
+ {
+ /* Récupération de l'opérande de gauche */
+
+ op_left = G_SCAN_LITERAL_EXPRESSION(new_left);
+ vtype_left = g_scan_literal_expression_get_value_type(op_left);
+
+ if (vtype_left == LVT_SIGNED_INTEGER)
+ {
+ if (!g_scan_literal_expression_get_signed_integer_value(op_left, &val_1_s))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+ }
+ else if (vtype_left == LVT_UNSIGNED_INTEGER)
+ {
+ if (!g_scan_literal_expression_get_unsigned_integer_value(op_left, &val_1_u))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+ }
+ else
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ /* Récupération de l'opérande de droite */
+
+ op_right = G_SCAN_LITERAL_EXPRESSION(new_right);
+ vtype_right = g_scan_literal_expression_get_value_type(op_right);
+
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ if (!g_scan_literal_expression_get_signed_integer_value(op_right, &val_2_s))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+ }
+ else if (vtype_right == LVT_UNSIGNED_INTEGER)
+ {
+ if (!g_scan_literal_expression_get_unsigned_integer_value(op_right, &val_2_u))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+ }
+ else
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ /* Partie des calculs */
+
+ result = SRS_REDUCED;
+
+ switch (expr->operator)
+ {
+ case AEO_PLUS:
+ if (vtype_left == LVT_SIGNED_INTEGER)
+ {
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_s + val_2_s;
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ if ((long long)val_2_u > val_1_s)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_s + (long long)val_2_u;
+ }
+ else
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_s + (long long)val_2_u;
+ }
+
+ }
+ }
+ else
+ {
+ assert(vtype_left == LVT_UNSIGNED_INTEGER);
+
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ if ((long long)val_1_u > val_2_s)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = (long long)val_1_u + val_2_s;
+ }
+ else
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = (long long)val_1_u + val_2_s;
+ }
+
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_u + val_2_u;
+
+ }
+ }
+ break;
+
+ case AEO_MINUS:
+ if (vtype_left == LVT_SIGNED_INTEGER)
+ {
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ if (val_2_s < val_1_s)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_s - val_2_s;
+ }
+ else
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_s - val_2_s;
+ }
+
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_s - (long long)val_2_u;
+
+ }
+ }
+ else
+ {
+ assert(vtype_left == LVT_UNSIGNED_INTEGER);
+
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = (long long)val_1_u - val_2_s;
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ if (val_1_u > val_2_u)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_u - val_2_u;
+ }
+ else
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_u - val_2_u;
+ }
+
+ }
+ }
+ break;
+
+ case AEO_MUL:
+ if (vtype_left == LVT_SIGNED_INTEGER)
+ {
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_s * val_2_s;
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_s * (long long)val_2_u;
+
+ }
+ }
+ else
+ {
+ assert(vtype_left == LVT_UNSIGNED_INTEGER);
+
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = (long long)val_1_u * val_2_s;
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_u * val_2_u;
+
+ }
+ }
+ break;
+
+ case AEO_DIV:
+ if ((vtype_right == LVT_SIGNED_INTEGER && val_2_s == 0)
+ || (vtype_right == LVT_UNSIGNED_INTEGER && val_2_u == 0))
+ {
+ result = SRS_UNRESOLVABLE;
+ break;
+ }
+
+ if (vtype_left == LVT_SIGNED_INTEGER)
+ {
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_s / val_2_s;
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = val_1_s / (long long)val_2_u;
+
+ }
+ }
+ else
+ {
+ assert(vtype_left == LVT_UNSIGNED_INTEGER);
+
+ if (vtype_right == LVT_SIGNED_INTEGER)
+ {
+ state_final = LVT_SIGNED_INTEGER;
+ reduced_s = (long long)val_1_u / val_2_s;
+ }
+ else
+ {
+ assert(vtype_right == LVT_UNSIGNED_INTEGER);
+
+ state_final = LVT_UNSIGNED_INTEGER;
+ reduced_u = val_1_u / val_2_u;
+
+ }
+ }
+ break;
+
+ case AEO_MOD:
+ result = SRS_UNRESOLVABLE;
+ /* FIXME
+ result = (val_2 != 0);
+ if (result)
+ reduced = val_1 % val_2;
+ */
+ break;
+
+ }
+
+ if (result == SRS_REDUCED)
+ {
+ if (state_final == LVT_SIGNED_INTEGER)
+ *out = g_scan_literal_expression_new(LVT_SIGNED_INTEGER, &reduced_s);
+ else
+ {
+ assert(state_final == LVT_UNSIGNED_INTEGER);
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &reduced_u);
+ }
+
+ }
+
+ }
+
+ /* Mise à jour de la progression ? */
+
+ else if (state_left == SRS_WAIT_FOR_SCAN || state_right == SRS_WAIT_FOR_SCAN)
+ {
+ if (new_left != expr->left || new_right != expr->right)
+ *out = g_scan_arithmetic_operation_new(expr->operator, new_left, new_right);
+
+ result = SRS_WAIT_FOR_SCAN;
+
+ }
+
+ /* Cas des situations où les expressions ne sont pas exploitables (!) */
+ else
+ {
+ assert(state_left == SRS_REDUCED && state_right == SRS_REDUCED);
+
+ result = SRS_UNRESOLVABLE;
+
+ }
+
+ /* Sortie propre */
+
+ exit:
+
+ g_clear_object(&new_left);
+ g_clear_object(&new_right);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/arithmop.h b/src/analysis/scan/exprs/arithmetic.h
index dcc8bf8..8a1e844 100644
--- a/src/analysis/scan/exprs/arithmop.h
+++ b/src/analysis/scan/exprs/arithmetic.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * arithmop.h - prototypes pour la gestion des opérations arithmétiques
+ * arithmetic.h - prototypes pour la gestion des opérations arithmétiques
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,27 +21,27 @@
*/
-#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMOP_H
-#define _ANALYSIS_SCAN_EXPRS_ARITHMOP_H
+#ifndef _ANALYSIS_SCAN_EXPRS_ARITHMETIC_H
+#define _ANALYSIS_SCAN_EXPRS_ARITHMETIC_H
#include "../expr.h"
-#define G_TYPE_ARITHMETIC_OPERATION g_arithmetic_operation_get_type()
-#define G_ARITHMETIC_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARITHMETIC_OPERATION, GArithmOperation))
-#define G_IS_ARITHMETIC_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARITHMETIC_OPERATION))
-#define G_ARITHMETIC_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARITHMETIC_OPERATION, GArithmOperationClass))
-#define G_IS_ARITHMETIC_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARITHMETIC_OPERATION))
-#define G_ARITHMETIC_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARITHMETIC_OPERATION, GArithmOperationClass))
+#define G_TYPE_SCAN_ARITHMETIC_OPERATION g_scan_arithmetic_operation_get_type()
+#define G_SCAN_ARITHMETIC_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_ARITHMETIC_OPERATION, GScanArithmeticOperation))
+#define G_IS_SCAN_ARITHMETIC_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_ARITHMETIC_OPERATION))
+#define G_SCAN_ARITHMETIC_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_ARITHMETIC_OPERATION, GScanArithmeticOperationClass))
+#define G_IS_SCAN_ARITHMETIC_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_ARITHMETIC_OPERATION))
+#define G_SCAN_ARITHMETIC_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_ARITHMETIC_OPERATION, GScanArithmeticOperationClass))
/* Opération arithmétique impliquant deux opérandes (instance) */
-typedef struct _GArithmOperation GArithmOperation;
+typedef struct _GScanArithmeticOperation GScanArithmeticOperation;
/* Opération arithmétique impliquant deux opérandes (classe) */
-typedef struct _GArithmOperationClass GArithmOperationClass;
+typedef struct _GScanArithmeticOperationClass GScanArithmeticOperationClass;
/* Type d'opération arithmétique */
@@ -57,11 +57,11 @@ typedef enum _ArithmeticExpressionOperator
/* Indique le type défini pour une opération arithmétique entre expressions. */
-GType g_arithmetic_operation_get_type(void);
+GType g_scan_arithmetic_operation_get_type(void);
/* Organise une opération arithmétique entre expressions. */
-GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator, GScanExpression *, GScanExpression *);
+GScanExpression *g_scan_arithmetic_operation_new(ArithmeticExpressionOperator, GScanExpression *, GScanExpression *);
-#endif /* _ANALYSIS_SCAN_EXPRS_ARITHMOP_H */
+#endif /* _ANALYSIS_SCAN_EXPRS_ARITHMETIC_H */
diff --git a/src/analysis/scan/exprs/call-int.h b/src/analysis/scan/exprs/call-int.h
index 631a25b..9646b95 100644
--- a/src/analysis/scan/exprs/call-int.h
+++ b/src/analysis/scan/exprs/call-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* call-int.h - prototypes internes pour l'organisation d'un appel à un élément de scan enregistré
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -33,9 +33,9 @@
/* Exécution d'une fonction auxiliaire d'analyse (instance) */
-struct _GPendingCall
+struct _GScanPendingCall
{
- GNamedAccess parent; /* A laisser en premier */
+ GScanNamedAccess parent; /* A laisser en premier */
GScanExpression **args; /* Arguments d'appel fournis */
size_t count; /* Quantité de ces arguments */
@@ -43,15 +43,15 @@ struct _GPendingCall
};
/* Exécution d'une fonction auxiliaire d'analyse (classe) */
-struct _GPendingCallClass
+struct _GScanPendingCallClass
{
- GNamedAccessClass parent; /* A laisser en premier */
+ GScanNamedAccessClass parent; /* A laisser en premier */
};
/* Met en place une expression d'appel. */
-bool g_pending_call_create(GPendingCall *, const sized_string_t *, GScanExpression **, size_t);
+bool g_scan_pending_call_create(GScanPendingCall *, const sized_string_t *, GScanExpression **, size_t);
diff --git a/src/analysis/scan/exprs/call.c b/src/analysis/scan/exprs/call.c
index dde627c..2fd1ff1 100644
--- a/src/analysis/scan/exprs/call.c
+++ b/src/analysis/scan/exprs/call.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* call.c - organisation d'un appel à un élément de scan enregistré
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -38,27 +38,27 @@
/* Initialise la classe des appels de fonction avec arguments. */
-static void g_pending_call_class_init(GPendingCallClass *);
+static void g_scan_pending_call_class_init(GScanPendingCallClass *);
/* Initialise une instance d'appel de fonction avec arguments. */
-static void g_pending_call_init(GPendingCall *);
+static void g_scan_pending_call_init(GScanPendingCall *);
/* Supprime toutes les références externes. */
-static void g_pending_call_dispose(GPendingCall *);
+static void g_scan_pending_call_dispose(GScanPendingCall *);
/* Procède à la libération totale de la mémoire. */
-static void g_pending_call_finalize(GPendingCall *);
+static void g_scan_pending_call_finalize(GScanPendingCall *);
/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_pending_call_copy(GPendingCall *, const GPendingCall *);
-
/* Réduit une expression à une forme plus simple. */
-static bool g_pending_call_reduce(GPendingCall *, GScanContext *, GScanScope *, GScanExpression **);
+static ScanReductionState g_scan_pending_call_reduce(GScanPendingCall *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Reproduit un accès en place dans une nouvelle instance. */
+static void g_scan_pending_call_copy(GScanPendingCall *, const GScanPendingCall *);
@@ -68,7 +68,7 @@ static bool g_pending_call_reduce(GPendingCall *, GScanContext *, GScanScope *,
/* Indique le type défini pour un appel de fonction enregistrée. */
-G_DEFINE_TYPE(GPendingCall, g_pending_call, G_TYPE_NAMED_ACCESS);
+G_DEFINE_TYPE(GScanPendingCall, g_scan_pending_call, G_TYPE_SCAN_NAMED_ACCESS);
/******************************************************************************
@@ -83,21 +83,25 @@ G_DEFINE_TYPE(GPendingCall, g_pending_call, G_TYPE_NAMED_ACCESS);
* *
******************************************************************************/
-static void g_pending_call_class_init(GPendingCallClass *klass)
+static void g_scan_pending_call_class_init(GScanPendingCallClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GScanExpressionClass *expr; /* Version de classe parente */
+ GScanNamedAccessClass *access; /* Autre version de la classe */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_pending_call_dispose;
- object->finalize = (GObjectFinalizeFunc)g_pending_call_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_pending_call_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_pending_call_finalize;
expr = G_SCAN_EXPRESSION_CLASS(klass);
expr->cmp_rich = (compare_expr_rich_fc)NULL;
- expr->copy = (copy_expr_fc)g_pending_call_copy;
- expr->reduce = (reduce_expr_fc)g_pending_call_reduce;
+ expr->reduce = (reduce_expr_fc)g_scan_pending_call_reduce;
+
+ access = G_SCAN_NAMED_ACCESS_CLASS(klass);
+
+ access->copy = (copy_scan_access_fc)g_scan_pending_call_copy;
}
@@ -114,7 +118,7 @@ static void g_pending_call_class_init(GPendingCallClass *klass)
* *
******************************************************************************/
-static void g_pending_call_init(GPendingCall *call)
+static void g_scan_pending_call_init(GScanPendingCall *call)
{
call->args = NULL;
call->count = 0;
@@ -134,14 +138,14 @@ static void g_pending_call_init(GPendingCall *call)
* *
******************************************************************************/
-static void g_pending_call_dispose(GPendingCall *call)
+static void g_scan_pending_call_dispose(GScanPendingCall *call)
{
size_t i; /* Boucle de parcours */
for (i = 0; i < call->count; i++)
g_clear_object(&call->args[i]);
- G_OBJECT_CLASS(g_pending_call_parent_class)->dispose(G_OBJECT(call));
+ G_OBJECT_CLASS(g_scan_pending_call_parent_class)->dispose(G_OBJECT(call));
}
@@ -158,12 +162,12 @@ static void g_pending_call_dispose(GPendingCall *call)
* *
******************************************************************************/
-static void g_pending_call_finalize(GPendingCall *call)
+static void g_scan_pending_call_finalize(GScanPendingCall *call)
{
if (call->args != NULL)
free(call->args);
- G_OBJECT_CLASS(g_pending_call_parent_class)->finalize(G_OBJECT(call));
+ G_OBJECT_CLASS(g_scan_pending_call_parent_class)->finalize(G_OBJECT(call));
}
@@ -182,13 +186,13 @@ static void g_pending_call_finalize(GPendingCall *call)
* *
******************************************************************************/
-GScanExpression *g_pending_call_new(const sized_string_t *target, GScanExpression **args, size_t count)
+GScanExpression *g_scan_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);
+ result = g_object_new(G_TYPE_SCAN_PENDING_CALL, NULL);
- if (!g_pending_call_create(G_PENDING_CALL(result), target, args, count))
+ if (!g_scan_pending_call_create(G_SCAN_PENDING_CALL(result), target, args, count))
g_clear_object(&result);
return result;
@@ -211,12 +215,12 @@ GScanExpression *g_pending_call_new(const sized_string_t *target, GScanExpressio
* *
******************************************************************************/
-bool g_pending_call_create(GPendingCall *call, const sized_string_t *target, GScanExpression **args, size_t count)
+bool g_scan_pending_call_create(GScanPendingCall *call, const sized_string_t *target, GScanExpression **args, size_t count)
{
bool result; /* Bilan à retourner */
size_t i; /* Boucle de parcours */
- result = g_named_access_create(G_NAMED_ACCESS(call), target);
+ result = g_scan_named_access_create(G_SCAN_NAMED_ACCESS(call), target);
if (!result) goto exit;
call->args = malloc(count * sizeof(GScanExpression *));
@@ -243,37 +247,6 @@ bool g_pending_call_create(GPendingCall *call, const sized_string_t *target, GSc
/******************************************************************************
* *
-* 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_pending_call_copy(GPendingCall *dest, const GPendingCall *src)
-{
- GScanExpressionClass *class; /* Classe parente à solliciter */
- size_t i; /* Boucle de parcours */
-
- class = G_SCAN_EXPRESSION_CLASS(g_pending_call_parent_class);
-
- 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]);
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : expr = expression à consulter. *
* ctx = contexte de suivi de l'analyse courante. *
* scope = portée courante des variables locales. *
@@ -287,89 +260,196 @@ static void g_pending_call_copy(GPendingCall *dest, const GPendingCall *src)
* *
******************************************************************************/
-static bool g_pending_call_reduce(GPendingCall *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static ScanReductionState g_scan_pending_call_reduce(GScanPendingCall *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- bool result; /* Bilan à retourner */
- GNamedAccess *new; /* Eventuel étage suivant */
- GPendingCall *new_call; /* Version en appel */
- size_t i; /* Boucle de parcours */
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanNamedAccess *access; /* Autre vision de l'expression*/
+ GRegisteredItem *resolved; /* Cible concrète obtenue */
+ size_t i; /* Boucle de parcours #1 */
GScanExpression *arg; /* Argument réduit à échanger */
- GObject *final; /* Expression ou élément ? */
+ GScanExpression *new; /* Nouvelle réduction obtenue */
+ ScanReductionState state; /* Etat synthétisé d'un élément*/
+ size_t k; /* Boucle de parcours #2 */
+ GScanExpression **new_args; /* Nouvelle séquence d'args. */
GScanExpression *new_next; /* Nouvelle version du suivant */
+ GObject *final; /* Expression ou élément ? */
+ bool valid; /* Validité de l'élément */
- result = _g_named_access_reduce(G_NAMED_ACCESS(expr), ctx, scope, out);
+ access = G_SCAN_NAMED_ACCESS(expr);
- if (result && *out != NULL)
- {
- assert(G_IS_NAMED_ACCESS(*out));
+ resolved = _g_scan_named_access_prepare_reduction(access, ctx, scope);
+
+ if (resolved == NULL)
+ result = SRS_UNRESOLVABLE;
- new = G_NAMED_ACCESS(*out);
- *out = NULL;
+ else
+ {
+ result = SRS_PENDING;
- assert(new->target == NULL);
- assert(G_IS_PENDING_CALL(new));
- assert(G_IS_REGISTERED_ITEM(new->resolved));
+ /* Actualisation nécessaire des arguments ? */
- new_call = G_PENDING_CALL(new);
+ new_args = NULL;
- for (i = 0; i < new_call->count; i++)
+ for (i = 0; i < expr->count; i++)
{
- result = g_scan_expression_reduce(new_call->args[i], ctx, scope, &arg);
- if (!result) goto exit;
+ arg = expr->args[i];
- if (arg != NULL)
+ state = g_scan_expression_reduce(arg, ctx, scope, &new);
+ if (state == SRS_UNRESOLVABLE)
{
- g_object_unref(G_OBJECT(new_call->args[i]));
- new_call->args[i] = arg;
+ result = SRS_UNRESOLVABLE;
+ break;
}
+ if (state == SRS_WAIT_FOR_SCAN)
+ result = SRS_WAIT_FOR_SCAN;
+
+ if (new != arg)
+ {
+ if (new_args == NULL)
+ {
+ new_args = calloc(expr->count, sizeof(GScanExpression *));
+
+ for (k = 0; k < i; k++)
+ {
+ new_args[k] = expr->args[i];
+ g_object_ref(G_OBJECT(new_args[k]));
+ }
+
+ }
+
+ new_args[i] = new;
+
+ }
+
+ else
+ {
+ if (new_args != NULL)
+ new_args[i] = new;
+ }
}
- result = g_registered_item_run_call(new->resolved,
- new_call->args,
- new_call->count,
- ctx, scope, &final);
+ /* Suite des traitements */
- if (result && final != NULL)
+ if (result == SRS_WAIT_FOR_SCAN)
{
/**
- * 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.
+ * Si changement il y a eu...
*/
- if (!G_IS_REGISTERED_ITEM(final))
+ if (new_args != NULL)
{
- assert(new->next == NULL);
- *out = G_SCAN_EXPRESSION(final);
+ *out = g_scan_pending_call_new(NULL, new_args, expr->count);
+
+ /**
+ * Fonctionnement équivalent de :
+ * g_scan_named_access_set_base(G_SCAN_NAMED_ACCESS(*out), resolved);
+ */
+ G_SCAN_NAMED_ACCESS(*out)->resolved = resolved;
+ g_object_ref(G_OBJECT(resolved));
+
+ if (G_SCAN_NAMED_ACCESS(expr)->next != NULL)
+ g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS(*out), G_SCAN_NAMED_ACCESS(expr)->next);
+
}
+
+ }
+
+ else if (result == SRS_PENDING)
+ {
+ if (new_args == NULL)
+ valid = g_registered_item_run_call(resolved,
+ expr->args,
+ expr->count,
+ ctx, scope, &final);
else
- {
- assert(new->next != NULL);
+ valid = g_registered_item_run_call(resolved,
+ new_args,
+ expr->count,
+ ctx, scope, &final);
- new_next = g_scan_expression_duplicate(G_SCAN_EXPRESSION(new->next));
- assert(G_IS_NAMED_ACCESS(new_next));
+ if (valid && 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(access->next == NULL);
- g_named_access_set_base(G_NAMED_ACCESS(new_next), G_REGISTERED_ITEM(final));
+ *out = G_SCAN_EXPRESSION(final);
- result = g_scan_expression_reduce(new_next, ctx, scope, out);
+ result = SRS_REDUCED;
- if (result && *out == NULL)
- *out = new_next;
+ }
else
+ {
+ assert(access->next != NULL);
+
+ new_next = g_scan_named_access_duplicate(access->next, resolved);
+
+ result = g_scan_expression_reduce(new_next, ctx, scope, out);
+
g_object_unref(G_OBJECT(new_next));
+ }
+
}
+ else
+ result = SRS_UNRESOLVABLE;
+
}
- exit:
+ /* Libération locale des arguments reconstruits */
- g_object_unref(G_OBJECT(new));
+ if (new_args != NULL)
+ {
+ for (i = 0; i < expr->count; i++)
+ g_clear_object(&new_args[i]);
+ }
+
+ g_object_unref(G_OBJECT(resolved));
}
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
+* src = expression source à copier. *
+* *
+* Description : Reproduit un accès en place dans une nouvelle instance. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pending_call_copy(GScanPendingCall *dest, const GScanPendingCall *src)
+{
+ GScanNamedAccessClass *class; /* Classe parente à solliciter */
+ size_t i; /* Boucle de parcours */
+
+ class = G_SCAN_NAMED_ACCESS_CLASS(g_scan_pending_call_parent_class);
+
+ class->copy(G_SCAN_NAMED_ACCESS(dest), G_SCAN_NAMED_ACCESS(src));
+
+ dest->args = malloc(src->count * sizeof(GScanExpression *));
+ dest->count = src->count;
+
+ for (i = 0; i < src->count; i++)
+ {
+ dest->args[i] = src->args[i];
+ g_object_ref(G_OBJECT(src->args[i]));
+ }
+
+}
diff --git a/src/analysis/scan/exprs/call.h b/src/analysis/scan/exprs/call.h
index c344036..c4d8964 100644
--- a/src/analysis/scan/exprs/call.h
+++ b/src/analysis/scan/exprs/call.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* call.h - prototypes pour l'organisation d'un appel à un élément de scan enregistré
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -30,26 +30,26 @@
-#define G_TYPE_PENDING_CALL g_pending_call_get_type()
-#define G_PENDING_CALL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PENDING_CALL, GPendingCall))
-#define G_IS_PENDING_CALL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PENDING_CALL))
-#define G_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PENDING_CALL, GPendingCallClass))
-#define G_IS_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PENDING_CALL))
-#define G_PENDING_CALL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PENDING_CALL, GPendingCallClass))
+#define G_TYPE_SCAN_PENDING_CALL g_scan_pending_call_get_type()
+#define G_SCAN_PENDING_CALL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_PENDING_CALL, GScanPendingCall))
+#define G_IS_SCAN_PENDING_CALL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_PENDING_CALL))
+#define G_SCAN_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_PENDING_CALL, GScanPendingCallClass))
+#define G_IS_SCAN_PENDING_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_PENDING_CALL))
+#define G_SCAN_PENDING_CALL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_PENDING_CALL, GScanPendingCallClass))
/* Exécution d'une fonction auxiliaire d'analyse (instance) */
-typedef struct _GPendingCall GPendingCall;
+typedef struct _GScanPendingCall GScanPendingCall;
/* Exécution d'une fonction auxiliaire d'analyse (classe) */
-typedef struct _GPendingCallClass GPendingCallClass;
+typedef struct _GScanPendingCallClass GScanPendingCallClass;
/* Indique le type défini pour un appel de fonction enregistrée. */
-GType g_pending_call_get_type(void);
+GType g_scan_pending_call_get_type(void);
/* Organise un appel de fonction avec ses arguments. */
-GScanExpression *g_pending_call_new(const sized_string_t *, GScanExpression **, size_t);
+GScanExpression *g_scan_pending_call_new(const sized_string_t *, GScanExpression **, size_t);
diff --git a/src/analysis/scan/exprs/counter-int.h b/src/analysis/scan/exprs/counter-int.h
new file mode 100644
index 0000000..8c5e56b
--- /dev/null
+++ b/src/analysis/scan/exprs/counter-int.h
@@ -0,0 +1,57 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * counter-int.h - prototypes internes pour le décompte de correspondances identifiées dans du contenu binaire
+ *
+ * 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_COUNTER_INT_H
+#define _ANALYSIS_SCAN_EXPRS_COUNTER_INT_H
+
+
+#include "counter.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Décompte des identifications de motifs (instance) */
+struct _GScanMatchCounter
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ GSearchPattern *pattern; /* Motif associé */
+
+};
+
+/* Décompte des identifications de motifs (classe) */
+struct _GScanMatchCounterClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un compteur de correspondances. */
+bool g_scan_match_counter_create(GScanMatchCounter *, GSearchPattern *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_COUNTER_INT_H */
diff --git a/src/analysis/scan/exprs/counter.c b/src/analysis/scan/exprs/counter.c
new file mode 100644
index 0000000..290fd02
--- /dev/null
+++ b/src/analysis/scan/exprs/counter.c
@@ -0,0 +1,248 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * counter.c - décompte de correspondances identifiées dans du contenu binaire
+ *
+ * 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 "counter.h"
+
+
+#include "counter-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INSTANCIATION D'UNE FORME DE CONDITION --------------------- */
+
+
+/* Initialise la classe des opérations booléennes. */
+static void g_scan_match_counter_class_init(GScanMatchCounterClass *);
+
+/* Initialise une instance d'opération booléenne. */
+static void g_scan_match_counter_init(GScanMatchCounter *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_match_counter_dispose(GScanMatchCounter *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_match_counter_finalize(GScanMatchCounter *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_scan_match_counter_reduce(GScanMatchCounter *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INSTANCIATION D'UNE FORME DE CONDITION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un décompte de résultats lors d'une recherche de motifs. */
+G_DEFINE_TYPE(GScanMatchCounter, g_scan_match_counter, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérations booléennes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_match_counter_class_init(GScanMatchCounterClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_match_counter_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_match_counter_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)NULL;
+ expr->reduce = (reduce_expr_fc)g_scan_match_counter_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opération booléenne. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_match_counter_init(GScanMatchCounter *counter)
+{
+ counter->pattern = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_match_counter_dispose(GScanMatchCounter *counter)
+{
+ g_clear_object(&counter->pattern);
+
+ G_OBJECT_CLASS(g_scan_match_counter_parent_class)->dispose(G_OBJECT(counter));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_match_counter_finalize(GScanMatchCounter *counter)
+{
+ G_OBJECT_CLASS(g_scan_match_counter_parent_class)->finalize(G_OBJECT(counter));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pattern = motif à impliquer. *
+* *
+* Description : Met en place un décompte de correspondances obtenues. *
+* *
+* Retour : Expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_match_counter_new(GSearchPattern *pattern)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_MATCH_COUNTER, NULL);
+
+ if (!g_scan_match_counter_create(G_SCAN_MATCH_COUNTER(result), pattern))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : counter = instance à initialiser pleinement. *
+* pattern = motif à impliquer. *
+* *
+* Description : Met en place un compteur de correspondances. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_match_counter_create(GScanMatchCounter *counter, GSearchPattern *pattern)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ counter->pattern = pattern;
+ g_object_ref(G_OBJECT(pattern));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* 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_scan_match_counter_reduce(GScanMatchCounter *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+ size_t count; /* Quantité de correspondances */
+ const GScanMatch **matches; /* Correspondances établies */
+
+
+ matches = g_scan_context_get_full_matches(ctx, expr->pattern, &count);
+
+
+ printf("matches: %zu\n", count);
+
+
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ count });
+ result = true;
+
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/counter.h b/src/analysis/scan/exprs/counter.h
new file mode 100644
index 0000000..c90953e
--- /dev/null
+++ b/src/analysis/scan/exprs/counter.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * counter.h - prototypes pour le décompte de correspondances identifiées dans du contenu binaire
+ *
+ * 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_COUNTER_H
+#define _ANALYSIS_SCAN_EXPRS_COUNTER_H
+
+
+#include <glib-object.h>
+
+
+#include "../expr.h"
+#include "../pattern.h"
+
+
+
+#define G_TYPE_SCAN_MATCH_COUNTER g_scan_match_counter_get_type()
+#define G_SCAN_MATCH_COUNTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MATCH_COUNTER, GScanMatchCounter))
+#define G_IS_SCAN_MATCH_COUNTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MATCH_COUNTER))
+#define G_SCAN_MATCH_COUNTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MATCH_COUNTER, GScanMatchCounterClass))
+#define G_IS_SCAN_MATCH_COUNTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MATCH_COUNTER))
+#define G_SCAN_MATCH_COUNTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MATCH_COUNTER, GScanMatchCounterClass))
+
+
+/* Décompte des identifications de motifs (instance) */
+typedef struct _GScanMatchCounter GScanMatchCounter;
+
+/* Décompte des identifications de motifs (classe) */
+typedef struct _GScanMatchCounterClass GScanMatchCounterClass;
+
+
+/* Indique le type défini pour un décompte de résultats lors d'une recherche de motifs. */
+GType g_scan_match_counter_get_type(void);
+
+/* Met en place un décompte de correspondances obtenues. */
+GScanExpression *g_scan_match_counter_new(GSearchPattern *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_COUNTER_H */
diff --git a/src/analysis/scan/exprs/intersect-int.h b/src/analysis/scan/exprs/intersect-int.h
new file mode 100644
index 0000000..83e4251
--- /dev/null
+++ b/src/analysis/scan/exprs/intersect-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * intersect-int.h - prototypes internes pour l'intersection d'ensembles aux types indentiques
+ *
+ * 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_INTERSECT_INT_H
+#define _ANALYSIS_SCAN_EXPRS_INTERSECT_INT_H
+
+
+#include "intersect.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Opération d'intersection entre deux ensembles (instance) */
+struct _GScanSetsIntersection
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ GScanExpression *first; /* Expression impactée #1 */
+ GScanExpression *second; /* Expression impactée #2 */
+
+};
+
+/* Opération d'intersection entre deux ensembles (classe) */
+struct _GScanSetsIntersectionClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une expression d'opération booléenne. */
+bool g_scan_sets_intersection_create(GScanSetsIntersection *, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_INTERSECT_INT_H */
diff --git a/src/analysis/scan/exprs/intersect.c b/src/analysis/scan/exprs/intersect.c
new file mode 100644
index 0000000..f0660e0
--- /dev/null
+++ b/src/analysis/scan/exprs/intersect.c
@@ -0,0 +1,290 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * intersect.c - intersection d'ensembles aux types indentiques
+ *
+ * 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 "intersect.h"
+
+
+#include <assert.h>
+
+
+#include "intersect-int.h"
+#include "literal.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des intersections entre deux ensembles. */
+static void g_scan_sets_intersection_class_init(GScanSetsIntersectionClass *);
+
+/* Initialise une instance d'intersection entre deux ensembles. */
+static void g_scan_sets_intersection_init(GScanSetsIntersection *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_sets_intersection_dispose(GScanSetsIntersection *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_sets_intersection_finalize(GScanSetsIntersection *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_sets_intersection_reduce(GScanSetsIntersection *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une intersection entre deux ensembles. */
+G_DEFINE_TYPE(GScanSetsIntersection, g_scan_sets_intersection, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des intersections entre deux ensembles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sets_intersection_class_init(GScanSetsIntersectionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_sets_intersection_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_sets_intersection_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->reduce = (reduce_expr_fc)g_scan_sets_intersection_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : op = instance à initialiser. *
+* *
+* Description : Initialise une instance d'intersection entre deux ensembles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sets_intersection_init(GScanSetsIntersection *inter)
+{
+ inter->first = NULL;
+ inter->second = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : inter = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sets_intersection_dispose(GScanSetsIntersection *inter)
+{
+ g_clear_object(&inter->first);
+ g_clear_object(&inter->second);
+
+ G_OBJECT_CLASS(g_scan_sets_intersection_parent_class)->dispose(G_OBJECT(inter));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : inter = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_sets_intersection_finalize(GScanSetsIntersection *inter)
+{
+ G_OBJECT_CLASS(g_scan_sets_intersection_parent_class)->finalize(G_OBJECT(inter));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type d'opération booléenne à représenter. *
+* first = premier élément concerné. *
+* second = second élément concerné. *
+* *
+* Description : Organise une intersection entre deux ensembles. *
+* *
+* Retour : Expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_sets_intersection_new(GScanExpression *first, GScanExpression *second)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_SETS_INTERSECTION, NULL);
+
+ if (!g_scan_sets_intersection_create(G_SCAN_SETS_INTERSECTION(result), first, second))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : inter = instance à initialiser pleinement. *
+* first = premier élément concerné. *
+* second = second élément concerné. *
+* *
+* Description : Met en place une expression d'opération booléenne. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_sets_intersection_create(GScanSetsIntersection *inter, GScanExpression *first, GScanExpression *second)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ inter->first = first;
+ g_object_ref(G_OBJECT(first));
+
+ inter->second = second;
+ g_object_ref(G_OBJECT(second));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* 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 ScanReductionState g_scan_sets_intersection_reduce(GScanSetsIntersection *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanExpression *new_first; /* Nouvelle réduction #1 */
+ GScanExpression *new_second; /* Nouvelle réduction #2 */
+ ScanReductionState state_first; /* Etat synthétisé #1 */
+ ScanReductionState state_second; /* Etat synthétisé #2 */
+
+ new_first = NULL;
+ new_second = NULL;
+
+ state_first = g_scan_expression_reduce(expr->first, ctx, scope, &new_first);
+ if (state_first == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ state_second = g_scan_expression_reduce(expr->second, ctx, scope, &new_second);
+ if (state_second == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ if (state_first == SRS_WAIT_FOR_SCAN || state_second == SRS_WAIT_FOR_SCAN)
+ {
+ if (new_first != expr->first || new_second != expr->second)
+ *out = g_scan_sets_intersection_new(new_first, new_second);
+
+ result = SRS_WAIT_FOR_SCAN;
+
+ }
+
+ else
+ {
+ assert(state_first == SRS_REDUCED && state_second == SRS_REDUCED);
+
+ *out = g_scan_expression_intersect(new_first, new_second, ctx, scope);
+
+ result = (*out != NULL ? SRS_REDUCED : SRS_UNRESOLVABLE);
+
+ }
+
+ exit:
+
+ g_clear_object(&new_first);
+ g_clear_object(&new_second);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/intersect.h b/src/analysis/scan/exprs/intersect.h
new file mode 100644
index 0000000..56efdff
--- /dev/null
+++ b/src/analysis/scan/exprs/intersect.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * intersect.h - prototypes pour l'intersection d'ensembles aux types indentiques
+ *
+ * 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_INTERSECT_H
+#define _ANALYSIS_SCAN_EXPRS_INTERSECT_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_SETS_INTERSECTION g_scan_sets_intersection_get_type()
+#define G_SCAN_SETS_INTERSECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_SETS_INTERSECTION, GScanSetsIntersection))
+#define G_IS_SCAN_SETS_INTERSECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_SETS_INTERSECTION))
+#define G_SCAN_SETS_INTERSECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_SETS_INTERSECTION, GScanSetsIntersectionClass))
+#define G_IS_SCAN_SETS_INTERSECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_SETS_INTERSECTION))
+#define G_SCAN_SETS_INTERSECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_SETS_INTERSECTION, GScanSetsIntersectionClass))
+
+
+/* Opération d'intersection entre deux ensembles (instance) */
+typedef struct _GScanSetsIntersection GScanSetsIntersection;
+
+/* Opération d'intersection entre deux ensembles (classe) */
+typedef struct _GScanSetsIntersectionClass GScanSetsIntersectionClass;
+
+
+/* Indique le type défini pour une intersection entre deux ensembles. */
+GType g_scan_sets_intersection_get_type(void);
+
+/* Organise une intersection entre deux ensembles. */
+GScanExpression *g_scan_sets_intersection_new(GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_INTERSECT_H */
diff --git a/src/analysis/scan/exprs/literal-int.h b/src/analysis/scan/exprs/literal-int.h
index 875b3de..b0a0ec5 100644
--- a/src/analysis/scan/exprs/literal-int.h
+++ b/src/analysis/scan/exprs/literal-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* literal-int.h - prototypes internes pour la représentation d'une valeur concrète
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -28,24 +28,22 @@
#include "literal.h"
-#include <stdbool.h>
-
-
#include "../expr-int.h"
/* Expression portant une valeur concrète (instance) */
-struct _GLiteralExpression
+struct _GScanLiteralExpression
{
GScanExpression parent; /* A laisser en premier */
- ExprValueType value_type; /* Type de valeur portée */
+ LiteralValueType value_type; /* Type de valeur portée */
union
{
bool boolean; /* Valeur booléenne */
- unsigned long long integer; /* Valeur entière 64 bits */
+ long long s_integer; /* Valeur entière 64 bits */
+ unsigned long long u_integer; /* Valeur entière 64 bits */
sized_string_t string; /* Chaîne de caractères */
struct
{
@@ -58,7 +56,7 @@ struct _GLiteralExpression
};
/* Expression portant une valeur concrète (classe) */
-struct _GLiteralExpressionClass
+struct _GScanLiteralExpressionClass
{
GScanExpressionClass parent; /* A laisser en premier */
@@ -66,7 +64,7 @@ struct _GLiteralExpressionClass
/* Met en place une expression de valeur concrête. */
-bool g_literal_expression_create(GLiteralExpression *, ExprValueType, ...);
+bool g_scan_literal_expression_create(GScanLiteralExpression *, LiteralValueType, ...);
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;
diff --git a/src/analysis/scan/exprs/literal.h b/src/analysis/scan/exprs/literal.h
index 7120c07..9352baf 100644
--- a/src/analysis/scan/exprs/literal.h
+++ b/src/analysis/scan/exprs/literal.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* literal.h - prototypes pour la représentation d'une valeur concrète
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -26,6 +26,7 @@
#include <regex.h>
+#include <stdbool.h>
#include "../expr.h"
@@ -33,38 +34,56 @@
-#define G_TYPE_LITERAL_EXPRESSION g_literal_expression_get_type()
-#define G_LITERAL_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_LITERAL_EXPRESSION, GLiteralExpression))
-#define G_IS_LITERAL_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_LITERAL_EXPRESSION))
-#define G_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_LITERAL_EXPRESSION, GLiteralExpressionClass))
-#define G_IS_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_LITERAL_EXPRESSION))
-#define G_LITERAL_EXPRESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_LITERAL_EXPRESSION, GLiteralExpressionClass))
+#define G_TYPE_SCAN_LITERAL_EXPRESSION g_scan_literal_expression_get_type()
+#define G_SCAN_LITERAL_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_LITERAL_EXPRESSION, GScanLiteralExpression))
+#define G_IS_SCAN_LITERAL_EXPRESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_LITERAL_EXPRESSION))
+#define G_SCAN_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_LITERAL_EXPRESSION, GScanLiteralExpressionClass))
+#define G_IS_SCAN_LITERAL_EXPRESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_LITERAL_EXPRESSION))
+#define G_SCAN_LITERAL_EXPRESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_LITERAL_EXPRESSION, GScanLiteralExpressionClass))
/* Expression portant une valeur concrète (instance) */
-typedef struct _GLiteralExpression GLiteralExpression;
+typedef struct _GScanLiteralExpression GScanLiteralExpression;
/* Expression portant une valeur concrète (classe) */
-typedef struct _GLiteralExpressionClass GLiteralExpressionClass;
+typedef struct _GScanLiteralExpressionClass GScanLiteralExpressionClass;
+
+
+/* Types naturel équivalant à l'expression */
+typedef enum _LiteralValueType
+{
+ LVT_BOOLEAN, /* Valeur booléenne */
+ LVT_SIGNED_INTEGER, /* Nombre entier 64 bits #1 */
+ LVT_UNSIGNED_INTEGER, /* Nombre entier 64 bits #2 */
+ LVT_STRING, /* Chaîne de caractères */
+ LVT_REG_EXPR, /* Expression rationnelle */
+
+} LiteralValueType;
/* Indique le type défini pour un appel de fonction enregistrée. */
-GType g_literal_expression_get_type(void);
+GType g_scan_literal_expression_get_type(void);
/* Organise un appel de fonction avec ses arguments. */
-GScanExpression *g_literal_expression_new(ExprValueType, ...);
+GScanExpression *g_scan_literal_expression_new(LiteralValueType, ...);
+
+/* Indique le type de valeur portée par une expression. */
+LiteralValueType g_scan_literal_expression_get_value_type(const GScanLiteralExpression *);
/* Indique la valeur portée par une expression booléenne. */
-bool g_literal_expression_get_boolean_value(const GLiteralExpression *, bool *);
+bool g_scan_literal_expression_get_boolean_value(const GScanLiteralExpression *, bool *);
+
+/* Indique la valeur portée par une expression d'entier. */
+bool g_scan_literal_expression_get_signed_integer_value(const GScanLiteralExpression *, long long *);
/* Indique la valeur portée par une expression d'entier. */
-bool g_literal_expression_get_integer_value(const GLiteralExpression *, unsigned long long *);
+bool g_scan_literal_expression_get_unsigned_integer_value(const GScanLiteralExpression *, unsigned long long *);
/* Indique la valeur portée par une expression de chaîne. */
-bool g_literal_expression_get_string_value(const GLiteralExpression *, const sized_string_t **);
+bool g_scan_literal_expression_get_string_value(const GScanLiteralExpression *, 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 **);
+bool g_scan_literal_expression_get_regex_value(const GScanLiteralExpression *, const regex_t **);
diff --git a/src/analysis/scan/exprs/boolop-int.h b/src/analysis/scan/exprs/logical-int.h
index c381cfe..6df55d0 100644
--- a/src/analysis/scan/exprs/boolop-int.h
+++ b/src/analysis/scan/exprs/logical-int.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * boolop-int.h - prototypes internes pour la gestion des opérations booléennes
+ * logical-int.h - prototypes internes pour la gestion des opérations booléennes
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,11 +21,11 @@
*/
-#ifndef _ANALYSIS_SCAN_EXPRS_BOOLOP_INT_H
-#define _ANALYSIS_SCAN_EXPRS_BOOLOP_INT_H
+#ifndef _ANALYSIS_SCAN_EXPRS_LOGICAL_INT_H
+#define _ANALYSIS_SCAN_EXPRS_LOGICAL_INT_H
-#include "boolop.h"
+#include "logical.h"
#include "../expr-int.h"
@@ -33,7 +33,7 @@
/* Opération booléenne avec un ou deux opérandes (instance) */
-struct _GBoolOperation
+struct _GScanLogicalOperation
{
GScanExpression parent; /* A laisser en premier */
@@ -45,7 +45,7 @@ struct _GBoolOperation
};
/* Opération booléenne avec un ou deux opérandes (classe) */
-struct _GBoolOperationClass
+struct _GScanLogicalOperationClass
{
GScanExpressionClass parent; /* A laisser en premier */
@@ -53,8 +53,8 @@ struct _GBoolOperationClass
/* Met en place une expression d'opération booléenne. */
-bool g_boolean_operation_create(GBoolOperation *, BooleanOperationType, GScanExpression *, GScanExpression *);
+bool g_scan_logical_operation_create(GScanLogicalOperation *, BooleanOperationType, GScanExpression *, GScanExpression *);
-#endif /* _ANALYSIS_SCAN_EXPRS_BOOLOP_INT_H */
+#endif /* _ANALYSIS_SCAN_EXPRS_LOGICAL_INT_H */
diff --git a/src/analysis/scan/exprs/boolop.c b/src/analysis/scan/exprs/logical.c
index f6a80dd..4c82b1e 100644
--- a/src/analysis/scan/exprs/boolop.c
+++ b/src/analysis/scan/exprs/logical.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * boolop.c - gestion des opérations booléennes
+ * logical.c - gestion des opérations booléennes
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,13 +21,13 @@
*/
-#include "boolop.h"
+#include "logical.h"
#include <assert.h>
-#include "boolop-int.h"
+#include "logical-int.h"
#include "literal.h"
@@ -36,16 +36,16 @@
/* Initialise la classe des opérations booléennes. */
-static void g_boolean_operation_class_init(GBoolOperationClass *);
+static void g_scan_logical_operation_class_init(GScanLogicalOperationClass *);
/* Initialise une instance d'opération booléenne. */
-static void g_boolean_operation_init(GBoolOperation *);
+static void g_scan_logical_operation_init(GScanLogicalOperation *);
/* Supprime toutes les références externes. */
-static void g_boolean_operation_dispose(GBoolOperation *);
+static void g_scan_logical_operation_dispose(GScanLogicalOperation *);
/* Procède à la libération totale de la mémoire. */
-static void g_boolean_operation_finalize(GBoolOperation *);
+static void g_scan_logical_operation_finalize(GScanLogicalOperation *);
@@ -53,13 +53,10 @@ static void g_boolean_operation_finalize(GBoolOperation *);
/* Réalise une comparaison entre objets selon un critère précis. */
-static bool g_boolean_operation_compare_rich(const GBoolOperation *, const GBoolOperation *, RichCmpOperation, bool *);
-
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_boolean_operation_copy(GBoolOperation *, const GBoolOperation *);
+static bool g_scan_logical_operation_compare_rich(const GScanLogicalOperation *, const GScanLogicalOperation *, RichCmpOperation, bool *);
/* Réduit une expression à une forme plus simple. */
-static bool g_boolean_operation_reduce(GBoolOperation *, GScanContext *, GScanScope *, GScanExpression **);
+static ScanReductionState g_scan_logical_operation_reduce(GScanLogicalOperation *, GScanContext *, GScanScope *, GScanExpression **);
@@ -69,7 +66,7 @@ static bool g_boolean_operation_reduce(GBoolOperation *, GScanContext *, GScanSc
/* Indique le type défini pour une opération booléenne sur expression(s). */
-G_DEFINE_TYPE(GBoolOperation, g_boolean_operation, G_TYPE_SCAN_EXPRESSION);
+G_DEFINE_TYPE(GScanLogicalOperation, g_scan_logical_operation, G_TYPE_SCAN_EXPRESSION);
/******************************************************************************
@@ -84,21 +81,20 @@ G_DEFINE_TYPE(GBoolOperation, g_boolean_operation, G_TYPE_SCAN_EXPRESSION);
* *
******************************************************************************/
-static void g_boolean_operation_class_init(GBoolOperationClass *klass)
+static void g_scan_logical_operation_class_init(GScanLogicalOperationClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GScanExpressionClass *expr; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_boolean_operation_dispose;
- object->finalize = (GObjectFinalizeFunc)g_boolean_operation_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_logical_operation_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_logical_operation_finalize;
expr = G_SCAN_EXPRESSION_CLASS(klass);
- expr->cmp_rich = (compare_expr_rich_fc)g_boolean_operation_compare_rich;
- expr->copy = (copy_expr_fc)g_boolean_operation_copy;
- expr->reduce = (reduce_expr_fc)g_boolean_operation_reduce;
+ expr->cmp_rich = (compare_expr_rich_fc)g_scan_logical_operation_compare_rich;
+ expr->reduce = (reduce_expr_fc)g_scan_logical_operation_reduce;
}
@@ -115,7 +111,7 @@ static void g_boolean_operation_class_init(GBoolOperationClass *klass)
* *
******************************************************************************/
-static void g_boolean_operation_init(GBoolOperation *op)
+static void g_scan_logical_operation_init(GScanLogicalOperation *op)
{
op->first = NULL;
op->second = NULL;
@@ -135,12 +131,12 @@ static void g_boolean_operation_init(GBoolOperation *op)
* *
******************************************************************************/
-static void g_boolean_operation_dispose(GBoolOperation *op)
+static void g_scan_logical_operation_dispose(GScanLogicalOperation *op)
{
g_clear_object(&op->first);
g_clear_object(&op->second);
- G_OBJECT_CLASS(g_boolean_operation_parent_class)->dispose(G_OBJECT(op));
+ G_OBJECT_CLASS(g_scan_logical_operation_parent_class)->dispose(G_OBJECT(op));
}
@@ -157,9 +153,9 @@ static void g_boolean_operation_dispose(GBoolOperation *op)
* *
******************************************************************************/
-static void g_boolean_operation_finalize(GBoolOperation *op)
+static void g_scan_logical_operation_finalize(GScanLogicalOperation *op)
{
- G_OBJECT_CLASS(g_boolean_operation_parent_class)->finalize(G_OBJECT(op));
+ G_OBJECT_CLASS(g_scan_logical_operation_parent_class)->finalize(G_OBJECT(op));
}
@@ -178,13 +174,13 @@ static void g_boolean_operation_finalize(GBoolOperation *op)
* *
******************************************************************************/
-GScanExpression *g_boolean_operation_new(BooleanOperationType type, GScanExpression *first, GScanExpression *second)
+GScanExpression *g_scan_logical_operation_new(BooleanOperationType type, GScanExpression *first, GScanExpression *second)
{
GScanExpression *result; /* Structure à retourner */
result = g_object_new(G_TYPE_BOOLEAN_OPERATION, NULL);
- if (!g_boolean_operation_create(G_BOOLEAN_OPERATION(result), type, first, second))
+ if (!g_scan_logical_operation_create(G_SCAN_LOGICAL_OPERATION(result), type, first, second))
g_clear_object(&result);
return result;
@@ -207,21 +203,10 @@ GScanExpression *g_boolean_operation_new(BooleanOperationType type, GScanExpress
* *
******************************************************************************/
-bool g_boolean_operation_create(GBoolOperation *op, BooleanOperationType type, GScanExpression *first, GScanExpression *second)
+bool g_scan_logical_operation_create(GScanLogicalOperation *op, BooleanOperationType type, GScanExpression *first, GScanExpression *second)
{
bool result; /* Bilan à retourner */
- result = false;
-
- if (g_scan_expression_get_value_type(first) != EVT_BOOLEAN)
- goto exit;
-
- if (g_scan_expression_get_value_type(second) != EVT_BOOLEAN)
- goto exit;
-
- if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_BOOLEAN))
- goto exit;
-
op->type = type;
switch (type)
@@ -245,9 +230,11 @@ bool g_boolean_operation_create(GBoolOperation *op, BooleanOperationType type, G
assert(second != NULL);
break;
- }
+ default:
+ result = false;
+ break;
- exit:
+ }
return result;
@@ -275,7 +262,7 @@ 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)
+static bool g_scan_logical_operation_compare_rich(const GScanLogicalOperation *item, const GScanLogicalOperation *other, RichCmpOperation op, bool *status)
{
bool result; /* Etat à retourner */
@@ -284,7 +271,7 @@ static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const G
if (item->type != other->type)
{
- *status = compare_rich_integer_values(item->type, other->type, op);
+ *status = compare_rich_integer_values_unsigned(item->type, other->type, op);
goto done;
}
@@ -332,37 +319,6 @@ static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const G
/******************************************************************************
* *
-* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
-* src = expression source à copier. *
-* *
-* Description : Reproduit une expression en place dans une nouvelle instance.*
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_boolean_operation_copy(GBoolOperation *dest, const GBoolOperation *src)
-{
- GScanExpressionClass *class; /* Classe parente à solliciter */
-
- class = G_SCAN_EXPRESSION_CLASS(g_boolean_operation_parent_class);
-
- 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);
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : expr = expression à consulter. *
* ctx = contexte de suivi de l'analyse courante. *
* scope = portée courante des variables locales. *
@@ -376,100 +332,173 @@ static void g_boolean_operation_copy(GBoolOperation *dest, const GBoolOperation
* *
******************************************************************************/
-static bool g_boolean_operation_reduce(GBoolOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static ScanReductionState g_scan_logical_operation_reduce(GScanLogicalOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- bool result; /* Bilan à retourner */
+ ScanReductionState result; /* Etat synthétisé à retourner */
GScanExpression *new_first; /* Expression réduite (gauche) */
+ ScanReductionState state[2]; /* Bilan de sous-réductons */
GScanExpression *new_second; /* Expression réduite (droite) */
+ GScanExpression *bool_operands[2]; /* Expressions booléennes */
bool values[2]; /* Valeurs des éléments portés */
bool valid[2]; /* Validité de ces valeurs */
/* Réduction des éléments considérés */
- new_first = NULL;
- new_second = NULL;
-
- result = g_scan_expression_reduce(expr->first, ctx, scope, &new_first);
- if (!result) goto exit;
+ state[0] = g_scan_expression_reduce(expr->first, ctx, scope, &new_first);
- if (expr->second == NULL)
- new_second = NULL;
+ if (expr->second != NULL)
+ state[1] = g_scan_expression_reduce(expr->second, ctx, scope, &new_second);
else
{
- result = g_scan_expression_reduce(expr->second, ctx, scope, &new_second);
- if (!result) goto exit;
+ new_second = NULL;
+ state[1] = SRS_REDUCED;
}
- /* Construction d'une réduction locale ? */
+ /* Récupération des valeurs booléennes */
- valid[0] = G_IS_LITERAL_EXPRESSION(new_first);
+ if (new_first != NULL)
+ {
+ valid[0] = g_scan_expression_reduce_to_boolean(new_first, ctx, scope, &bool_operands[0]);
- if (valid[0])
- valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(new_first), &values[0]);
+ if (valid[0])
+ valid[0] = g_scan_literal_expression_get_boolean_value(G_SCAN_LITERAL_EXPRESSION(bool_operands[0]),
+ &values[0]);
+ else
+ bool_operands[0] = NULL;
- valid[1] = G_IS_LITERAL_EXPRESSION(new_second);
+ }
+ else
+ {
+ bool_operands[0] = NULL;
+ valid[0] = false;
+ }
- if (valid[1])
- valid[1] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(new_second), &values[1]);
+ if (new_second != NULL)
+ {
+ valid[1] = g_scan_expression_reduce_to_boolean(new_second, ctx, scope, &bool_operands[1]);
+
+ if (valid[1])
+ valid[1] = g_scan_literal_expression_get_boolean_value(G_SCAN_LITERAL_EXPRESSION(bool_operands[1]),
+ &values[1]);
+ else
+ bool_operands[1] = NULL;
+
+ }
+ else
+ {
+ bool_operands[1] = NULL;
+ valid[1] = false;
+ }
+
+ /* Construction d'une réduction locale ? */
switch (expr->type)
{
case BOT_AND:
if (valid[0] && valid[1])
- *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] && values[1] });
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { values[0] && values[1] });
+ result = SRS_REDUCED;
+ }
else if (valid[0] && !values[0])
- *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false });
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { false });
+ result = SRS_REDUCED;
+ }
else if (valid[1] && !values[1])
- *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false });
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { false });
+ result = SRS_REDUCED;
+ }
+
+ else
+ {
+ if (state[0] == SRS_UNRESOLVABLE || state[1] == SRS_UNRESOLVABLE)
+ result = SRS_UNRESOLVABLE;
+ else
+ {
+ assert(state[0] == SRS_WAIT_FOR_SCAN || state[1] == SRS_WAIT_FOR_SCAN);
+ result = SRS_WAIT_FOR_SCAN;
+ }
+ }
break;
case BOT_OR:
if (valid[0] && valid[1])
- *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] || values[1] });
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { values[0] || values[1] });
+ result = SRS_REDUCED;
+ }
else if (valid[0] && values[0])
- *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { true });
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { true });
+ result = SRS_REDUCED;
+ }
else if (valid[1] && values[1])
- *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { true });
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { true });
+ result = SRS_REDUCED;
+ }
+
+ else
+ {
+ if (state[0] == SRS_UNRESOLVABLE || state[1] == SRS_UNRESOLVABLE)
+ result = SRS_UNRESOLVABLE;
+ else
+ {
+ assert(state[0] == SRS_WAIT_FOR_SCAN || state[1] == SRS_WAIT_FOR_SCAN);
+ result = SRS_WAIT_FOR_SCAN;
+ }
+ }
break;
case BOT_NOT:
if (valid[0])
- *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { !values[0] });
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { !values[0] });
+ result = SRS_REDUCED;
+ }
+
+ else
+ {
+ if (state[0] == SRS_UNRESOLVABLE)
+ result = SRS_UNRESOLVABLE;
+ else
+ {
+ assert(state[0] == SRS_WAIT_FOR_SCAN);
+ result = SRS_WAIT_FOR_SCAN;
+ }
+ }
+
break;
}
/* Mise à jour de la progression ? */
- if (*out == NULL)
+ if (result == SRS_WAIT_FOR_SCAN)
{
- if ((new_first != NULL && new_first != expr->first) || (new_second != NULL && new_second != expr->second))
+ if (new_first != expr->first || new_second != expr->second)
{
- if (new_first == NULL)
- {
- new_first = expr->first;
- g_object_ref(G_OBJECT(new_first));
- }
+ assert(new_first != NULL);
+ assert(new_second != NULL || expr->second == NULL);
- if (new_second == NULL)
- {
- new_second = expr->second;
- g_object_ref(G_OBJECT(new_second));
- }
-
- *out = g_boolean_operation_new(expr->type, new_first, new_second);
+ *out = g_scan_logical_operation_new(expr->type, new_first, new_second);
}
}
- exit:
+ /* Sortie propre */
+
+ g_clear_object(&bool_operands[0]);
+ g_clear_object(&bool_operands[1]);
g_clear_object(&new_first);
g_clear_object(&new_second);
diff --git a/src/analysis/scan/exprs/boolop.h b/src/analysis/scan/exprs/logical.h
index 4add5a1..e98bf11 100644
--- a/src/analysis/scan/exprs/boolop.h
+++ b/src/analysis/scan/exprs/logical.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * boolop.h - prototypes pour la gestion des opérations booléennes
+ * logical.h - prototypes pour la gestion des opérations booléennes
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,27 +21,27 @@
*/
-#ifndef _ANALYSIS_SCAN_EXPRS_BOOLOP_H
-#define _ANALYSIS_SCAN_EXPRS_BOOLOP_H
+#ifndef _ANALYSIS_SCAN_EXPRS_LOGICAL_H
+#define _ANALYSIS_SCAN_EXPRS_LOGICAL_H
#include "../expr.h"
-#define G_TYPE_BOOLEAN_OPERATION g_boolean_operation_get_type()
-#define G_BOOLEAN_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BOOLEAN_OPERATION, GBoolOperation))
+#define G_TYPE_BOOLEAN_OPERATION g_scan_logical_operation_get_type()
+#define G_SCAN_LOGICAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BOOLEAN_OPERATION, GScanLogicalOperation))
#define G_IS_BOOLEAN_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BOOLEAN_OPERATION))
-#define G_BOOLEAN_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BOOLEAN_OPERATION, GBoolOperationClass))
+#define G_SCAN_LOGICAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BOOLEAN_OPERATION, GScanLogicalOperationClass))
#define G_IS_BOOLEAN_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BOOLEAN_OPERATION))
-#define G_BOOLEAN_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BOOLEAN_OPERATION, GBoolOperationClass))
+#define G_SCAN_LOGICAL_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BOOLEAN_OPERATION, GScanLogicalOperationClass))
/* Opération booléenne avec un ou deux opérandes (instance) */
-typedef struct _GBoolOperation GBoolOperation;
+typedef struct _GScanLogicalOperation GScanLogicalOperation;
/* Opération booléenne avec un ou deux opérandes (classe) */
-typedef struct _GBoolOperationClass GBoolOperationClass;
+typedef struct _GScanLogicalOperationClass GScanLogicalOperationClass;
/* Types d'opérations booléennes supportées */
@@ -55,11 +55,11 @@ typedef enum _BooleanOperationType
/* Indique le type défini pour une opération booléenne sur expression(s). */
-GType g_boolean_operation_get_type(void);
+GType g_scan_logical_operation_get_type(void);
/* Organise un appel de fonction avec ses arguments. */
-GScanExpression *g_boolean_operation_new(BooleanOperationType, GScanExpression *, GScanExpression *);
+GScanExpression *g_scan_logical_operation_new(BooleanOperationType, GScanExpression *, GScanExpression *);
-#endif /* _ANALYSIS_SCAN_EXPRS_BOOLOP_H */
+#endif /* _ANALYSIS_SCAN_EXPRS_LOGICAL_H */
diff --git a/src/analysis/scan/exprs/range-int.h b/src/analysis/scan/exprs/range-int.h
new file mode 100644
index 0000000..6257874
--- /dev/null
+++ b/src/analysis/scan/exprs/range-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * range-int.h - prototypes internes pour la représentation compacte d'un éventail de valeurs
+ *
+ * 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_RANGE_INT_H
+#define _ANALYSIS_SCAN_EXPRS_RANGE_INT_H
+
+
+#include "range.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Représentation compacte d'un éventail de valeurs (instance) */
+struct _GScanCompactRange
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ GScanExpression *start; /* Point de départ */
+ GScanExpression *end; /* Point d'arrivée */
+
+};
+
+/* Représentation compacte d'un éventail de valeurs (classe) */
+struct _GScanCompactRangeClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une réprésentation d'un éventail de valeurs. */
+bool g_scan_compact_range_create(GScanCompactRange *, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_RANGE_INT_H */
diff --git a/src/analysis/scan/exprs/range.c b/src/analysis/scan/exprs/range.c
new file mode 100644
index 0000000..f97b15e
--- /dev/null
+++ b/src/analysis/scan/exprs/range.c
@@ -0,0 +1,352 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * range.c - représentation compacte d'un éventail de valeurs
+ *
+ * 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 "range.h"
+
+
+#include "literal.h"
+#include "range-int.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des éventail de valeurs. */
+static void g_scan_compact_range_class_init(GScanCompactRangeClass *);
+
+/* Initialise une instance d'éventail de valeurs. */
+static void g_scan_compact_range_init(GScanCompactRange *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_compact_range_dispose(GScanCompactRange *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_compact_range_finalize(GScanCompactRange *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_compact_range_reduce(GScanCompactRange *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réduit une expression à une forme booléenne. */
+static bool g_scan_compact_range_reduce_to_boolean(GScanCompactRange *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réalise l'intersection entre deux ensembles. */
+static GScanExpression *g_scan_compact_range_intersect(GScanCompactRange *expr, const GScanExpression *, GScanContext *, GScanScope *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une représentation compacte d'un éventail de valeurs. */
+G_DEFINE_TYPE(GScanCompactRange, g_scan_compact_range, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des éventail de valeurs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_compact_range_class_init(GScanCompactRangeClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_compact_range_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_compact_range_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->reduce = (reduce_expr_fc)g_scan_compact_range_reduce;
+ expr->reduce_to_bool = (reduce_expr_to_bool_fc)g_scan_compact_range_reduce_to_boolean;
+ expr->intersect = (intersect_scan_expr_fc)g_scan_compact_range_intersect;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : range = instance à initialiser. *
+* *
+* Description : Initialise une instance d'éventail de valeurs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_compact_range_init(GScanCompactRange *range)
+{
+ range->start = NULL;
+ range->end = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : range = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_compact_range_dispose(GScanCompactRange *range)
+{
+ g_clear_object(&range->start);
+ g_clear_object(&range->end);
+
+ G_OBJECT_CLASS(g_scan_compact_range_parent_class)->dispose(G_OBJECT(range));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : range = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_compact_range_finalize(GScanCompactRange *range)
+{
+ G_OBJECT_CLASS(g_scan_compact_range_parent_class)->finalize(G_OBJECT(range));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : start = point de départ de la plage de valeurs. *
+* end = point d'arrivée de la plage de valeurs. *
+* *
+* Description : Organise une réprésentation d'un éventail de valeurs. *
+* *
+* Retour : Expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_compact_range_new(GScanExpression *start, GScanExpression *end)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_COMPACT_RANGE, NULL);
+
+ if (!g_scan_compact_range_create(G_SCAN_COMPACT_RANGE(result), start, end))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : range = instance à initialiser pleinement. *
+* start = point de départ de la plage de valeurs. *
+* end = point d'arrivée de la plage de valeurs. *
+* *
+* Description : Met en place une réprésentation d'un éventail de valeurs. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_compact_range_create(GScanCompactRange *range, GScanExpression *start, GScanExpression *end)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ range->start = start;
+ g_object_ref(G_OBJECT(start));
+
+ range->end = end;
+ g_object_ref(G_OBJECT(end));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* 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 ScanReductionState g_scan_compact_range_reduce(GScanCompactRange *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanExpression *new_start; /* Nouvelle réduction #1 */
+ GScanExpression *new_end; /* Nouvelle réduction #2 */
+ ScanReductionState state_start; /* Etat synthétisé #1 */
+ ScanReductionState state_end; /* Etat synthétisé #2 */
+
+ new_start = NULL;
+ new_end = NULL;
+
+ state_start = g_scan_expression_reduce(expr->start, ctx, scope, &new_start);
+ if (state_start == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ state_end = g_scan_expression_reduce(expr->end, ctx, scope, &new_end);
+ if (state_end == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ if (state_start == SRS_WAIT_FOR_SCAN || state_end == SRS_WAIT_FOR_SCAN)
+ result = SRS_WAIT_FOR_SCAN;
+ else
+ result = SRS_REDUCED;
+
+ if (new_start != expr->start || new_end != expr->end)
+ *out = g_scan_compact_range_new(new_start, new_end);
+
+ exit:
+
+ g_clear_object(&new_start);
+ g_clear_object(&new_end);
+
+ 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 booléenne. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_compact_range_reduce_to_boolean(GScanCompactRange *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+ bool status; /* Bilan d'une comparaison */
+
+ result = G_IS_SCAN_LITERAL_EXPRESSION(expr->start) && G_IS_SCAN_LITERAL_EXPRESSION(expr->end);
+ if (!result) goto exit;
+
+ result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(expr->start),
+ G_COMPARABLE_ITEM(expr->end),
+ RCO_LE, &status);
+ if (!result) goto exit;
+
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à filtrer. *
+* other = expression utilisée pour le filtrage. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* *
+* Description : Réalise l'intersection entre deux ensembles. *
+* *
+* Retour : Intersection entre les deux ensembles ou NULL en cas d'échec.*
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GScanExpression *g_scan_compact_range_intersect(GScanCompactRange *expr, const GScanExpression *other, GScanContext *ctx, GScanScope *scope)
+{
+ GScanExpression *result; /* Instance à retourner */
+
+
+
+
+ result = true; // TODO
+
+
+
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/range.h b/src/analysis/scan/exprs/range.h
new file mode 100644
index 0000000..4b7ad04
--- /dev/null
+++ b/src/analysis/scan/exprs/range.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * range.h - prototypes pour la représentation compacte d'un éventail de valeurs
+ *
+ * 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_SET_H
+#define _ANALYSIS_SCAN_EXPRS_SET_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_COMPACT_RANGE g_scan_compact_range_get_type()
+#define G_SCAN_COMPACT_RANGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_COMPACT_RANGE, GScanCompactRange))
+#define G_IS_SCAN_COMPACT_RANGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_COMPACT_RANGE))
+#define G_SCAN_COMPACT_RANGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_COMPACT_RANGE, GScanCompactRangeClass))
+#define G_IS_SCAN_COMPACT_RANGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_COMPACT_RANGE))
+#define G_SCAN_COMPACT_RANGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_COMPACT_RANGE, GScanCompactRangeClass))
+
+
+/* Représentation compacte d'un éventail de valeurs (instance) */
+typedef struct _GScanCompactRange GScanCompactRange;
+
+/* Représentation compacte d'un éventail de valeurs (classe) */
+typedef struct _GScanCompactRangeClass GScanCompactRangeClass;
+
+
+/* Indique le type défini pour une représentation compacte d'un éventail de valeurs. */
+GType g_scan_compact_range_get_type(void);
+
+/* Organise une réprésentation d'un éventail de valeurs. */
+GScanExpression *g_scan_compact_range_new(GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_SET_H */
diff --git a/src/analysis/scan/exprs/relop-int.h b/src/analysis/scan/exprs/relational-int.h
index 3adbcf0..813b89d 100644
--- a/src/analysis/scan/exprs/relop-int.h
+++ b/src/analysis/scan/exprs/relational-int.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * relop-int.h - prototypes internes pour la gestion des opérations relationnelles
+ * relational-int.h - prototypes internes pour la gestion des opérations relationnelles
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,11 +21,11 @@
*/
-#ifndef _ANALYSIS_SCAN_EXPRS_RELOP_INT_H
-#define _ANALYSIS_SCAN_EXPRS_RELOP_INT_H
+#ifndef _ANALYSIS_SCAN_EXPRS_RELATIONAL_INT_H
+#define _ANALYSIS_SCAN_EXPRS_RELATIONAL_INT_H
-#include "relop.h"
+#include "relational.h"
#include "../expr-int.h"
@@ -33,7 +33,7 @@
/* Opération relationnelle impliquant deux opérandes (instance) */
-struct _GRelOperation
+struct _GScanRelationalOperation
{
GScanExpression parent; /* A laisser en premier */
@@ -45,7 +45,7 @@ struct _GRelOperation
};
/* Opération relationnelle impliquant deux opérandes (classe) */
-struct _GRelOperationClass
+struct _GScanRelationalOperationClass
{
GScanExpressionClass parent; /* A laisser en premier */
@@ -53,8 +53,8 @@ struct _GRelOperationClass
/* Met en place une opération relationnelle entre expressions. */
-bool g_relational_operation_create(GRelOperation *, RichCmpOperation, GScanExpression *, GScanExpression *);
+bool g_scan_relational_operation_create(GScanRelationalOperation *, RichCmpOperation, GScanExpression *, GScanExpression *);
-#endif /* _ANALYSIS_SCAN_EXPRS_RELOP_INT_H */
+#endif /* _ANALYSIS_SCAN_EXPRS_RELATIONAL_INT_H */
diff --git a/src/analysis/scan/exprs/relop.c b/src/analysis/scan/exprs/relational.c
index 7dc6864..b56b599 100644
--- a/src/analysis/scan/exprs/relop.c
+++ b/src/analysis/scan/exprs/relational.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * relop.c - gestion des opérations relationnelles
+ * relational.c - gestion des opérations relationnelles
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,10 +21,13 @@
*/
-#include "relop.h"
+#include "relational.h"
-#include "relop-int.h"
+#include <assert.h>
+
+
+#include "relational-int.h"
#include "literal.h"
@@ -33,16 +36,16 @@
/* Initialise la classe des opérations de relations. */
-static void g_relational_operation_class_init(GRelOperationClass *);
+static void g_scan_relational_operation_class_init(GScanRelationalOperationClass *);
/* Initialise une instance d'opération de relation. */
-static void g_relational_operation_init(GRelOperation *);
+static void g_scan_relational_operation_init(GScanRelationalOperation *);
/* Supprime toutes les références externes. */
-static void g_relational_operation_dispose(GRelOperation *);
+static void g_scan_relational_operation_dispose(GScanRelationalOperation *);
/* Procède à la libération totale de la mémoire. */
-static void g_relational_operation_finalize(GRelOperation *);
+static void g_scan_relational_operation_finalize(GScanRelationalOperation *);
@@ -50,13 +53,10 @@ 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 *);
-
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_relational_operation_copy(GRelOperation *, const GRelOperation *);
+static bool g_scan_relational_operation_compare_rich(const GScanRelationalOperation *, const GScanRelationalOperation *, RichCmpOperation, bool *);
/* Réduit une expression à une forme plus simple. */
-static bool g_relational_operation_reduce(GRelOperation *, GScanContext *, GScanScope *, GScanExpression **);
+static ScanReductionState g_scan_relational_operation_reduce(GScanRelationalOperation *, GScanContext *, GScanScope *, GScanExpression **);
@@ -66,7 +66,7 @@ static bool g_relational_operation_reduce(GRelOperation *, GScanContext *, GScan
/* Indique le type défini pour une opération de relation entre expressions. */
-G_DEFINE_TYPE(GRelOperation, g_relational_operation, G_TYPE_SCAN_EXPRESSION);
+G_DEFINE_TYPE(GScanRelationalOperation, g_scan_relational_operation, G_TYPE_SCAN_EXPRESSION);
/******************************************************************************
@@ -81,21 +81,20 @@ G_DEFINE_TYPE(GRelOperation, g_relational_operation, G_TYPE_SCAN_EXPRESSION);
* *
******************************************************************************/
-static void g_relational_operation_class_init(GRelOperationClass *klass)
+static void g_scan_relational_operation_class_init(GScanRelationalOperationClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GScanExpressionClass *expr; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_relational_operation_dispose;
- object->finalize = (GObjectFinalizeFunc)g_relational_operation_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_relational_operation_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_relational_operation_finalize;
expr = G_SCAN_EXPRESSION_CLASS(klass);
- expr->cmp_rich = (compare_expr_rich_fc)g_relational_operation_compare_rich;
- expr->copy = (copy_expr_fc)g_relational_operation_copy;
- expr->reduce = (reduce_expr_fc)g_relational_operation_reduce;
+ expr->cmp_rich = (compare_expr_rich_fc)g_scan_relational_operation_compare_rich;
+ expr->reduce = (reduce_expr_fc)g_scan_relational_operation_reduce;
}
@@ -112,7 +111,7 @@ static void g_relational_operation_class_init(GRelOperationClass *klass)
* *
******************************************************************************/
-static void g_relational_operation_init(GRelOperation *op)
+static void g_scan_relational_operation_init(GScanRelationalOperation *op)
{
op->left = NULL;
op->right = NULL;
@@ -132,12 +131,12 @@ static void g_relational_operation_init(GRelOperation *op)
* *
******************************************************************************/
-static void g_relational_operation_dispose(GRelOperation *op)
+static void g_scan_relational_operation_dispose(GScanRelationalOperation *op)
{
g_clear_object(&op->left);
g_clear_object(&op->right);
- G_OBJECT_CLASS(g_relational_operation_parent_class)->dispose(G_OBJECT(op));
+ G_OBJECT_CLASS(g_scan_relational_operation_parent_class)->dispose(G_OBJECT(op));
}
@@ -154,9 +153,9 @@ static void g_relational_operation_dispose(GRelOperation *op)
* *
******************************************************************************/
-static void g_relational_operation_finalize(GRelOperation *op)
+static void g_scan_relational_operation_finalize(GScanRelationalOperation *op)
{
- G_OBJECT_CLASS(g_relational_operation_parent_class)->finalize(G_OBJECT(op));
+ G_OBJECT_CLASS(g_scan_relational_operation_parent_class)->finalize(G_OBJECT(op));
}
@@ -175,13 +174,13 @@ static void g_relational_operation_finalize(GRelOperation *op)
* *
******************************************************************************/
-GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpression *left, GScanExpression *right)
+GScanExpression *g_scan_relational_operation_new(RichCmpOperation type, GScanExpression *left, GScanExpression *right)
{
GScanExpression *result; /* Structure à retourner */
- result = g_object_new(G_TYPE_RELATIONAL_OPERATION, NULL);
+ result = g_object_new(G_TYPE_SCAN_RELATIONAL_OPERATION, NULL);
- if (!g_relational_operation_create(G_RELATIONAL_OPERATION(result), type, left, right))
+ if (!g_scan_relational_operation_create(G_SCAN_RELATIONAL_OPERATION(result), type, left, right))
g_clear_object(&result);
return result;
@@ -204,17 +203,11 @@ GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpressi
* *
******************************************************************************/
-bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GScanExpression *left, GScanExpression *right)
+bool g_scan_relational_operation_create(GScanRelationalOperation *op, RichCmpOperation type, GScanExpression *left, GScanExpression *right)
{
bool result; /* Bilan à retourner */
- result = false;
-
- 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))
- goto exit;
+ result = true;
op->rel_type = type;
@@ -224,10 +217,6 @@ bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GSc
op->right = right;
g_object_ref(G_OBJECT(op->right));
- result = true;
-
- exit:
-
return result;
}
@@ -254,16 +243,16 @@ 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)
+static bool g_scan_relational_operation_compare_rich(const GScanRelationalOperation *item, const GScanRelationalOperation *other, RichCmpOperation op, bool *status)
{
bool result; /* Etat à retourner */
- result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_RELATIONAL_OPERATION);
+ result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_SCAN_RELATIONAL_OPERATION);
if (!result) goto done;
if (item->rel_type != other->rel_type)
{
- *status = compare_rich_integer_values(item->rel_type, other->rel_type, op);
+ *status = compare_rich_integer_values_unsigned(item->rel_type, other->rel_type, op);
goto done;
}
@@ -288,35 +277,6 @@ static bool g_relational_operation_compare_rich(const GRelOperation *item, const
/******************************************************************************
* *
-* 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_relational_operation_copy(GRelOperation *dest, const GRelOperation *src)
-{
- GScanExpressionClass *class; /* Classe parente à solliciter */
-
- class = G_SCAN_EXPRESSION_CLASS(g_relational_operation_parent_class);
-
- 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);
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : expr = expression à consulter. *
* ctx = contexte de suivi de l'analyse courante. *
* scope = portée courante des variables locales. *
@@ -330,11 +290,16 @@ static void g_relational_operation_copy(GRelOperation *dest, const GRelOperation
* *
******************************************************************************/
-static bool g_relational_operation_reduce(GRelOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static ScanReductionState g_scan_relational_operation_reduce(GScanRelationalOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- bool result; /* Bilan à retourner */
+ ScanReductionState result; /* Etat synthétisé à retourner */
GScanExpression *new_left; /* Expression réduite (gauche) */
GScanExpression *new_right; /* Expression réduite (droite) */
+ ScanReductionState state_left; /* Etat synthétisé #1 */
+ ScanReductionState state_right; /* Etat synthétisé #2 */
+ LiteralValueType vtype_left; /* Type de valeur portée #1 */
+ LiteralValueType vtype_right; /* Type de valeur portée #2 */
+ GScanExpression *casted; /* Nouvelle forme en booléen */
bool status; /* Bilan d'une comparaison */
bool valid; /* Validité de ce bilan obtenu */
@@ -343,45 +308,96 @@ static bool g_relational_operation_reduce(GRelOperation *expr, GScanContext *ctx
new_left = NULL;
new_right = NULL;
- result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
- if (!result) goto exit;
+ state_left = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
+ if (state_left == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ state_right = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
+ if (state_right == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ /* Transtypage vers des booléens imposé ? */
+
+ if (expr->rel_type == RCO_EQ || expr->rel_type == RCO_NE)
+ {
+ if (G_IS_SCAN_LITERAL_EXPRESSION(new_left))
+ {
+ vtype_left = g_scan_literal_expression_get_value_type(G_SCAN_LITERAL_EXPRESSION(new_left));
+
+ if (vtype_left == LVT_BOOLEAN)
+ {
+ if (g_scan_expression_reduce_to_boolean(new_right, ctx, scope, &casted))
+ {
+ g_object_unref(G_OBJECT(new_right));
+ new_right = casted;
+ }
+ }
+
+ }
+
+ if (G_IS_SCAN_LITERAL_EXPRESSION(new_right))
+ {
+ vtype_right = g_scan_literal_expression_get_value_type(G_SCAN_LITERAL_EXPRESSION(new_right));
- result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
- if (!result) goto exit;
+ if (vtype_right == LVT_BOOLEAN)
+ {
+ if (g_scan_expression_reduce_to_boolean(new_left, ctx, scope, &casted))
+ {
+ g_object_unref(G_OBJECT(new_left));
+ new_left = casted;
+ }
+ }
+
+ }
+
+ }
/* Construction d'une réduction locale ? */
- if (G_IS_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right))
+ if (G_IS_SCAN_LITERAL_EXPRESSION(new_left) && G_IS_SCAN_LITERAL_EXPRESSION(new_right))
{
valid = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(new_left),
G_COMPARABLE_ITEM(new_right),
expr->rel_type, &status);
if (valid)
- *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { status });
+ {
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { status });
+ result = SRS_REDUCED;
+ }
+ else
+ result = SRS_UNRESOLVABLE;
}
/* Mise à jour de la progression ? */
- else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right))
+ else if (state_left == SRS_WAIT_FOR_SCAN || state_right == SRS_WAIT_FOR_SCAN)
{
- if (new_left == NULL)
- {
- new_left = expr->left;
- g_object_ref(G_OBJECT(new_left));
- }
+ if (new_left != expr->left || new_right != expr->right)
+ *out = g_scan_relational_operation_new(expr->rel_type, new_left, new_right);
- if (new_right == NULL)
- {
- new_right = expr->right;
- g_object_ref(G_OBJECT(new_right));
- }
+ result = SRS_WAIT_FOR_SCAN;
- *out = g_relational_operation_new(expr->rel_type, new_left, new_right);
+ }
+
+ /* Cas des situations où les expressions ne sont pas exploitables (!) */
+ else
+ {
+ assert(state_left == SRS_REDUCED && state_right == SRS_REDUCED);
+
+ result = SRS_UNRESOLVABLE;
}
+ /* Sortie propre */
+
exit:
g_clear_object(&new_left);
diff --git a/src/analysis/scan/exprs/relational.h b/src/analysis/scan/exprs/relational.h
new file mode 100644
index 0000000..10d58a6
--- /dev/null
+++ b/src/analysis/scan/exprs/relational.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * relational.h - prototypes pour la gestion des opérations relationnelles
+ *
+ * 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_RELATIONAL_H
+#define _ANALYSIS_SCAN_EXPRS_RELATIONAL_H
+
+
+#include "../expr.h"
+#include "../../../glibext/comparison.h"
+
+
+
+#define G_TYPE_SCAN_RELATIONAL_OPERATION g_scan_relational_operation_get_type()
+#define G_SCAN_RELATIONAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_RELATIONAL_OPERATION, GScanRelationalOperation))
+#define G_IS_SCAN_RELATIONAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_RELATIONAL_OPERATION))
+#define G_SCAN_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_RELATIONAL_OPERATION, GScanRelationalOperationClass))
+#define G_IS_SCAN_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_RELATIONAL_OPERATION))
+#define G_SCAN_RELATIONAL_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_RELATIONAL_OPERATION, GScanRelationalOperationClass))
+
+
+/* Opération relationnelle impliquant deux opérandes (instance) */
+typedef struct _GScanRelationalOperation GScanRelationalOperation;
+
+/* Opération relationnelle impliquant deux opérandes (classe) */
+typedef struct _GScanRelationalOperationClass GScanRelationalOperationClass;
+
+
+/* Indique le type défini pour une opération de relation entre expressions. */
+GType g_scan_relational_operation_get_type(void);
+
+/* Organise une opération relationnelle entre expressions. */
+GScanExpression *g_scan_relational_operation_new(RichCmpOperation, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_RELATIONAL_H */
diff --git a/src/analysis/scan/exprs/relop.h b/src/analysis/scan/exprs/relop.h
deleted file mode 100644
index ecbc8ef..0000000
--- a/src/analysis/scan/exprs/relop.h
+++ /dev/null
@@ -1,56 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * relop.h - prototypes pour la gestion des opérations relationnelles
- *
- * Copyright (C) 2022 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_RELOP_H
-#define _ANALYSIS_SCAN_EXPRS_RELOP_H
-
-
-#include "../expr.h"
-#include "../../../glibext/comparison.h"
-
-
-
-#define G_TYPE_RELATIONAL_OPERATION g_relational_operation_get_type()
-#define G_RELATIONAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RELATIONAL_OPERATION, GRelOperation))
-#define G_IS_RELATIONAL_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RELATIONAL_OPERATION))
-#define G_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RELATIONAL_OPERATION, GRelOperationClass))
-#define G_IS_RELATIONAL_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RELATIONAL_OPERATION))
-#define G_RELATIONAL_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RELATIONAL_OPERATION, GRelOperationClass))
-
-
-/* Opération relationnelle impliquant deux opérandes (instance) */
-typedef struct _GRelOperation GRelOperation;
-
-/* Opération relationnelle impliquant deux opérandes (classe) */
-typedef struct _GRelOperationClass GRelOperationClass;
-
-
-/* Indique le type défini pour une opération de relation entre expressions. */
-GType g_relational_operation_get_type(void);
-
-/* Organise une opération relationnelle entre expressions. */
-GScanExpression *g_relational_operation_new(RichCmpOperation, GScanExpression *, GScanExpression *);
-
-
-
-#endif /* _ANALYSIS_SCAN_EXPRS_RELOP_H */
diff --git a/src/analysis/scan/exprs/set-int.h b/src/analysis/scan/exprs/set-int.h
new file mode 100644
index 0000000..ebb4380
--- /dev/null
+++ b/src/analysis/scan/exprs/set-int.h
@@ -0,0 +1,54 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * set-int.h - prototypes internes pour la base d'ensembles de valeurs diverses, de types hétérogènes ou homogènes
+ *
+ * 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_SET_INT_H
+#define _ANALYSIS_SCAN_EXPRS_SET_INT_H
+
+
+#include "set.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Base d'un ensemble d'éléments homogènes ou hétérogènes (instance) */
+struct _GScanGenericSet
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ GScanExpression **items; /* Liste d'éléments embarqués */
+ size_t count; /* Quantité de ces éléments */
+
+};
+
+/* Base d'un ensemble d'éléments homogènes ou hétérogènes (classe) */
+struct _GScanGenericSetClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_SET_INT_H */
diff --git a/src/analysis/scan/exprs/arithmop.c b/src/analysis/scan/exprs/set.c
index 5f9e3f1..0a93ced 100644
--- a/src/analysis/scan/exprs/arithmop.c
+++ b/src/analysis/scan/exprs/set.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * arithmop.c - gestion des opérations arithmétiques
+ * set.c - base d'ensembles de valeurs diverses, de types hétérogènes ou homogènes
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,42 +21,49 @@
*/
-#include "arithmop.h"
+#include "set.h"
+
+
+#include <assert.h>
+#include <malloc.h>
-#include "arithmop-int.h"
#include "literal.h"
+#include "set-int.h"
/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
-/* Initialise la classe des opérations arithmétiques. */
-static void g_arithmetic_operation_class_init(GArithmOperationClass *);
+/* Initialise la classe des bases d'ensembles d'éléments. */
+static void g_scan_generic_set_class_init(GScanGenericSetClass *);
-/* Initialise une instance d'opération arithmétique. */
-static void g_arithmetic_operation_init(GArithmOperation *);
+/* Initialise une instance de base d'ensemble d'éléments. */
+static void g_scan_generic_set_init(GScanGenericSet *);
/* Supprime toutes les références externes. */
-static void g_arithmetic_operation_dispose(GArithmOperation *);
+static void g_scan_generic_set_dispose(GScanGenericSet *);
/* Procède à la libération totale de la mémoire. */
-static void g_arithmetic_operation_finalize(GArithmOperation *);
+static void g_scan_generic_set_finalize(GScanGenericSet *);
/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* 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 *);
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_generic_set_reduce(GScanGenericSet *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réduit une expression à une forme booléenne. */
+static bool g_scan_generic_set_reduce_to_boolean(GScanGenericSet *, GScanContext *, GScanScope *, GScanExpression **);
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_arithmetic_operation_copy(GArithmOperation *, const GArithmOperation *);
+/* Dénombre les éléments portés par une expression. */
+static bool g_scan_generic_set_count_items(const GScanGenericSet *, size_t *);
-/* Réduit une expression à une forme plus simple. */
-static bool g_arithmetic_operation_reduce(GArithmOperation *, GScanContext *, GScanScope *, GScanExpression **);
+/* Fournit un élément donné issu d'un ensemble constitué. */
+static bool g_scan_generic_set_get_item(const GScanGenericSet *, size_t, GScanExpression **);
@@ -65,15 +72,15 @@ static bool g_arithmetic_operation_reduce(GArithmOperation *, GScanContext *, GS
/* ---------------------------------------------------------------------------------- */
-/* Indique le type défini pour une opération de relation entre expressions. */
-G_DEFINE_TYPE(GArithmOperation, g_arithmetic_operation, G_TYPE_SCAN_EXPRESSION);
+/* Indique le type défini pour une base d'ensembles d'éléments homogènes ou hétérogènes. */
+G_DEFINE_TYPE(GScanGenericSet, g_scan_generic_set, G_TYPE_SCAN_EXPRESSION);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
-* Description : Initialise la classe des opérations arithmétiques. *
+* Description : Initialise la classe des bases d'ensembles d'éléments. *
* *
* Retour : - *
* *
@@ -81,30 +88,31 @@ G_DEFINE_TYPE(GArithmOperation, g_arithmetic_operation, G_TYPE_SCAN_EXPRESSION);
* *
******************************************************************************/
-static void g_arithmetic_operation_class_init(GArithmOperationClass *klass)
+static void g_scan_generic_set_class_init(GScanGenericSetClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GScanExpressionClass *expr; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_arithmetic_operation_dispose;
- object->finalize = (GObjectFinalizeFunc)g_arithmetic_operation_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_generic_set_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_generic_set_finalize;
expr = G_SCAN_EXPRESSION_CLASS(klass);
- expr->cmp_rich = (compare_expr_rich_fc)g_arithmetic_operation_compare_rich;
- expr->copy = (copy_expr_fc)g_arithmetic_operation_copy;
- expr->reduce = (reduce_expr_fc)g_arithmetic_operation_reduce;
+ expr->reduce = (reduce_expr_fc)g_scan_generic_set_reduce;
+ expr->reduce_to_bool = (reduce_expr_to_bool_fc)g_scan_generic_set_reduce_to_boolean;
+ expr->count = (count_scan_expr_fc)g_scan_generic_set_count_items;
+ expr->get = (get_scan_expr_fc)g_scan_generic_set_get_item;
}
/******************************************************************************
* *
-* Paramètres : op = instance à initialiser. *
+* Paramètres : set = instance à initialiser. *
* *
-* Description : Initialise une instance d'opération arithmétique. *
+* Description : Initialise une instance de base d'ensemble d'éléments. *
* *
* Retour : - *
* *
@@ -112,17 +120,17 @@ static void g_arithmetic_operation_class_init(GArithmOperationClass *klass)
* *
******************************************************************************/
-static void g_arithmetic_operation_init(GArithmOperation *op)
+static void g_scan_generic_set_init(GScanGenericSet *set)
{
- op->left = NULL;
- op->right = NULL;
+ set->items = NULL;
+ set->count = 0;
}
/******************************************************************************
* *
-* Paramètres : op = instance d'objet GLib à traiter. *
+* Paramètres : set = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -132,19 +140,21 @@ static void g_arithmetic_operation_init(GArithmOperation *op)
* *
******************************************************************************/
-static void g_arithmetic_operation_dispose(GArithmOperation *op)
+static void g_scan_generic_set_dispose(GScanGenericSet *set)
{
- g_clear_object(&op->left);
- g_clear_object(&op->right);
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < set->count; i++)
+ g_clear_object(&set->items[i]);
- G_OBJECT_CLASS(g_arithmetic_operation_parent_class)->dispose(G_OBJECT(op));
+ G_OBJECT_CLASS(g_scan_generic_set_parent_class)->dispose(G_OBJECT(set));
}
/******************************************************************************
* *
-* Paramètres : op = instance d'objet GLib à traiter. *
+* Paramètres : set = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -154,35 +164,33 @@ static void g_arithmetic_operation_dispose(GArithmOperation *op)
* *
******************************************************************************/
-static void g_arithmetic_operation_finalize(GArithmOperation *op)
+static void g_scan_generic_set_finalize(GScanGenericSet *set)
{
- G_OBJECT_CLASS(g_arithmetic_operation_parent_class)->finalize(G_OBJECT(op));
+ if (set->items != NULL)
+ free(set->items);
+
+ G_OBJECT_CLASS(g_scan_generic_set_parent_class)->finalize(G_OBJECT(set));
}
/******************************************************************************
* *
-* Paramètres : operator = type d'opération arithmétique à représenter. *
-* left = premier opérande concerné. *
-* right = éventuel second opérande impliqué ou NULL. *
+* Paramètres : - *
* *
-* Description : Organise une opération arithmétique entre expressions. *
+* Description : Met en place un ensemble d'éléments homogènes ou hétérogènes.*
* *
-* Retour : Fonction mise en place. *
+* Retour : Expression mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
-GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right)
+GScanExpression *g_scan_generic_set_new(void)
{
GScanExpression *result; /* Structure à retourner */
- result = g_object_new(G_TYPE_ARITHMETIC_OPERATION, NULL);
-
- if (!g_arithmetic_operation_create(G_ARITHMETIC_OPERATION(result), operator, left, right))
- g_clear_object(&result);
+ result = g_object_new(G_TYPE_SCAN_GENERIC_SET, NULL);
return result;
@@ -191,52 +199,23 @@ GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operato
/******************************************************************************
* *
-* Paramètres : op = instance à initialiser pleinement. *
-* operator = type d'opération booléenne à représenter. *
-* left = premier opérande concerné. *
-* right = éventuel second opérande impliqué ou NULL. *
+* Paramètres : set = ensemble à compléter. *
+* item = nouvel élément à intégrer. *
* *
-* Description : Met en place une opération arithmétique entre expressions. *
+* Description : Ajoute un nouvel élément à un ensemble. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right)
+void g_scan_generic_set_add_item(GScanGenericSet *set, GScanExpression *item)
{
- bool result; /* Bilan à retourner */
- ExprValueType vtype; /* Type de valeur portée */
-
- result = false;
-
- vtype = g_scan_expression_get_value_type(left);
+ set->items = realloc(set->items, ++set->count * sizeof(GScanExpression *));
- if (vtype != EVT_INTEGER && vtype != EVT_PENDING)
- goto exit;
-
- vtype = g_scan_expression_get_value_type(right);
-
- if (vtype != EVT_INTEGER && vtype != EVT_PENDING)
- goto exit;
-
- if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_INTEGER))
- goto exit;
-
- op->operator = operator;
-
- op->left = left;
- g_object_ref(G_OBJECT(op->left));
-
- op->right = right;
- g_object_ref(G_OBJECT(op->right));
-
- result = true;
-
- exit:
-
- return result;
+ set->items[set->count - 1] = item;
+ g_object_ref(G_OBJECT(item));
}
@@ -249,45 +228,69 @@ bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOpe
/******************************************************************************
* *
-* Paramètres : item = 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] *
+* 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éalise une comparaison entre objets selon un critère précis.*
+* Description : Réduit une expression à une forme plus simple. *
* *
-* Retour : true si la comparaison a pu être effectuée, false sinon. *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_arithmetic_operation_compare_rich(const GArithmOperation *item, const GArithmOperation *other, RichCmpOperation op, bool *status)
+static ScanReductionState g_scan_generic_set_reduce(GScanGenericSet *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- bool result; /* Etat à retourner */
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ size_t i; /* Boucle de parcours #1 */
+ GScanExpression *item; /* Elément en cours d'analyse */
+ GScanExpression *new; /* Nouvelle réduction obtenue */
+ ScanReductionState state; /* Etat synthétisé d'un élément*/
+ size_t k; /* Boucle de parcours #2 */
- result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_ARITHMETIC_OPERATION);
- if (!result) goto done;
+ result = SRS_REDUCED;
- if (item->operator != other->operator)
+ for (i = 0; i < expr->count; i++)
{
- result = compare_rich_integer_values(item->operator, other->operator, op);
- goto done;
- }
+ item = expr->items[i];
- 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;
+ state = g_scan_expression_reduce(item, ctx, scope, &new);
+ if (state == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ g_clear_object(out);
+ break;
+ }
+
+ if (state == SRS_WAIT_FOR_SCAN)
+ result = SRS_WAIT_FOR_SCAN;
- 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;
+ if (new != item)
+ {
+ if (*out == NULL)
+ {
+ *out = g_scan_generic_set_new();
+
+ for (k = 0; k < i; k++)
+ g_scan_generic_set_add_item(G_SCAN_GENERIC_SET(*out), expr->items[k]);
- result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->right),
- G_COMPARABLE_ITEM(other->right),
- op, status);
+ }
- done:
+ g_scan_generic_set_add_item(G_SCAN_GENERIC_SET(*out), new);
+
+ }
+
+ else
+ {
+ if (*out != NULL)
+ g_scan_generic_set_add_item(G_SCAN_GENERIC_SET(*out), item);
+ }
+
+ g_object_unref(G_OBJECT(new));
+
+ }
return result;
@@ -296,29 +299,28 @@ static bool g_arithmetic_operation_compare_rich(const GArithmOperation *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_arithmetic_operation_copy(GArithmOperation *dest, const GArithmOperation *src)
+static bool g_scan_generic_set_reduce_to_boolean(GScanGenericSet *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- GScanExpressionClass *class; /* Classe parente à solliciter */
-
- class = G_SCAN_EXPRESSION_CLASS(g_arithmetic_operation_parent_class);
+ bool result; /* Bilan à retourner */
- class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
+ result = true;
- dest->operator = src->operator;
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ expr->count > 0 });
- dest->left = g_scan_expression_duplicate(src->left);
- dest->right = g_scan_expression_duplicate(src->right);
+ return result;
}
@@ -326,11 +328,9 @@ static void g_arithmetic_operation_copy(GArithmOperation *dest, const GArithmOpe
/******************************************************************************
* *
* 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. *
* *
@@ -338,98 +338,41 @@ static void g_arithmetic_operation_copy(GArithmOperation *dest, const GArithmOpe
* *
******************************************************************************/
-static bool g_arithmetic_operation_reduce(GArithmOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static bool g_scan_generic_set_count_items(const GScanGenericSet *expr, size_t *count)
{
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; /* Seconde valeur à traiter */
- unsigned long long reduced; /* Valeur réduite finale */
-
- /* Réduction des éléments considérés */
-
- new_left = NULL;
- new_right = NULL;
-
- result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
- if (!result) goto exit;
-
- 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(new_left) && G_IS_LITERAL_EXPRESSION(new_right))
- {
- op_left = G_LITERAL_EXPRESSION(new_left);
- op_right = G_LITERAL_EXPRESSION(new_right);
-
- result = g_literal_expression_get_integer_value(op_left, &val_1);
- if (!result) goto exit;
-
- result = g_literal_expression_get_integer_value(op_right, &val_2);
- if (!result) goto exit;
-
- 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;
-
- }
- if (result)
- *out = g_literal_expression_new(EVT_INTEGER, &reduced);
+ result = true;
- }
+ *count = expr->count;
- /* Mise à jour de la progression ? */
+ return result;
- 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);
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* index = indice de l'élément à transférer. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Fournit un élément donné issu d'un ensemble constitué. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- }
+static bool g_scan_generic_set_get_item(const GScanGenericSet *expr, size_t index, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
- exit:
+ result = (index < expr->count);
- g_clear_object(&new_left);
- g_clear_object(&new_right);
+ if (result)
+ *out = expr->items[index];
return result;
diff --git a/src/analysis/scan/exprs/set.h b/src/analysis/scan/exprs/set.h
new file mode 100644
index 0000000..f857ce9
--- /dev/null
+++ b/src/analysis/scan/exprs/set.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * set.h - prototypes pour la base d'ensembles de valeurs diverses, de types hétérogènes ou homogènes
+ *
+ * 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_SET_H
+#define _ANALYSIS_SCAN_EXPRS_SET_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_GENERIC_SET g_scan_generic_set_get_type()
+#define G_SCAN_GENERIC_SET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_GENERIC_SET, GScanGenericSet))
+#define G_IS_SCAN_GENERIC_SET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_GENERIC_SET))
+#define G_SCAN_GENERIC_SET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_GENERIC_SET, GScanGenericSetClass))
+#define G_IS_SCAN_GENERIC_SET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_GENERIC_SET))
+#define G_SCAN_GENERIC_SET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_GENERIC_SET, GScanGenericSetClass))
+
+
+/* Base d'un ensemble d'éléments homogènes ou hétérogènes (instance) */
+typedef struct _GScanGenericSet GScanGenericSet;
+
+/* Base d'un ensemble d'éléments homogènes ou hétérogènes (classe) */
+typedef struct _GScanGenericSetClass GScanGenericSetClass;
+
+
+/* Indique le type défini pour une base d'ensembles d'éléments homogènes ou hétérogènes. */
+GType g_scan_generic_set_get_type(void);
+
+/* Met en place un ensemble d'éléments homogènes ou hétérogènes. */
+GScanExpression *g_scan_generic_set_new(void);
+
+/* Ajoute un nouvel élément à un ensemble. */
+void g_scan_generic_set_add_item(GScanGenericSet *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_SET_H */
diff --git a/src/analysis/scan/exprs/strop-int.h b/src/analysis/scan/exprs/strop-int.h
index 234ae8f..c2b40cf 100644
--- a/src/analysis/scan/exprs/strop-int.h
+++ b/src/analysis/scan/exprs/strop-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* strop-int.h - prototypes internes pour la gestion des opérations booléennes
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -34,7 +34,7 @@
/* Opération booléenne avec un ou deux opérandes (instance) */
-struct _GStringOperation
+struct _GScanStringOperation
{
GScanExpression parent; /* A laisser en premier */
@@ -47,7 +47,7 @@ struct _GStringOperation
};
/* Opération booléenne avec un ou deux opérandes (classe) */
-struct _GStringOperationClass
+struct _GScanStringOperationClass
{
GScanExpressionClass parent; /* A laisser en premier */
@@ -55,7 +55,7 @@ struct _GStringOperationClass
/* Met en place une expression d'opération traite une chaîne. */
-bool g_string_operation_create(GStringOperation *, StringOperationType, GScanExpression *, GScanExpression *, bool);
+bool g_scan_string_operation_create(GScanStringOperation *, StringOperationType, GScanExpression *, GScanExpression *, bool);
diff --git a/src/analysis/scan/exprs/strop.c b/src/analysis/scan/exprs/strop.c
index 145e8da..c7c2878 100644
--- a/src/analysis/scan/exprs/strop.c
+++ b/src/analysis/scan/exprs/strop.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* strop.c - gestion des opérations booléennes
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -38,27 +38,24 @@
/* Initialise la classe des opérations visant des chaînes. */
-static void g_string_operation_class_init(GStringOperationClass *);
+static void g_scan_string_operation_class_init(GScanStringOperationClass *);
/* Initialise une instance d'opération visant une chaîne. */
-static void g_string_operation_init(GStringOperation *);
+static void g_scan_string_operation_init(GScanStringOperation *);
/* Supprime toutes les références externes. */
-static void g_string_operation_dispose(GStringOperation *);
+static void g_scan_string_operation_dispose(GScanStringOperation *);
/* Procède à la libération totale de la mémoire. */
-static void g_string_operation_finalize(GStringOperation *);
+static void g_scan_string_operation_finalize(GScanStringOperation *);
/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* Reproduit une expression en place dans une nouvelle instance. */
-static void g_string_operation_copy(GStringOperation *, const GStringOperation *);
-
/* Réduit une expression à une forme plus simple. */
-static bool g_string_operation_reduce(GStringOperation *, GScanContext *, GScanScope *, GScanExpression **);
+static ScanReductionState g_scan_string_operation_reduce(GScanStringOperation *, GScanContext *, GScanScope *, GScanExpression **);
@@ -68,7 +65,7 @@ static bool g_string_operation_reduce(GStringOperation *, GScanContext *, GScanS
/* Indique le type défini pour une opération traitant une chaîne de caractères. */
-G_DEFINE_TYPE(GStringOperation, g_string_operation, G_TYPE_SCAN_EXPRESSION);
+G_DEFINE_TYPE(GScanStringOperation, g_scan_string_operation, G_TYPE_SCAN_EXPRESSION);
/******************************************************************************
@@ -83,21 +80,20 @@ G_DEFINE_TYPE(GStringOperation, g_string_operation, G_TYPE_SCAN_EXPRESSION);
* *
******************************************************************************/
-static void g_string_operation_class_init(GStringOperationClass *klass)
+static void g_scan_string_operation_class_init(GScanStringOperationClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GScanExpressionClass *expr; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_string_operation_dispose;
- object->finalize = (GObjectFinalizeFunc)g_string_operation_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_string_operation_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_string_operation_finalize;
expr = G_SCAN_EXPRESSION_CLASS(klass);
expr->cmp_rich = (compare_expr_rich_fc)NULL;
- expr->copy = (copy_expr_fc)g_string_operation_copy;
- expr->reduce = (reduce_expr_fc)g_string_operation_reduce;
+ expr->reduce = (reduce_expr_fc)g_scan_string_operation_reduce;
}
@@ -114,7 +110,7 @@ static void g_string_operation_class_init(GStringOperationClass *klass)
* *
******************************************************************************/
-static void g_string_operation_init(GStringOperation *op)
+static void g_scan_string_operation_init(GScanStringOperation *op)
{
op->left = NULL;
op->right = NULL;
@@ -134,12 +130,12 @@ static void g_string_operation_init(GStringOperation *op)
* *
******************************************************************************/
-static void g_string_operation_dispose(GStringOperation *op)
+static void g_scan_string_operation_dispose(GScanStringOperation *op)
{
g_clear_object(&op->left);
g_clear_object(&op->right);
- G_OBJECT_CLASS(g_string_operation_parent_class)->dispose(G_OBJECT(op));
+ G_OBJECT_CLASS(g_scan_string_operation_parent_class)->dispose(G_OBJECT(op));
}
@@ -156,9 +152,9 @@ static void g_string_operation_dispose(GStringOperation *op)
* *
******************************************************************************/
-static void g_string_operation_finalize(GStringOperation *op)
+static void g_scan_string_operation_finalize(GScanStringOperation *op)
{
- G_OBJECT_CLASS(g_string_operation_parent_class)->finalize(G_OBJECT(op));
+ G_OBJECT_CLASS(g_scan_string_operation_parent_class)->finalize(G_OBJECT(op));
}
@@ -178,13 +174,13 @@ static void g_string_operation_finalize(GStringOperation *op)
* *
******************************************************************************/
-GScanExpression *g_string_operation_new(StringOperationType type, GScanExpression *first, GScanExpression *second, bool sensitive)
+GScanExpression *g_scan_string_operation_new(StringOperationType type, GScanExpression *first, GScanExpression *second, bool sensitive)
{
GScanExpression *result; /* Structure à retourner */
- result = g_object_new(G_TYPE_STRING_OPERATION, NULL);
+ result = g_object_new(G_TYPE_SCAN_STRING_OPERATION, NULL);
- if (!g_string_operation_create(G_STRING_OPERATION(result), type, first, second, sensitive))
+ if (!g_scan_string_operation_create(G_SCAN_STRING_OPERATION(result), type, first, second, sensitive))
g_clear_object(&result);
return result;
@@ -198,7 +194,7 @@ GScanExpression *g_string_operation_new(StringOperationType type, GScanExpressio
* type = type d'opération booléenne à représenter. *
* left = premier opérande concerné. *
* right = éventuel second opérande impliqué ou NULL. *
-* sensitive = détermine la prise en compte de la casse. *
+* sensitive = détermine la prise en compte de la casse. *
* *
* Description : Met en place une expression d'opération traite une chaîne. *
* *
@@ -208,22 +204,11 @@ GScanExpression *g_string_operation_new(StringOperationType type, GScanExpressio
* *
******************************************************************************/
-bool g_string_operation_create(GStringOperation *op, StringOperationType type, GScanExpression *left, GScanExpression *right, bool sensitive)
+bool g_scan_string_operation_create(GScanStringOperation *op, StringOperationType type, GScanExpression *left, GScanExpression *right, bool sensitive)
{
bool result; /* Bilan à retourner */
- ExprValueType vtype; /* Type de valeur portée */
-
- result = false;
-
- vtype = g_scan_expression_get_value_type(left);
-
- if (vtype != EVT_STRING && vtype != EVT_PENDING)
- goto exit;
-
- vtype = g_scan_expression_get_value_type(right);
- if (vtype != EVT_STRING && vtype != EVT_REG_EXPR && vtype != EVT_PENDING)
- goto exit;
+ result = true;
op->type = type;
@@ -251,10 +236,6 @@ bool g_string_operation_create(GStringOperation *op, StringOperationType type, G
op->right = right;
g_object_ref(G_OBJECT(op->right));
- result = true;
-
- exit:
-
return result;
}
@@ -268,36 +249,6 @@ bool g_string_operation_create(GStringOperation *op, StringOperationType type, G
/******************************************************************************
* *
-* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
-* src = expression source à copier. *
-* *
-* Description : Reproduit une expression en place dans une nouvelle instance.*
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_string_operation_copy(GStringOperation *dest, const GStringOperation *src)
-{
- GScanExpressionClass *class; /* Classe parente à solliciter */
-
- class = G_SCAN_EXPRESSION_CLASS(g_string_operation_parent_class);
-
- class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
-
- dest->type = src->type;
- dest->case_sensitive = src->case_sensitive;
-
- dest->left = g_scan_expression_duplicate(src->left);
- dest->right = g_scan_expression_duplicate(src->right);
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : expr = expression à consulter. *
* ctx = contexte de suivi de l'analyse courante. *
* scope = portée courante des variables locales. *
@@ -311,47 +262,65 @@ static void g_string_operation_copy(GStringOperation *dest, const GStringOperati
* *
******************************************************************************/
-static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static ScanReductionState g_scan_string_operation_reduce(GScanStringOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- bool result; /* Bilan à retourner */
+ ScanReductionState result; /* Etat synthétisé à retourner */
GScanExpression *new_left; /* Expression réduite (gauche) */
GScanExpression *new_right; /* Expression réduite (droite) */
- GLiteralExpression *op_left; /* Opérande gauche final */
- GLiteralExpression *op_right; /* Opérande droite final */
+ ScanReductionState state_left; /* Etat synthétisé #1 */
+ ScanReductionState state_right; /* Etat synthétisé #2 */
+ GScanLiteralExpression *op_left; /* Opérande gauche final */
+ GScanLiteralExpression *op_right; /* Opérande droite final */
const sized_string_t *strings[2]; /* Chaînes en jeu */
const void *found; /* Présence d'une bribe ? */
bool status; /* Bilan de comparaison #1 */
+ int ret; /* Bilan de comparaison #2 */
size_t offset; /* Point de départ d'analyse */
const regex_t *preg; /* Expression rationnelle */
- int ret; /* Bilan de comparaison #2 */
/* Réduction des éléments considérés */
new_left = NULL;
new_right = NULL;
- result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
- if (!result) goto exit;
+ state_left = g_scan_expression_reduce(expr->left, ctx, scope, &new_left);
+ if (state_left == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
- result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
- if (!result) goto exit;
+ state_right = g_scan_expression_reduce(expr->right, ctx, scope, &new_right);
+ if (state_right == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
/* Construction d'une réduction locale ? */
- if (G_IS_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right))
+ if (G_IS_SCAN_LITERAL_EXPRESSION(new_left) && G_IS_SCAN_LITERAL_EXPRESSION(new_right))
{
- op_left = G_LITERAL_EXPRESSION(new_left);
- op_right = G_LITERAL_EXPRESSION(new_right);
+ op_left = G_SCAN_LITERAL_EXPRESSION(new_left);
+ op_right = G_SCAN_LITERAL_EXPRESSION(new_right);
+
+ if (!g_scan_literal_expression_get_string_value(op_left, &strings[0]))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
- result = g_literal_expression_get_string_value(op_left, &strings[0]);
- if (!result) goto exit;
+ result = SRS_REDUCED;
switch (expr->type)
{
case SOT_CONTAINS:
- result = g_literal_expression_get_string_value(op_right, &strings[1]);
- if (!result) goto exit;
+ if (!g_scan_literal_expression_get_string_value(op_right, &strings[1]))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
if (expr->case_sensitive)
found = memmem(strings[0]->data, strings[0]->len, strings[1]->data, strings[1]->len);
@@ -359,13 +328,16 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx,
else
found = memcasemem(strings[0]->data, strings[0]->len, strings[1]->data, strings[1]->len);
- result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { found != NULL });
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { found != NULL });
break;
case SOT_STARTSWITH:
- result = g_literal_expression_get_string_value(op_right, &strings[1]);
- if (!result) goto exit;
+ if (!g_scan_literal_expression_get_string_value(op_right, &strings[1]))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
if (strings[0]->len < strings[1]->len)
status = false;
@@ -381,13 +353,16 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx,
}
- result = g_literal_expression_new(EVT_BOOLEAN, &status);
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
break;
case SOT_ENDSWITH:
- result = g_literal_expression_get_string_value(op_right, &strings[1]);
- if (!result) goto exit;
+ if (!g_scan_literal_expression_get_string_value(op_right, &strings[1]))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
if (strings[0]->len < strings[1]->len)
status = false;
@@ -405,23 +380,29 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx,
}
- result = g_literal_expression_new(EVT_BOOLEAN, &status);
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
break;
case SOT_MATCHES:
- result = g_literal_expression_get_regex_value(op_right, &preg);
- if (!result) goto exit;
+ if (!g_scan_literal_expression_get_regex_value(op_right, &preg))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
ret = regexec(preg, strings[0]->data, 0, NULL, 0);
- *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { ret != REG_NOMATCH });
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []) { ret != REG_NOMATCH });
break;
case SOT_IEQUALS:
- result = g_literal_expression_get_string_value(op_right, &strings[1]);
- if (!result) goto exit;
+ if (!g_scan_literal_expression_get_string_value(op_right, &strings[1]))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
if (strings[0]->len != strings[1]->len)
status = false;
@@ -432,7 +413,7 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx,
status = (ret == 0);
}
- result = g_literal_expression_new(EVT_BOOLEAN, &status);
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &status);
break;
}
@@ -441,24 +422,26 @@ static bool g_string_operation_reduce(GStringOperation *expr, GScanContext *ctx,
/* Mise à jour de la progression ? */
- else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right))
+ else if (state_left == SRS_WAIT_FOR_SCAN || state_right == SRS_WAIT_FOR_SCAN)
{
- if (new_left == NULL)
- {
- new_left = expr->left;
- g_object_ref(G_OBJECT(new_left));
- }
+ if (new_left != expr->left || new_right != expr->right)
+ *out = g_scan_string_operation_new(expr->type, new_left, new_right, expr->case_sensitive);
- if (new_right == NULL)
- {
- new_right = expr->right;
- g_object_ref(G_OBJECT(new_right));
- }
+ result = SRS_WAIT_FOR_SCAN;
- *out = g_string_operation_new(expr->type, new_left, new_right, expr->case_sensitive);
+ }
+
+ /* Cas des situations où les expressions ne sont pas exploitables (!) */
+ else
+ {
+ assert(state_left == SRS_REDUCED && state_right == SRS_REDUCED);
+
+ result = SRS_UNRESOLVABLE;
}
+ /* Sortie propre */
+
exit:
g_clear_object(&new_left);
diff --git a/src/analysis/scan/exprs/strop.h b/src/analysis/scan/exprs/strop.h
index c7c0813..0a32269 100644
--- a/src/analysis/scan/exprs/strop.h
+++ b/src/analysis/scan/exprs/strop.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* strop.h - prototypes pour la gestion des opérations booléennes
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -29,19 +29,19 @@
-#define G_TYPE_STRING_OPERATION g_string_operation_get_type()
-#define G_STRING_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_STRING_OPERATION, GStringOperation))
-#define G_IS_STRING_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_STRING_OPERATION))
-#define G_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_STRING_OPERATION, GStringOperationClass))
-#define G_IS_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_STRING_OPERATION))
-#define G_STRING_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_STRING_OPERATION, GStringOperationClass))
+#define G_TYPE_SCAN_STRING_OPERATION g_scan_string_operation_get_type()
+#define G_SCAN_STRING_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_STRING_OPERATION, GScanStringOperation))
+#define G_IS_SCAN_STRING_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_STRING_OPERATION))
+#define G_SCAN_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_STRING_OPERATION, GScanStringOperationClass))
+#define G_IS_SCAN_STRING_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_STRING_OPERATION))
+#define G_SCAN_STRING_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_STRING_OPERATION, GScanStringOperationClass))
/* Opération booléenne avec un ou deux opérandes (instance) */
-typedef struct _GStringOperation GStringOperation;
+typedef struct _GScanStringOperation GScanStringOperation;
/* Opération booléenne avec un ou deux opérandes (classe) */
-typedef struct _GStringOperationClass GStringOperationClass;
+typedef struct _GScanStringOperationClass GScanStringOperationClass;
/* Types d'opérations booléennes supportées */
@@ -57,10 +57,10 @@ typedef enum _StringOperationType
/* Indique le type défini pour une opération traitant une chaîne de caractères. */
-GType g_string_operation_get_type(void);
+GType g_scan_string_operation_get_type(void);
/* Organise un appel de fonction avec ses arguments. */
-GScanExpression *g_string_operation_new(StringOperationType, GScanExpression *, GScanExpression *, bool);
+GScanExpression *g_scan_string_operation_new(StringOperationType, GScanExpression *, GScanExpression *, bool);
diff --git a/src/analysis/scan/grammar.y b/src/analysis/scan/grammar.y
index 525c5d1..19a4257 100644
--- a/src/analysis/scan/grammar.y
+++ b/src/analysis/scan/grammar.y
@@ -18,12 +18,15 @@ typedef void *yyscan_t;
#include "scanner.h"
#include "exprs/access.h"
-#include "exprs/arithmop.h"
-#include "exprs/boolop.h"
+#include "exprs/arithmetic.h"
#include "exprs/call.h"
+#include "exprs/counter.h"
+#include "exprs/intersect.h"
#include "exprs/literal.h"
+#include "exprs/logical.h"
+#include "exprs/set.h"
+#include "exprs/relational.h"
#include "exprs/strop.h"
-#include "exprs/relop.h"
#include "patterns/tokens/plain.h"
@@ -48,13 +51,12 @@ typedef void *yyscan_t;
unsigned long long unsigned_integer; /* Valeur entière #1 */
signed long long signed_integer; /* Valeur entière #2 */
- double floating_number; /* Valeur à virgule flottante */
+ //double floating_number; /* Valeur à virgule flottante */
sized_string_t sized_cstring; /* Chaîne de caractères */
- char byte; /* Octet unique */
+ //char byte; /* Octet unique */
- unsigned long long integer; /* Valeur entière */
GScanRule *rule; /* Nouvelle règle à intégrer */
@@ -89,11 +91,17 @@ YY_DECL;
}
+%token INCLUDE "include"
+
%token RAW_RULE
%token RULE_NAME
%token STRINGS CONDITION
%token IDENTIFIER
+%token BYTES_ID
+%token BYTES_ID_COUNTER
+%token BYTES_ID_LOCATION
+%token BYTES_ID_LENGTH
%token NAME
%token BRACE_IN BRACE_OUT ASSIGN COLON
@@ -104,7 +112,8 @@ YY_DECL;
%token TRUE_ "true"
%token FALSE_ "false"
-%token INTEGER
+%token SIGNED_INTEGER
+%token UNSIGNED_INTEGER
%token STRING
%token KB MB GB
@@ -132,7 +141,7 @@ YY_DECL;
%token PLUS "+"
%token MINUS "-"
%token MUL "*"
-%token DIV "\\"
+%token DIV "/"
%token MOD "%"
%token PAREN_O "("
@@ -145,16 +154,18 @@ YY_DECL;
%token ALL "all"
%token OF "of"
%token THEM "them"
+%token IN "in"
%type <sized_cstring> RULE_NAME
-%type <sized_cstring> IDENTIFIER
+%type <sized_cstring> IDENTIFIER BYTES_ID_COUNTER
%type <sized_cstring> NAME
-%type <integer> INTEGER
+%type <signed_integer> SIGNED_INTEGER
+%type <unsigned_integer> UNSIGNED_INTEGER
%type <sized_cstring> STRING
%type <rule> rule
@@ -162,16 +173,19 @@ YY_DECL;
%type <sized_cstring> PLAIN_STRING
%type <pattern> MASKED_STRING
-%type <expr> cexpression
+%type <expr> cexpression _cexpression
+%type <expr> pattern_match
%type <expr> literal
%type <expr> item_chain
%type <args_list> call_args
-%type <expr> bool_expr
-%type <expr> rel_expr
-%type <expr> str_expr
+%type <expr> logical_expr
+%type <expr> relational_expr
+%type <expr> string_op
%type <expr> arithm_expr
%type <expr> set_counter
-
+%type <expr> set
+%type <expr> set_items
+%type <expr> intersection
%left OR
@@ -181,11 +195,11 @@ YY_DECL;
%left LT LE GT GE
%left PLUS MINUS
%left MUL DIV MOD
+%left IN
%right NOT
-
%destructor { printf("-------- Discarding symbol %p.\n", $$); } <rule>
@@ -207,12 +221,24 @@ YY_DECL;
rules : /* empty */
+ | external rules
| rule rules { g_content_scanner_add_rule(scanner, $1); }
//rule : RAW_RULE RULE_NAME { printf("RULE %s\n", $2); } RAW_BLOCK { printf("BLOCK: %s\n", $4); }
+
+external : "include" STRING
+ {
+ bool __status;
+ __status = g_content_scanner_include_resource(scanner, $2.data);
+ if (!__status)
+ YYERROR;
+ }
+
+
rule : RAW_RULE RULE_NAME
{
+ //printf("--------built rule '%s'\n", $2.data);
*built_rule = g_scan_rule_new($2.data);
$<rule>$ = *built_rule;
}
@@ -220,6 +246,7 @@ rule : RAW_RULE RULE_NAME
{
$$ = $<rule>3;
//printf("RULE %s -> %p\n", $2, $$);
+ //printf("end of rule\n");
}
@@ -274,16 +301,18 @@ string_decl : IDENTIFIER ASSIGN PLAIN_STRING
}
;
-condition : /* empty */
- | CONDITION COLON cexpression
- {
- g_scan_rule_set_match_condition(*built_rule, $3);
- g_object_ref(G_OBJECT($3));
- }
- ;
+ condition : /* empty */
+ | CONDITION COLON cexpression
+ {
+ g_scan_rule_set_match_condition(*built_rule, $3);
+ g_object_unref(G_OBJECT($3));
+ }
+ ;
-cexpression : IDENTIFIER
- {
+ cexpression : _cexpression { $$ = $1; if ($$ == NULL) { printf("ERROR !!!\n"); YYERROR; } }
+
+ _cexpression : IDENTIFIER
+ {
printf("named var: %s\n", "$1");
/*
GSearchPattern *__pat;
@@ -297,112 +326,223 @@ cexpression : IDENTIFIER
g_object_unref(G_OBJECT(__pat));
}
*/
- }
- | literal { $$ = $1; }
- | item_chain { $$ = $1; }
- | bool_expr { $$ = $1; }
- | rel_expr { $$ = $1; }
- | str_expr { $$ = $1; }
- | arithm_expr { $$ = $1; }
- | set_counter { $$ = $1; }
- | "(" cexpression ")" { $$ = $2; }
+ }
+ | literal { $$ = $1; }
+ | pattern_match { $$ = $1; }
+ | item_chain { $$ = $1; }
+ | logical_expr { $$ = $1; }
+ | relational_expr { $$ = $1; }
+ | string_op { $$ = $1; }
+ | arithm_expr { $$ = $1; }
+ | set_counter { $$ = $1; }
+ | set { $$ = $1; }
+ | intersection { $$ = $1; }
+ | "(" cexpression ")" { $$ = $2; }
+ ;
+
+ pattern_match : BYTES_ID_COUNTER
+ {
+ GSearchPattern *__pat;
+ __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
+ $$ = g_scan_match_counter_new(__pat);
+ g_object_unref(G_OBJECT(__pat));
+ }
+ ;
+
+ literal : "true"
+ {
+ $$ = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ true });
+ }
+ | "false"
+ {
+ $$ = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ false });
+ }
+ | SIGNED_INTEGER
+ {
+ $$ = g_scan_literal_expression_new(LVT_SIGNED_INTEGER, &$1);
+ }
+ | UNSIGNED_INTEGER
+ {
+ $$ = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &$1);
+ }
+ | UNSIGNED_INTEGER KB
+ {
+ unsigned long long __converted;
+ __converted = $1 * 1024;
+ $$ = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &__converted);
+ }
+ | UNSIGNED_INTEGER MB
+ {
+ unsigned long long __converted;
+ __converted = $1 * 1048576;
+ $$ = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &__converted);
+ }
+ | UNSIGNED_INTEGER GB
+ {
+ unsigned long long __converted;
+ __converted = $1 * 1073741824;
+ $$ = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &__converted);
+ }
+ | STRING
+ {
+ $$ = g_scan_literal_expression_new(LVT_STRING, &$1);
+ }
+ ;
+
+ item_chain : NAME { $$ = g_scan_named_access_new(&$1); }
+ | NAME "(" ")" { $$ = g_scan_pending_call_new(&$1, NULL, 0); }
+ | NAME "(" call_args ")"
+ {
+ size_t __i;
+ $$ = g_scan_pending_call_new(&$1, $3.args, $3.count);
+ for (__i = 0; __i < $3.count; __i++)
+ g_object_unref(G_OBJECT($3.args[__i]));
+ free($3.args);
+ }
+ | item_chain "." NAME
+ {
+ GScanExpression *__next;
+ __next = g_scan_named_access_new(&$3);
+ g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS($1), G_SCAN_NAMED_ACCESS(__next));
+ $$ = $1;
+ }
+ | item_chain "." NAME "(" ")"
+ {
+ GScanExpression *__next;
+ __next = g_scan_pending_call_new(&$3, NULL, 0);
+ g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS($1), G_SCAN_NAMED_ACCESS(__next));
+ $$ = $1;
+ }
+ | item_chain "." NAME "(" call_args ")"
+ {
+ GScanExpression *__next;
+ size_t __i;
+ __next = g_scan_pending_call_new(&$3, $5.args, $5.count);
+ for (__i = 0; __i < $5.count; __i++)
+ g_object_unref(G_OBJECT($5.args[__i]));
+ free($5.args);
+ g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS($1), G_SCAN_NAMED_ACCESS(__next));
+ $$ = $1;
+ }
+ ;
+
+ call_args : cexpression
+ {
+ $$.count = 1;
+ $$.args = malloc(sizeof(GScanExpression *));
+ $$.args[0] = $1;
+ }
+ | call_args "," cexpression
+ {
+ $1.count++;
+ $1.args = realloc($1.args, $1.count * sizeof(GScanExpression *));
+ $1.args[$1.count - 1] = $3;
+ $$ = $1;
+ }
+ ;
+
+ logical_expr : cexpression "and" cexpression { $$ = g_scan_logical_operation_new(BOT_AND, $1, $3); }
+ | cexpression "or" cexpression { $$ = g_scan_logical_operation_new(BOT_OR, $1, $3); }
+ | "not" "(" cexpression ")" { $$ = g_scan_logical_operation_new(BOT_NOT, $3, NULL); }
+ ;
+
+relational_expr : cexpression "<" cexpression { $$ = g_scan_relational_operation_new(RCO_LT, $1, $3); }
+ | cexpression "<=" cexpression { $$ = g_scan_relational_operation_new(RCO_LE, $1, $3); }
+ | cexpression "==" cexpression { $$ = g_scan_relational_operation_new(RCO_EQ, $1, $3); }
+ | cexpression "!=" cexpression { $$ = g_scan_relational_operation_new(RCO_NE, $1, $3); }
+ | cexpression ">" cexpression { $$ = g_scan_relational_operation_new(RCO_GT, $1, $3); }
+ | cexpression ">=" cexpression { $$ = g_scan_relational_operation_new(RCO_GE, $1, $3); }
+ ;
+
+ string_op : cexpression "contains" cexpression
+ {
+ $$ = g_scan_string_operation_new(SOT_CONTAINS, $1, $3, true);
+ }
+ | cexpression "startswith" cexpression
+ {
+ $$ = g_scan_string_operation_new(SOT_STARTSWITH, $1, $3, true);
+ }
+ | cexpression "endswith" cexpression
+ {
+ $$ = g_scan_string_operation_new(SOT_ENDSWITH, $1, $3, true);
+ }
+ | cexpression "matches" cexpression
+ {
+ $$ = g_scan_string_operation_new(SOT_MATCHES, $1, $3, true);
+ }
+ | cexpression "icontains" cexpression
+ {
+ $$ = g_scan_string_operation_new(SOT_CONTAINS, $1, $3, false);
+ }
+ | cexpression "istartswith" cexpression
+ {
+ $$ = g_scan_string_operation_new(SOT_STARTSWITH, $1, $3, false);
+ }
+ | cexpression "iendswith" cexpression
+ {
+ $$ = g_scan_string_operation_new(SOT_ENDSWITH, $1, $3, false);
+ }
+ | cexpression "iequals" cexpression
+ {
+ $$ = g_scan_string_operation_new(SOT_IEQUALS, $1, $3, false);
+ }
+ ;
+
+ arithm_expr : cexpression "+" cexpression { $$ = g_scan_arithmetic_operation_new(AEO_PLUS, $1, $3); }
+ | cexpression "-" cexpression { $$ = g_scan_arithmetic_operation_new(AEO_MINUS, $1, $3); }
+ | cexpression "*" cexpression { $$ = g_scan_arithmetic_operation_new(AEO_MUL, $1, $3); }
+ | cexpression "/" cexpression { $$ = g_scan_arithmetic_operation_new(AEO_DIV, $1, $3); }
+ | cexpression "%" cexpression { $$ = g_scan_arithmetic_operation_new(AEO_MOD, $1, $3); }
+ ;
+
+set_counter : "none" "of" "them" { $$ = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ true }); }
+ | "any" "of" "them" { $$ = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ true }); }
+ | "all" "of" "them" { $$ = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ true }); }
;
-literal : "true" { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ true }); }
- | "false" { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ false }); }
- | INTEGER { $$ = g_literal_expression_new(EVT_INTEGER, &$1); }
- | INTEGER KB { $$ = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ $1 * 1024 }); }
- | INTEGER MB { $$ = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ $1 * 1048576 }); }
- | INTEGER GB { $$ = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ $1 * 1073741824 }); }
- | STRING { $$ = g_literal_expression_new(EVT_STRING, &$1); }
- ;
-item_chain : NAME { $$ = g_named_access_new(&$1); }
- | NAME "(" ")" { $$ = g_pending_call_new(&$1, NULL, 0); }
- | NAME "(" call_args ")"
- {
- size_t __i;
- $$ = g_pending_call_new(&$1, $3.args, $3.count);
- for (__i = 0; __i < $3.count; __i++)
- g_object_unref(G_OBJECT($3.args[__i]));
- free($3.args);
- }
- | item_chain "." NAME
- {
- GScanExpression *__next;
- __next = g_named_access_new(&$3);
- g_named_access_attach_next(G_NAMED_ACCESS($1), G_NAMED_ACCESS(__next));
- $$ = $1;
- }
- | item_chain "." NAME "(" ")"
- {
- GScanExpression *__next;
- __next = g_pending_call_new(&$3, NULL, 0);
- g_named_access_attach_next(G_NAMED_ACCESS($1), G_NAMED_ACCESS(__next));
- $$ = $1;
- }
- | item_chain "." NAME "(" call_args ")"
- {
- GScanExpression *__next;
- size_t __i;
- __next = g_pending_call_new(&$3, $5.args, $5.count);
- for (__i = 0; __i < $5.count; __i++)
- g_object_unref(G_OBJECT($5.args[__i]));
- free($5.args);
- g_named_access_attach_next(G_NAMED_ACCESS($1), G_NAMED_ACCESS(__next));
- $$ = $1;
- }
- ;
-
-call_args : cexpression
- {
- $$.count = 1;
- $$.args = malloc(sizeof(GScanExpression *));
- $$.args[0] = $1;
- }
- | call_args "," cexpression
- {
- $1.count++;
- $1.args = realloc($1.args, $1.count * sizeof(GScanExpression *));
- $1.args[$1.count - 1] = $3;
- $$ = $1;
- }
- ;
-
-bool_expr : cexpression "and" cexpression { $$ = g_boolean_operation_new(BOT_AND, $1, $3); }
- | cexpression "or" cexpression { $$ = g_boolean_operation_new(BOT_OR, $1, $3); }
- | "not" "(" cexpression ")" { $$ = g_boolean_operation_new(BOT_NOT, $3, NULL); }
- ;
-
-rel_expr : cexpression "<" cexpression { $$ = g_relational_operation_new(RCO_LT, $1, $3); }
- | cexpression "<=" cexpression { $$ = g_relational_operation_new(RCO_LE, $1, $3); }
- | cexpression "==" cexpression { $$ = g_relational_operation_new(RCO_EQ, $1, $3); }
- | cexpression "!=" cexpression { $$ = g_relational_operation_new(RCO_NE, $1, $3); }
- | cexpression ">" cexpression { $$ = g_relational_operation_new(RCO_GT, $1, $3); }
- | cexpression ">=" cexpression { $$ = g_relational_operation_new(RCO_GT, $1, $3); }
- ;
-
-str_expr : cexpression "contains" cexpression { $$ = g_string_operation_new(SOT_CONTAINS, $1, $3, true); }
- | cexpression "startswith" cexpression { $$ = g_string_operation_new(SOT_STARTSWITH, $1, $3, true); }
- | cexpression "endswith" cexpression { $$ = g_string_operation_new(SOT_ENDSWITH, $1, $3, true); }
- | cexpression "matches" cexpression { $$ = g_string_operation_new(SOT_MATCHES, $1, $3, true); }
- | cexpression "icontains" cexpression { $$ = g_string_operation_new(SOT_CONTAINS, $1, $3, false); }
- | cexpression "istartswith" cexpression { $$ = g_string_operation_new(SOT_STARTSWITH, $1, $3, false); }
- | cexpression "iendswith" cexpression { $$ = g_string_operation_new(SOT_ENDSWITH, $1, $3, false); }
- | cexpression "iequals" cexpression { $$ = g_string_operation_new(SOT_IEQUALS, $1, $3, false); }
- ;
-
-arithm_expr : cexpression "+" cexpression { $$ = g_arithmetic_operation_new(AEO_PLUS, $1, $3); }
- | cexpression "-" cexpression { $$ = g_arithmetic_operation_new(AEO_MINUS, $1, $3); }
- | cexpression "*" cexpression { $$ = g_arithmetic_operation_new(AEO_MUL, $1, $3); }
- | cexpression "\\" cexpression { $$ = g_arithmetic_operation_new(AEO_DIV, $1, $3); }
- | cexpression "%" cexpression { $$ = g_arithmetic_operation_new(AEO_MOD, $1, $3); }
- ;
+ set : "(" ")"
+ {
+ $$ = g_scan_generic_set_new();
+ }
+ | "(" cexpression "," ")"
+ {
+ $$ = g_scan_generic_set_new();
+ g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $2);
+ g_object_unref(G_OBJECT($2));
+ }
+ | "(" set_items ")"
+ {
+ $$ = $2;
+ }
+ ;
+
+ set_items : cexpression "," cexpression
+ {
+ $$ = g_scan_generic_set_new();
+ g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $1);
+ g_object_unref(G_OBJECT($1));
+ g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $3);
+ g_object_unref(G_OBJECT($3));
+ }
+ | set_items "," cexpression
+ {
+ $$ = $1;
+ g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $3);
+ g_object_unref(G_OBJECT($3));
+ }
+ ;
+
+ intersection : cexpression "in" cexpression
+ {
+ $$ = g_scan_sets_intersection_new($1, $3);
+ g_object_unref(G_OBJECT($1));
+ g_object_unref(G_OBJECT($3));
+ }
+ ;
+
+
-set_counter : "none" "of" "them" { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ true }); }
- | "any" "of" "them" { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ true }); }
- | "all" "of" "them" { $$ = g_literal_expression_new(EVT_BOOLEAN, (bool []){ true }); }
- ;
%%
diff --git a/src/analysis/scan/items/Makefile.am b/src/analysis/scan/items/Makefile.am
index 3a6bb62..ce39cad 100644
--- a/src/analysis/scan/items/Makefile.am
+++ b/src/analysis/scan/items/Makefile.am
@@ -2,14 +2,32 @@
noinst_LTLIBRARIES = libanalysisscanitems.la
+if BUILD_MAGIC_SUPPORT
+
+MAGIC_LIBADD = magic/libanalysisscanitemsmagic.la
+
+MAGIC_SUBDIRS = magic
+
+endif
+
+
libanalysisscanitems_la_SOURCES = \
+ count.h count.c \
datasize.h datasize.c \
uint-int.h \
uint.h uint.c
+libanalysisscanitems_la_LIBADD = \
+ console/libanalysisscanitemsconsole.la \
+ $(MAGIC_LIBADD) \
+ time/libanalysisscanitemstime.la
+
libanalysisscanitems_la_CFLAGS = $(LIBGOBJ_CFLAGS)
devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
dev_HEADERS = $(libanalysisscanitems_la_SOURCES:%c=)
+
+
+SUBDIRS = console $(MAGIC_SUBDIRS) time
diff --git a/src/analysis/scan/items/console/Makefile.am b/src/analysis/scan/items/console/Makefile.am
new file mode 100644
index 0000000..4433789
--- /dev/null
+++ b/src/analysis/scan/items/console/Makefile.am
@@ -0,0 +1,13 @@
+
+noinst_LTLIBRARIES = libanalysisscanitemsconsole.la
+
+
+libanalysisscanitemsconsole_la_SOURCES = \
+ log.h log.c
+
+libanalysisscanitemsconsole_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscanitemsconsole_la_SOURCES:%c=)
diff --git a/src/analysis/scan/items/console/log.c b/src/analysis/scan/items/console/log.c
new file mode 100644
index 0000000..f4031c7
--- /dev/null
+++ b/src/analysis/scan/items/console/log.c
@@ -0,0 +1,303 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * log.c - affichage de message à partir des conditions d'une règle
+ *
+ * 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 "log.h"
+
+
+#include <ctype.h>
+
+
+#include "../../item-int.h"
+#include "../../exprs/literal.h"
+
+
+
+/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */
+
+
+/* Initialise la classe des affichages de messages. */
+static void g_scan_console_log_function_class_init(GScanConsoleLogFunctionClass *);
+
+/* Initialise une instance d'affichage de message. */
+static void g_scan_console_log_function_init(GScanConsoleLogFunction *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_console_log_function_dispose(GScanConsoleLogFunction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_console_log_function_finalize(GScanConsoleLogFunction *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_scan_console_log_function_get_name(const GScanConsoleLogFunction *);
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_scan_console_log_function_run_call(GScanConsoleLogFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE FONCTION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un afficheur de messages arbitraires. */
+G_DEFINE_TYPE(GScanConsoleLogFunction, g_scan_console_log_function, G_TYPE_REGISTERED_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des affichages de messages. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_console_log_function_class_init(GScanConsoleLogFunctionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_console_log_function_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_console_log_function_finalize;
+
+ registered = G_REGISTERED_ITEM_CLASS(klass);
+
+ registered->get_name = (get_registered_item_name_fc)g_scan_console_log_function_get_name;
+ registered->run_call = (run_registered_item_call_fc)g_scan_console_log_function_run_call;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance à initialiser. *
+* *
+* Description : Initialise une instance d'affichage de message. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_console_log_function_init(GScanConsoleLogFunction *func)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_console_log_function_dispose(GScanConsoleLogFunction *func)
+{
+ G_OBJECT_CLASS(g_scan_console_log_function_parent_class)->dispose(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_console_log_function_finalize(GScanConsoleLogFunction *func)
+{
+ G_OBJECT_CLASS(g_scan_console_log_function_parent_class)->finalize(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Constitue une fonction d'affichage de messages quelconques. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanConsoleLogFunction *g_scan_console_log_function_new(void)
+{
+ GScanConsoleLogFunction *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_CONSOLE_LOG_FUNCTION, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* *
+* Description : Indique le nom associé à une expression d'évaluation. *
+* *
+* Retour : Désignation humaine de l'expression d'évaluation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_console_log_function_get_name(const GScanConsoleLogFunction *item)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("log");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* args = liste d'éventuels arguments fournis. *
+* count = taille de cette liste. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_console_log_function_run_call(GScanConsoleLogFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours #1 */
+ LiteralValueType vtype; /* Type de valeur portée */
+ GScanLiteralExpression *literal; /* Version plus accessible */
+ bool boolean; /* Valeur booléenne */
+ long long sinteger; /* Valeur entière signée */
+ unsigned long long uinteger; /* Valeur entière non signée */
+ const sized_string_t *string; /* Description du chaîne */
+ size_t k; /* Boucle de parcours #2 */
+
+ result = true;
+
+ if (count == 0)
+ goto done;
+
+ for (i = 0; i < count && result; i++)
+ result = G_IS_SCAN_LITERAL_EXPRESSION(args[i]);
+
+ if (!result)
+ goto done;
+
+ for (i = 0; i < count; i++)
+ {
+ literal = G_SCAN_LITERAL_EXPRESSION(args[i]);
+
+ vtype = g_scan_literal_expression_get_value_type(literal);
+
+ switch (vtype)
+ {
+ case LVT_BOOLEAN:
+ result = g_scan_literal_expression_get_boolean_value(literal, &boolean);
+ if (result)
+ fprintf(stderr, "%s", boolean ? "true" : "false");
+ break;
+
+ case LVT_SIGNED_INTEGER:
+ result = g_scan_literal_expression_get_signed_integer_value(literal, &sinteger);
+ if (result)
+ fprintf(stderr, "0x%llx", sinteger);
+ break;
+
+ case LVT_UNSIGNED_INTEGER:
+ result = g_scan_literal_expression_get_unsigned_integer_value(literal, &uinteger);
+ if (result)
+ fprintf(stderr, "0x%llx", uinteger);
+ break;
+
+ case LVT_STRING:
+ result = g_scan_literal_expression_get_string_value(literal, &string);
+ for (k = 0; k < string->len; k++)
+ {
+ if (isprint(string->data[k]))
+ fprintf(stderr, "%c", string->data[k]);
+ else
+ fprintf(stderr, "\\x%02hhx", string->data[k]);
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ }
+
+ fprintf(stderr, "\n");
+
+ done:
+
+ if (result)
+ *out = G_OBJECT(g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ result }));
+
+ return result;
+
+}
diff --git a/src/analysis/scan/items/console/log.h b/src/analysis/scan/items/console/log.h
new file mode 100644
index 0000000..3e72ad8
--- /dev/null
+++ b/src/analysis/scan/items/console/log.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * log.h - prototypes pour l'affichage de message à partir des conditions d'une règle
+ *
+ * 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_ITEMS_CONSOLE_LOG_H
+#define _ANALYSIS_SCAN_ITEMS_CONSOLE_LOG_H
+
+
+#include <glib-object.h>
+
+
+#include "../../item.h"
+
+
+
+#define G_TYPE_SCAN_CONSOLE_LOG_FUNCTION g_scan_console_log_function_get_type()
+#define G_SCAN_CONSOLE_LOG_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_CONSOLE_LOG_FUNCTION, GScanConsoleLogFunction))
+#define G_IS_SCAN_CONSOLE_LOG_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_CONSOLE_LOG_FUNCTION))
+#define G_SCAN_CONSOLE_LOG_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_CONSOLE_LOG_FUNCTION, GScanConsoleLogFunctionClass))
+#define G_IS_SCAN_CONSOLE_LOG_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_CONSOLE_LOG_FUNCTION))
+#define G_SCAN_CONSOLE_LOG_FUNCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_CONSOLE_LOG_FUNCTION, GScanConsoleLogFunctionClass))
+
+
+/* Mesure de la quantité de données scannées (instance) */
+typedef GRegisteredItem GScanConsoleLogFunction;
+
+/* Mesure de la quantité de données scannées (classe) */
+typedef GRegisteredItemClass GScanConsoleLogFunctionClass;
+
+
+/* Indique le type défini pour un afficheur de messages arbitraires. */
+GType g_scan_console_log_function_get_type(void);
+
+/* Constitue une fonction d'affichage de messages quelconques. */
+GScanConsoleLogFunction *g_scan_console_log_function_new(void);
+
+
+
+#endif /* _ANALYSIS_SCAN_ITEMS_CONSOLE_LOG_H */
diff --git a/src/analysis/scan/items/count.c b/src/analysis/scan/items/count.c
new file mode 100644
index 0000000..d87d33b
--- /dev/null
+++ b/src/analysis/scan/items/count.c
@@ -0,0 +1,244 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * count.c - récupération de la taille du contenu scanné
+ *
+ * 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 "count.h"
+
+
+#include "../item-int.h"
+#include "../exprs/arithmetic.h"
+#include "../exprs/literal.h"
+
+
+
+/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */
+
+
+/* Initialise la classe des décomptes d'ensemble homogène. */
+static void g_scan_count_function_class_init(GScanCountFunctionClass *);
+
+/* Initialise une instance de décompte d'ensemble homogène. */
+static void g_scan_count_function_init(GScanCountFunction *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_count_function_dispose(GScanCountFunction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_count_function_finalize(GScanCountFunction *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_scan_count_function_get_name(const GScanCountFunction *);
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_scan_count_function_run_call(GScanCountFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE FONCTION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un décompte d'ensemble. */
+G_DEFINE_TYPE(GScanCountFunction, g_scan_count_function, G_TYPE_REGISTERED_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des décomptes d'ensemble homogène. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_count_function_class_init(GScanCountFunctionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_count_function_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_count_function_finalize;
+
+ registered = G_REGISTERED_ITEM_CLASS(klass);
+
+ registered->get_name = (get_registered_item_name_fc)g_scan_count_function_get_name;
+ registered->run_call = (run_registered_item_call_fc)g_scan_count_function_run_call;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance à initialiser. *
+* *
+* Description : Initialise une instance de décompte d'ensemble homogène. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_count_function_init(GScanCountFunction *func)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_count_function_dispose(GScanCountFunction *func)
+{
+ G_OBJECT_CLASS(g_scan_count_function_parent_class)->dispose(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_count_function_finalize(GScanCountFunction *func)
+{
+ G_OBJECT_CLASS(g_scan_count_function_parent_class)->finalize(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Constitue une fonction de décompte d'éléments d'un ensemble. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GRegisteredItem *g_scan_count_function_new(void)
+{
+ GScanCountFunction *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_COUNT_FUNCTION, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* *
+* Description : Indique le nom associé à une expression d'évaluation. *
+* *
+* Retour : Désignation humaine de l'expression d'évaluation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_count_function_get_name(const GScanCountFunction *item)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("count");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* args = liste d'éventuels arguments fournis. *
+* count = taille de cette liste. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_count_function_run_call(GScanCountFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+{
+ bool result; /* Bilan à retourner */
+ size_t value; /* Nouveau décompte */
+
+ if (count != 1)
+ result = false;
+
+ else
+ {
+ result = g_scan_expression_count_items(args[0], &value);
+
+ if (result)
+ *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ value }));
+
+ }
+
+ return result;
+
+}
diff --git a/src/analysis/scan/items/count.h b/src/analysis/scan/items/count.h
new file mode 100644
index 0000000..2429e40
--- /dev/null
+++ b/src/analysis/scan/items/count.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * count.h - prototypes pour la récupération de la taille du contenu scanné
+ *
+ * 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_ITEMS_COUNT_H
+#define _ANALYSIS_SCAN_ITEMS_COUNT_H
+
+
+#include <glib-object.h>
+
+
+#include "../item.h"
+
+
+
+#define G_TYPE_SCAN_COUNT_FUNCTION g_scan_count_function_get_type()
+#define G_SCAN_COUNT_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_COUNT_FUNCTION, GScanCountFunction))
+#define G_IS_SCAN_COUNT_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_COUNT_FUNCTION))
+#define G_SCAN_COUNT_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_COUNT_FUNCTION, GScanCountFunctionClass))
+#define G_IS_SCAN_COUNT_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_COUNT_FUNCTION))
+#define G_SCAN_COUNT_FUNCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_COUNT_FUNCTION, GScanCountFunctionClass))
+
+
+/* Mesure de la quantité de données scannées (instance) */
+typedef GRegisteredItem GScanCountFunction;
+
+/* Mesure de la quantité de données scannées (classe) */
+typedef GRegisteredItemClass GScanCountFunctionClass;
+
+
+/* Indique le type défini pour un décompte d'ensemble. */
+GType g_scan_count_function_get_type(void);
+
+/* Constitue une fonction de décompte d'éléments d'un ensemble. */
+GRegisteredItem *g_scan_count_function_new(void);
+
+
+
+#endif /* _ANALYSIS_SCAN_ITEMS_COUNT_H */
diff --git a/src/analysis/scan/items/datasize.c b/src/analysis/scan/items/datasize.c
index 618d0c3..55e2d3b 100644
--- a/src/analysis/scan/items/datasize.c
+++ b/src/analysis/scan/items/datasize.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* datasize.c - récupération de la taille du contenu scanné
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -33,16 +33,16 @@
/* Initialise la classe des mesures de quantité de données. */
-static void g_datasize_function_class_init(GDatasizeFunctionClass *);
+static void g_scan_datasize_function_class_init(GScanDatasizeFunctionClass *);
/* Initialise une instance de mesure de quantité de données. */
-static void g_datasize_function_init(GDatasizeFunction *);
+static void g_scan_datasize_function_init(GScanDatasizeFunction *);
/* Supprime toutes les références externes. */
-static void g_datasize_function_dispose(GDatasizeFunction *);
+static void g_scan_datasize_function_dispose(GScanDatasizeFunction *);
/* Procède à la libération totale de la mémoire. */
-static void g_datasize_function_finalize(GDatasizeFunction *);
+static void g_scan_datasize_function_finalize(GScanDatasizeFunction *);
@@ -50,13 +50,13 @@ static void g_datasize_function_finalize(GDatasizeFunction *);
/* Indique le nom associé à une expression d'évaluation. */
-static char *g_datasize_function_get_name(const GDatasizeFunction *);
+static char *g_scan_datasize_function_get_name(const GScanDatasizeFunction *);
/* Réduit une expression à une forme plus simple. */
-static bool g_datasize_function_reduce(GDatasizeFunction *, GScanContext *, GScanScope *, GScanExpression **);
+static bool g_scan_datasize_function_reduce(GScanDatasizeFunction *, GScanContext *, GScanScope *, GScanExpression **);
/* Réduit une expression à une forme plus simple. */
-static bool g_datasize_function_run_call(GDatasizeFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+static bool g_scan_datasize_function_run_call(GScanDatasizeFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
@@ -66,7 +66,7 @@ static bool g_datasize_function_run_call(GDatasizeFunction *, GScanExpression **
/* Indique le type défini pour une mesure de quantité de données scannées. */
-G_DEFINE_TYPE(GDatasizeFunction, g_datasize_function, G_TYPE_REGISTERED_ITEM);
+G_DEFINE_TYPE(GScanDatasizeFunction, g_scan_datasize_function, G_TYPE_REGISTERED_ITEM);
/******************************************************************************
@@ -81,21 +81,21 @@ G_DEFINE_TYPE(GDatasizeFunction, g_datasize_function, G_TYPE_REGISTERED_ITEM);
* *
******************************************************************************/
-static void g_datasize_function_class_init(GDatasizeFunctionClass *klass)
+static void g_scan_datasize_function_class_init(GScanDatasizeFunctionClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GRegisteredItemClass *registered; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_datasize_function_dispose;
- object->finalize = (GObjectFinalizeFunc)g_datasize_function_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_datasize_function_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_datasize_function_finalize;
registered = G_REGISTERED_ITEM_CLASS(klass);
- registered->get_name = (get_registered_item_name_fc)g_datasize_function_get_name;
- registered->reduce = (reduce_registered_item_fc)g_datasize_function_reduce;
- registered->run_call = (run_registered_item_call_fc)g_datasize_function_run_call;
+ registered->get_name = (get_registered_item_name_fc)g_scan_datasize_function_get_name;
+ registered->reduce = (reduce_registered_item_fc)g_scan_datasize_function_reduce;
+ registered->run_call = (run_registered_item_call_fc)g_scan_datasize_function_run_call;
}
@@ -112,7 +112,7 @@ static void g_datasize_function_class_init(GDatasizeFunctionClass *klass)
* *
******************************************************************************/
-static void g_datasize_function_init(GDatasizeFunction *func)
+static void g_scan_datasize_function_init(GScanDatasizeFunction *func)
{
}
@@ -130,9 +130,9 @@ static void g_datasize_function_init(GDatasizeFunction *func)
* *
******************************************************************************/
-static void g_datasize_function_dispose(GDatasizeFunction *func)
+static void g_scan_datasize_function_dispose(GScanDatasizeFunction *func)
{
- G_OBJECT_CLASS(g_datasize_function_parent_class)->dispose(G_OBJECT(func));
+ G_OBJECT_CLASS(g_scan_datasize_function_parent_class)->dispose(G_OBJECT(func));
}
@@ -149,9 +149,9 @@ static void g_datasize_function_dispose(GDatasizeFunction *func)
* *
******************************************************************************/
-static void g_datasize_function_finalize(GDatasizeFunction *func)
+static void g_scan_datasize_function_finalize(GScanDatasizeFunction *func)
{
- G_OBJECT_CLASS(g_datasize_function_parent_class)->finalize(G_OBJECT(func));
+ G_OBJECT_CLASS(g_scan_datasize_function_parent_class)->finalize(G_OBJECT(func));
}
@@ -168,11 +168,11 @@ static void g_datasize_function_finalize(GDatasizeFunction *func)
* *
******************************************************************************/
-GDatasizeFunction *g_datasize_function_new(void)
+GRegisteredItem *g_scan_datasize_function_new(void)
{
- GDatasizeFunction *result; /* Structure à retourner */
+ GScanDatasizeFunction *result; /* Structure à retourner */
- result = g_object_new(G_TYPE_DATASIZE_FUNCTION, NULL);
+ result = g_object_new(G_TYPE_SCAN_DATASIZE_FUNCTION, NULL);
return result;
@@ -197,7 +197,7 @@ GDatasizeFunction *g_datasize_function_new(void)
* *
******************************************************************************/
-static char *g_datasize_function_get_name(const GDatasizeFunction *item)
+static char *g_scan_datasize_function_get_name(const GScanDatasizeFunction *item)
{
char *result; /* Désignation à retourner */
@@ -223,7 +223,7 @@ static char *g_datasize_function_get_name(const GDatasizeFunction *item)
* *
******************************************************************************/
-static bool g_datasize_function_reduce(GDatasizeFunction *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static bool g_scan_datasize_function_reduce(GScanDatasizeFunction *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
bool result; /* Bilan à retourner */
GBinContent *content; /* Contenu à manipuler */
@@ -235,7 +235,7 @@ static bool g_datasize_function_reduce(GDatasizeFunction *item, GScanContext *ct
size = g_binary_content_compute_size(content);
- *out = g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ size });
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ size });
g_object_unref(G_OBJECT(content));
@@ -261,11 +261,11 @@ static bool g_datasize_function_reduce(GDatasizeFunction *item, GScanContext *ct
* *
******************************************************************************/
-static bool g_datasize_function_run_call(GDatasizeFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+static bool g_scan_datasize_function_run_call(GScanDatasizeFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
{
bool result; /* Bilan à retourner */
- result = g_datasize_function_reduce(item, ctx, scope, (GScanExpression **)out);
+ result = g_scan_datasize_function_reduce(item, ctx, scope, (GScanExpression **)out);
return result;
diff --git a/src/analysis/scan/items/datasize.h b/src/analysis/scan/items/datasize.h
index bd8e185..476df2d 100644
--- a/src/analysis/scan/items/datasize.h
+++ b/src/analysis/scan/items/datasize.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* datasize.h - prototypes pour la récupération de la taille du contenu scanné
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -32,26 +32,26 @@
-#define G_TYPE_DATASIZE_FUNCTION g_datasize_function_get_type()
-#define G_DATASIZE_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DATASIZE_FUNCTION, GDatasizeFunction))
-#define G_IS_DATASIZE_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DATASIZE_FUNCTION))
-#define G_DATASIZE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DATASIZE_FUNCTION, GDatasizeFunctionClass))
-#define G_IS_DATASIZE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DATASIZE_FUNCTION))
-#define G_DATASIZE_FUNCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DATASIZE_FUNCTION, GDatasizeFunctionClass))
+#define G_TYPE_SCAN_DATASIZE_FUNCTION g_scan_datasize_function_get_type()
+#define G_SCAN_DATASIZE_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_DATASIZE_FUNCTION, GScanDatasizeFunction))
+#define G_IS_SCAN_DATASIZE_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_DATASIZE_FUNCTION))
+#define G_SCAN_DATASIZE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_DATASIZE_FUNCTION, GScanDatasizeFunctionClass))
+#define G_IS_SCAN_DATASIZE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_DATASIZE_FUNCTION))
+#define G_SCAN_DATASIZE_FUNCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_DATASIZE_FUNCTION, GScanDatasizeFunctionClass))
/* Mesure de la quantité de données scannées (instance) */
-typedef GRegisteredItem GDatasizeFunction;
+typedef GRegisteredItem GScanDatasizeFunction;
/* Mesure de la quantité de données scannées (classe) */
-typedef GRegisteredItemClass GDatasizeFunctionClass;
+typedef GRegisteredItemClass GScanDatasizeFunctionClass;
/* Indique le type défini pour une mesure de quantité de données scannées. */
-GType g_datasize_function_get_type(void);
+GType g_scan_datasize_function_get_type(void);
/* Constitue une fonction de récupération de taille de données. */
-GDatasizeFunction *g_datasize_function_new(void);
+GRegisteredItem *g_scan_datasize_function_new(void);
diff --git a/src/analysis/scan/items/magic/Makefile.am b/src/analysis/scan/items/magic/Makefile.am
new file mode 100644
index 0000000..1d741ff
--- /dev/null
+++ b/src/analysis/scan/items/magic/Makefile.am
@@ -0,0 +1,16 @@
+
+noinst_LTLIBRARIES = libanalysisscanitemsmagic.la
+
+
+libanalysisscanitemsmagic_la_SOURCES = \
+ cookie.h cookie.c \
+ mime-encoding.h mime-encoding.c \
+ mime-type.h mime-type.c \
+ type.h type.c
+
+libanalysisscanitemsmagic_la_CFLAGS = $(LIBGOBJ_CFLAGS) $(LIBMAGIC_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscanitemsmagic_la_SOURCES:%c=)
diff --git a/src/analysis/scan/items/magic/cookie.c b/src/analysis/scan/items/magic/cookie.c
new file mode 100644
index 0000000..41f26a0
--- /dev/null
+++ b/src/analysis/scan/items/magic/cookie.c
@@ -0,0 +1,122 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cookie.c - chargement des motifs de reconnaissance de contenus
+ *
+ * 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 "cookie.h"
+
+
+#include <assert.h>
+
+
+#include <i18n.h>
+
+
+#include "../../../../core/logs.h"
+
+
+
+/* Référence des bibliothèques de reconnaissance */
+static magic_t __magic_cookie = 0;
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Charge les motifs de reconnaissance de contenus. *
+* *
+* Retour : Bilan de l'opération de chargemement. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool init_magic_cookie(void)
+{
+ bool result; /* Bilan à retourner */
+ int ret; /* Bilan d'une opération */
+
+ __magic_cookie = magic_open(0);
+
+ ret = magic_load(__magic_cookie, NULL);
+ result = (ret != -1);
+
+ if (!result)
+ log_variadic_message(LMT_EXT_ERROR, _("cannot load magic database: %s"), magic_error(__magic_cookie));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Décharge les motifs de reconnaissance de contenus. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void exit_magic_cookie(void)
+{
+ magic_close(__magic_cookie);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : flags = forme de reconnaissance à préparer. *
+* *
+* Description : Fournit la référence aux mécanismes de reconnaissance. *
+* *
+* Retour : Cookie prêt à emploi. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+magic_t get_magic_cookie(int flags)
+{
+ magic_t result; /* Référence à retourner */
+#ifndef NDEBUG
+ int ret; /* Bilan de la préparation */
+#endif
+
+ result = __magic_cookie;
+ assert(result != 0);
+
+#ifndef NDEBUG
+ ret = magic_setflags(result, flags);
+ assert(ret != -1);
+#else
+ magic_setflags(result, flags);
+#endif
+
+ return result;
+
+}
diff --git a/src/analysis/scan/items/magic/cookie.h b/src/analysis/scan/items/magic/cookie.h
new file mode 100644
index 0000000..0ee2274
--- /dev/null
+++ b/src/analysis/scan/items/magic/cookie.h
@@ -0,0 +1,44 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cookie.h - prototypes pour le chargement des motifs de reconnaissance de contenus
+ *
+ * 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_ITEMS_MAGIC_COOKIE_H
+#define _ANALYSIS_SCAN_ITEMS_MAGIC_COOKIE_H
+
+
+#include <magic.h>
+#include <stdbool.h>
+
+
+
+/* Charge les motifs de reconnaissance de contenus. */
+bool init_magic_cookie(void);
+
+/* Décharge les motifs de reconnaissance de contenus. */
+void exit_magic_cookie(void);
+
+/* Fournit la référence aux mécanismes de reconnaissance. */
+magic_t get_magic_cookie(int);
+
+
+
+#endif /* _ANALYSIS_SCAN_ITEMS_MAGIC_COOKIE_H */
diff --git a/src/analysis/scan/items/magic/mime-encoding.c b/src/analysis/scan/items/magic/mime-encoding.c
new file mode 100644
index 0000000..935515d
--- /dev/null
+++ b/src/analysis/scan/items/magic/mime-encoding.c
@@ -0,0 +1,270 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * mime-encoding.c - reconnaissance de l'encodage d'un contenu
+ *
+ * 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 "mime-encoding.h"
+
+
+#include "cookie.h"
+#include "../../item-int.h"
+#include "../../exprs/literal.h"
+
+
+
+/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */
+
+
+/* Initialise la classe des reconnaissances de contenus. */
+static void g_scan_mime_encoding_function_class_init(GScanMimeEncodingFunctionClass *);
+
+/* Initialise une instance de reconnaissance de contenus. */
+static void g_scan_mime_encoding_function_init(GScanMimeEncodingFunction *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_mime_encoding_function_dispose(GScanMimeEncodingFunction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_mime_encoding_function_finalize(GScanMimeEncodingFunction *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_scan_mime_encoding_function_get_name(const GScanMimeEncodingFunction *);
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_scan_mime_encoding_function_run_call(GScanMimeEncodingFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE FONCTION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une reconnaissance d'encodages de contenus. */
+G_DEFINE_TYPE(GScanMimeEncodingFunction, g_scan_mime_encoding_function, G_TYPE_REGISTERED_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des reconnaissances de contenus. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_mime_encoding_function_class_init(GScanMimeEncodingFunctionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_mime_encoding_function_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_mime_encoding_function_finalize;
+
+ registered = G_REGISTERED_ITEM_CLASS(klass);
+
+ registered->get_name = (get_registered_item_name_fc)g_scan_mime_encoding_function_get_name;
+ registered->run_call = (run_registered_item_call_fc)g_scan_mime_encoding_function_run_call;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance à initialiser. *
+* *
+* Description : Initialise une instance de reconnaissance de contenus. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_mime_encoding_function_init(GScanMimeEncodingFunction *func)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_mime_encoding_function_dispose(GScanMimeEncodingFunction *func)
+{
+ G_OBJECT_CLASS(g_scan_mime_encoding_function_parent_class)->dispose(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_mime_encoding_function_finalize(GScanMimeEncodingFunction *func)
+{
+ G_OBJECT_CLASS(g_scan_mime_encoding_function_parent_class)->finalize(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Constitue une fonction de cernement d'encodages de contenus. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GRegisteredItem *g_scan_mime_encoding_function_new(void)
+{
+ GRegisteredItem *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_MIME_ENCODING_FUNCTION, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* *
+* Description : Indique le nom associé à une expression d'évaluation. *
+* *
+* Retour : Désignation humaine de l'expression d'évaluation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_mime_encoding_function_get_name(const GScanMimeEncodingFunction *item)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("mime_encoding");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* args = liste d'éventuels arguments fournis. *
+* count = taille de cette liste. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_mime_encoding_function_run_call(GScanMimeEncodingFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+{
+ bool result; /* Bilan à retourner */
+ magic_t cookie; /* Référence des bibliothèques */
+ GBinContent *content; /* Contenu à manipuler */
+ vmpa2t pos; /* Tête de lecture */
+ phys_t size; /* Quantité de données dispos. */
+ const bin_t *data; /* Accès à des données */
+ const char *desc; /* Description du contenu */
+ sized_string_t string; /* Description à diffuser */
+
+ result = (count == 0);
+ if (!result) goto exit;
+
+ cookie = get_magic_cookie(MAGIC_MIME_ENCODING);
+
+ content = g_scan_context_get_content(ctx);
+
+ g_binary_content_compute_start_pos(content, &pos);
+
+ size = g_binary_content_compute_size(content);
+
+ data = g_binary_content_get_raw_access(content, &pos, size);
+
+ desc = magic_buffer(cookie, data, size);
+
+ if (desc != NULL)
+ {
+ string.data = (char *)desc;
+ string.len = strlen(desc);
+ }
+ else
+ {
+ string.data = "";
+ string.len = 0;
+ }
+
+ *out = G_OBJECT(g_scan_literal_expression_new(LVT_STRING, &string));
+
+ g_object_unref(G_OBJECT(content));
+
+ exit:
+
+ return result;
+
+}
diff --git a/src/analysis/scan/items/magic/mime-encoding.h b/src/analysis/scan/items/magic/mime-encoding.h
new file mode 100644
index 0000000..9349d55
--- /dev/null
+++ b/src/analysis/scan/items/magic/mime-encoding.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * mime-encoding.h - prototypes pour la reconnaissance de l'encodage d'un contenu
+ *
+ * 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_ITEMS_MAGIC_MIME_ENCODING_H
+#define _ANALYSIS_SCAN_ITEMS_MAGIC_MIME_ENCODING_H
+
+
+#include <glib-object.h>
+
+
+#include "../../item.h"
+
+
+
+#define G_TYPE_SCAN_MIME_ENCODING_FUNCTION g_scan_mime_encoding_function_get_type()
+#define G_SCAN_MIME_ENCODING_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MIME_ENCODING_FUNCTION, GScanMimeEncodingFunction))
+#define G_IS_SCAN_MIME_ENCODING_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MIME_ENCODING_FUNCTION))
+#define G_SCAN_MIME_ENCODING_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MIME_ENCODING_FUNCTION, GScanMimeEncodingFunctionClass))
+#define G_IS_SCAN_MIME_ENCODING_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MIME_ENCODING_FUNCTION))
+#define G_SCAN_MIME_ENCODING_FUNCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MIME_ENCODING_FUNCTION, GScanMimeEncodingFunctionClass))
+
+
+/* Reconnaissance d'encodages de contenus (instance) */
+typedef GRegisteredItem GScanMimeEncodingFunction;
+
+/* Reconnaissance d'encodages de contenus (classe) */
+typedef GRegisteredItemClass GScanMimeEncodingFunctionClass;
+
+
+/* Indique le type défini pour une reconnaissance d'encodages de contenus. */
+GType g_scan_mime_encoding_function_get_type(void);
+
+/* Constitue une fonction de cernement d'encodages de contenus. */
+GRegisteredItem *g_scan_mime_encoding_function_new(void);
+
+
+
+#endif /* _ANALYSIS_SCAN_ITEMS_MAGIC_MIME_ENCODING_H */
diff --git a/src/analysis/scan/items/magic/mime-type.c b/src/analysis/scan/items/magic/mime-type.c
new file mode 100644
index 0000000..95e441d
--- /dev/null
+++ b/src/analysis/scan/items/magic/mime-type.c
@@ -0,0 +1,270 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * type.c - reconnaissance du type MIME d'un contenu
+ *
+ * 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 "mime-type.h"
+
+
+#include "cookie.h"
+#include "../../item-int.h"
+#include "../../exprs/literal.h"
+
+
+
+/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */
+
+
+/* Initialise la classe des reconnaissances de contenus. */
+static void g_scan_mime_type_function_class_init(GScanMimeTypeFunctionClass *);
+
+/* Initialise une instance de reconnaissance de contenus. */
+static void g_scan_mime_type_function_init(GScanMimeTypeFunction *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_mime_type_function_dispose(GScanMimeTypeFunction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_mime_type_function_finalize(GScanMimeTypeFunction *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_scan_mime_type_function_get_name(const GScanMimeTypeFunction *);
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_scan_mime_type_function_run_call(GScanMimeTypeFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE FONCTION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une reconnaissance de types de contenus. */
+G_DEFINE_TYPE(GScanMimeTypeFunction, g_scan_mime_type_function, G_TYPE_REGISTERED_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des reconnaissances de contenus. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_mime_type_function_class_init(GScanMimeTypeFunctionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_mime_type_function_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_mime_type_function_finalize;
+
+ registered = G_REGISTERED_ITEM_CLASS(klass);
+
+ registered->get_name = (get_registered_item_name_fc)g_scan_mime_type_function_get_name;
+ registered->run_call = (run_registered_item_call_fc)g_scan_mime_type_function_run_call;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance à initialiser. *
+* *
+* Description : Initialise une instance de reconnaissance de contenus. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_mime_type_function_init(GScanMimeTypeFunction *func)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_mime_type_function_dispose(GScanMimeTypeFunction *func)
+{
+ G_OBJECT_CLASS(g_scan_mime_type_function_parent_class)->dispose(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_mime_type_function_finalize(GScanMimeTypeFunction *func)
+{
+ G_OBJECT_CLASS(g_scan_mime_type_function_parent_class)->finalize(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Constitue une fonction d'identification de types de contenus.*
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GRegisteredItem *g_scan_mime_type_function_new(void)
+{
+ GRegisteredItem *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_MIME_TYPE_FUNCTION, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* *
+* Description : Indique le nom associé à une expression d'évaluation. *
+* *
+* Retour : Désignation humaine de l'expression d'évaluation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_mime_type_function_get_name(const GScanMimeTypeFunction *item)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("mime_type");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* args = liste d'éventuels arguments fournis. *
+* count = taille de cette liste. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_mime_type_function_run_call(GScanMimeTypeFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+{
+ bool result; /* Bilan à retourner */
+ magic_t cookie; /* Référence des bibliothèques */
+ GBinContent *content; /* Contenu à manipuler */
+ vmpa2t pos; /* Tête de lecture */
+ phys_t size; /* Quantité de données dispos. */
+ const bin_t *data; /* Accès à des données */
+ const char *desc; /* Description du contenu */
+ sized_string_t string; /* Description à diffuser */
+
+ result = (count == 0);
+ if (!result) goto exit;
+
+ cookie = get_magic_cookie(MAGIC_MIME_TYPE);
+
+ content = g_scan_context_get_content(ctx);
+
+ g_binary_content_compute_start_pos(content, &pos);
+
+ size = g_binary_content_compute_size(content);
+
+ data = g_binary_content_get_raw_access(content, &pos, size);
+
+ desc = magic_buffer(cookie, data, size);
+
+ if (desc != NULL)
+ {
+ string.data = (char *)desc;
+ string.len = strlen(desc);
+ }
+ else
+ {
+ string.data = "";
+ string.len = 0;
+ }
+
+ *out = G_OBJECT(g_scan_literal_expression_new(LVT_STRING, &string));
+
+ g_object_unref(G_OBJECT(content));
+
+ exit:
+
+ return result;
+
+}
diff --git a/src/analysis/scan/items/magic/mime-type.h b/src/analysis/scan/items/magic/mime-type.h
new file mode 100644
index 0000000..e02ce0f
--- /dev/null
+++ b/src/analysis/scan/items/magic/mime-type.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * mime-type.h - prototypes pour la reconnaissance du type MIME d'un contenu
+ *
+ * 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_ITEMS_MAGIC_MIME_TYPE_H
+#define _ANALYSIS_SCAN_ITEMS_MAGIC_MIME_TYPE_H
+
+
+#include <glib-object.h>
+
+
+#include "../../item.h"
+
+
+
+#define G_TYPE_SCAN_MIME_TYPE_FUNCTION g_scan_mime_type_function_get_type()
+#define G_SCAN_MIME_TYPE_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MIME_TYPE_FUNCTION, GScanMimeTypeFunction))
+#define G_IS_SCAN_MIME_TYPE_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MIME_TYPE_FUNCTION))
+#define G_SCAN_MIME_TYPE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MIME_TYPE_FUNCTION, GScanMimeTypeFunctionClass))
+#define G_IS_SCAN_MIME_TYPE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MIME_TYPE_FUNCTION))
+#define G_SCAN_MIME_TYPE_FUNCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MIME_TYPE_FUNCTION, GScanMimeTypeFunctionClass))
+
+
+/* Reconnaissance de types de contenus (instance) */
+typedef GRegisteredItem GScanMimeTypeFunction;
+
+/* Reconnaissance de types de contenus (classe) */
+typedef GRegisteredItemClass GScanMimeTypeFunctionClass;
+
+
+/* Indique le type défini pour une reconnaissance de types de contenus. */
+GType g_scan_mime_type_function_get_type(void);
+
+/* Constitue une fonction d'identification de types de contenus. */
+GRegisteredItem *g_scan_mime_type_function_new(void);
+
+
+
+#endif /* _ANALYSIS_SCAN_ITEMS_MAGIC_MIME_TYPE_H */
diff --git a/src/analysis/scan/items/magic/type.c b/src/analysis/scan/items/magic/type.c
new file mode 100644
index 0000000..f87c34a
--- /dev/null
+++ b/src/analysis/scan/items/magic/type.c
@@ -0,0 +1,270 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * type.c - reconnaissance du type d'un contenu
+ *
+ * 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 "type.h"
+
+
+#include "cookie.h"
+#include "../../item-int.h"
+#include "../../exprs/literal.h"
+
+
+
+/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */
+
+
+/* Initialise la classe des reconnaissances de contenus. */
+static void g_scan_magic_type_function_class_init(GScanMagicTypeFunctionClass *);
+
+/* Initialise une instance de reconnaissance de contenus. */
+static void g_scan_magic_type_function_init(GScanMagicTypeFunction *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_magic_type_function_dispose(GScanMagicTypeFunction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_magic_type_function_finalize(GScanMagicTypeFunction *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_scan_magic_type_function_get_name(const GScanMagicTypeFunction *);
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_scan_magic_type_function_run_call(GScanMagicTypeFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE FONCTION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une reconnaissance de types de contenus. */
+G_DEFINE_TYPE(GScanMagicTypeFunction, g_scan_magic_type_function, G_TYPE_REGISTERED_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des reconnaissances de contenus. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_magic_type_function_class_init(GScanMagicTypeFunctionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_magic_type_function_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_magic_type_function_finalize;
+
+ registered = G_REGISTERED_ITEM_CLASS(klass);
+
+ registered->get_name = (get_registered_item_name_fc)g_scan_magic_type_function_get_name;
+ registered->run_call = (run_registered_item_call_fc)g_scan_magic_type_function_run_call;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance à initialiser. *
+* *
+* Description : Initialise une instance de reconnaissance de contenus. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_magic_type_function_init(GScanMagicTypeFunction *func)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_magic_type_function_dispose(GScanMagicTypeFunction *func)
+{
+ G_OBJECT_CLASS(g_scan_magic_type_function_parent_class)->dispose(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_magic_type_function_finalize(GScanMagicTypeFunction *func)
+{
+ G_OBJECT_CLASS(g_scan_magic_type_function_parent_class)->finalize(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Constitue une fonction d'identification de types de contenus.*
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GRegisteredItem *g_scan_magic_type_function_new(void)
+{
+ GRegisteredItem *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_MAGIC_TYPE_FUNCTION, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* *
+* Description : Indique le nom associé à une expression d'évaluation. *
+* *
+* Retour : Désignation humaine de l'expression d'évaluation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_magic_type_function_get_name(const GScanMagicTypeFunction *item)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("type");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* args = liste d'éventuels arguments fournis. *
+* count = taille de cette liste. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_magic_type_function_run_call(GScanMagicTypeFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+{
+ bool result; /* Bilan à retourner */
+ magic_t cookie; /* Référence des bibliothèques */
+ GBinContent *content; /* Contenu à manipuler */
+ vmpa2t pos; /* Tête de lecture */
+ phys_t size; /* Quantité de données dispos. */
+ const bin_t *data; /* Accès à des données */
+ const char *desc; /* Description du contenu */
+ sized_string_t string; /* Description à diffuser */
+
+ result = (count == 0);
+ if (!result) goto exit;
+
+ cookie = get_magic_cookie(MAGIC_NONE);
+
+ content = g_scan_context_get_content(ctx);
+
+ g_binary_content_compute_start_pos(content, &pos);
+
+ size = g_binary_content_compute_size(content);
+
+ data = g_binary_content_get_raw_access(content, &pos, size);
+
+ desc = magic_buffer(cookie, data, size);
+
+ if (desc != NULL)
+ {
+ string.data = (char *)desc;
+ string.len = strlen(desc);
+ }
+ else
+ {
+ string.data = "";
+ string.len = 0;
+ }
+
+ *out = G_OBJECT(g_scan_literal_expression_new(LVT_STRING, &string));
+
+ g_object_unref(G_OBJECT(content));
+
+ exit:
+
+ return result;
+
+}
diff --git a/src/analysis/scan/items/magic/type.h b/src/analysis/scan/items/magic/type.h
new file mode 100644
index 0000000..bfad213
--- /dev/null
+++ b/src/analysis/scan/items/magic/type.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * type.h - prototypes pour la reconnaissance du type d'un contenu
+ *
+ * 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_ITEMS_MAGIC_TYPE_H
+#define _ANALYSIS_SCAN_ITEMS_MAGIC_TYPE_H
+
+
+#include <glib-object.h>
+
+
+#include "../../item.h"
+
+
+
+#define G_TYPE_SCAN_MAGIC_TYPE_FUNCTION g_scan_magic_type_function_get_type()
+#define G_SCAN_MAGIC_TYPE_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MAGIC_TYPE_FUNCTION, GScanMagicTypeFunction))
+#define G_IS_SCAN_MAGIC_TYPE_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MAGIC_TYPE_FUNCTION))
+#define G_SCAN_MAGIC_TYPE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MAGIC_TYPE_FUNCTION, GScanMagicTypeFunctionClass))
+#define G_IS_SCAN_MAGIC_TYPE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MAGIC_TYPE_FUNCTION))
+#define G_SCAN_MAGIC_TYPE_FUNCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MAGIC_TYPE_FUNCTION, GScanMagicTypeFunctionClass))
+
+
+/* Reconnaissance de types de contenus (instance) */
+typedef GRegisteredItem GScanMagicTypeFunction;
+
+/* Reconnaissance de types de contenus (classe) */
+typedef GRegisteredItemClass GScanMagicTypeFunctionClass;
+
+
+/* Indique le type défini pour une reconnaissance de types de contenus. */
+GType g_scan_magic_type_function_get_type(void);
+
+/* Constitue une fonction d'identification de types de contenus. */
+GRegisteredItem *g_scan_magic_type_function_new(void);
+
+
+
+#endif /* _ANALYSIS_SCAN_ITEMS_MAGIC_TYPE_H */
diff --git a/src/analysis/scan/items/time/Makefile.am b/src/analysis/scan/items/time/Makefile.am
new file mode 100644
index 0000000..e5330be
--- /dev/null
+++ b/src/analysis/scan/items/time/Makefile.am
@@ -0,0 +1,14 @@
+
+noinst_LTLIBRARIES = libanalysisscanitemstime.la
+
+
+libanalysisscanitemstime_la_SOURCES = \
+ make.h make.c \
+ now.h now.c
+
+libanalysisscanitemstime_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscanitemstime_la_SOURCES:%c=)
diff --git a/src/analysis/scan/items/time/make.c b/src/analysis/scan/items/time/make.c
new file mode 100644
index 0000000..477a77c
--- /dev/null
+++ b/src/analysis/scan/items/time/make.c
@@ -0,0 +1,350 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * make.c - construction de volume de secondes à partir d'une date
+ *
+ * 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 "make.h"
+
+
+#include <assert.h>
+#include <time.h>
+
+
+#include "../../item-int.h"
+#include "../../exprs/literal.h"
+
+
+
+/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */
+
+
+/* Initialise la classe des conversions de dates en secondes. */
+static void g_scan_time_make_function_class_init(GScanTimeMakeFunctionClass *);
+
+/* Initialise une instance de convertisseur de date en secondes. */
+static void g_scan_time_make_function_init(GScanTimeMakeFunction *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_time_make_function_dispose(GScanTimeMakeFunction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_time_make_function_finalize(GScanTimeMakeFunction *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_scan_time_make_function_get_name(const GScanTimeMakeFunction *);
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_scan_time_make_function_run_call(GScanTimeMakeFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE FONCTION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une conversion de date en nombre de secondes. */
+G_DEFINE_TYPE(GScanTimeMakeFunction, g_scan_time_make_function, G_TYPE_REGISTERED_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des conversions de dates en secondes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_time_make_function_class_init(GScanTimeMakeFunctionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_time_make_function_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_time_make_function_finalize;
+
+ registered = G_REGISTERED_ITEM_CLASS(klass);
+
+ registered->get_name = (get_registered_item_name_fc)g_scan_time_make_function_get_name;
+ registered->run_call = (run_registered_item_call_fc)g_scan_time_make_function_run_call;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance à initialiser. *
+* *
+* Description : Initialise une instance de convertisseur de date en secondes.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_time_make_function_init(GScanTimeMakeFunction *func)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_time_make_function_dispose(GScanTimeMakeFunction *func)
+{
+ G_OBJECT_CLASS(g_scan_time_make_function_parent_class)->dispose(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_time_make_function_finalize(GScanTimeMakeFunction *func)
+{
+ G_OBJECT_CLASS(g_scan_time_make_function_parent_class)->finalize(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Constitue une fonction de décompte du temps écoulé. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GRegisteredItem *g_scan_time_make_function_new(void)
+{
+ GRegisteredItem *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_TIME_MAKE_FUNCTION, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* *
+* Description : Indique le nom associé à une expression d'évaluation. *
+* *
+* Retour : Désignation humaine de l'expression d'évaluation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_time_make_function_get_name(const GScanTimeMakeFunction *item)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("make");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* args = liste d'éventuels arguments fournis. *
+* count = taille de cette liste. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_time_make_function_run_call(GScanTimeMakeFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+{
+ bool result; /* Bilan à retourner */
+ bool status; /* Possibilité de construction */
+ size_t i; /* Boucle de parcours */
+ LiteralValueType vtype; /* Type de valeur portée */
+ struct tm date; /* Date à mettre en place */
+ unsigned long long value; /* Valeur entière à utiliser */
+ time_t computed; /* Nombre de secondes déterminé*/
+
+ /* Validation des arguments */
+
+ result = (count == 3 || count == 6);
+ if (!result) goto exit;
+
+ status = true;
+
+ for (i = 0; i < count && status; i++)
+ {
+ status = G_IS_SCAN_LITERAL_EXPRESSION(args[i]);
+ if (!status) break;
+
+ vtype = g_scan_literal_expression_get_value_type(G_SCAN_LITERAL_EXPRESSION(args[i]));
+
+ status = (vtype == LVT_UNSIGNED_INTEGER);
+ if (!status) break;
+
+ }
+
+ if (!status) goto exit;
+
+ /* Lecture des arguments */
+
+ memset(&date, 0, sizeof(struct tm));
+
+ status = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[0]), &value);
+ assert(status);
+ if (!status) goto exit;
+
+ if (value < 1900)
+ {
+ result = false;
+ goto exit;
+ }
+
+ date.tm_year = value - 1900;
+
+ status = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[1]), &value);
+ assert(status);
+ if (!status) goto exit;
+
+ if (value > 12)
+ {
+ result = false;
+ goto exit;
+ }
+
+ date.tm_mon = value - 1;
+
+ status = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[2]), &value);
+ assert(status);
+ if (!status) goto exit;
+
+ if (value < 1 || value > 31)
+ {
+ result = false;
+ goto exit;
+ }
+
+ date.tm_mday = value;
+
+ if (count == 6)
+ {
+ status = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[3]), &value);
+ assert(status);
+ if (!status) goto exit;
+
+ if (value >= 24)
+ {
+ result = false;
+ goto exit;
+ }
+
+ date.tm_hour = value;
+
+ status = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[4]), &value);
+ assert(status);
+ if (!status) goto exit;
+
+ if (value >= 60)
+ {
+ result = false;
+ goto exit;
+ }
+
+ date.tm_min = value;
+
+ status = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[5]), &value);
+ assert(status);
+ if (!status) goto exit;
+
+ if (value >= 60)
+ {
+ result = false;
+ goto exit;
+ }
+
+ date.tm_sec = value;
+
+ }
+
+ /* Construction de la valeur finale */
+
+ computed = timegm(&date);
+
+ if (computed != (time_t)-1)
+ *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ computed }));
+
+ exit:
+
+ return result;
+
+}
diff --git a/src/analysis/scan/items/time/make.h b/src/analysis/scan/items/time/make.h
new file mode 100644
index 0000000..958a392
--- /dev/null
+++ b/src/analysis/scan/items/time/make.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * make.h - prototypes pour une construction de volume de secondes à partir d'une date
+ *
+ * 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_ITEMS_TIME_MAKE_H
+#define _ANALYSIS_SCAN_ITEMS_TIME_MAKE_H
+
+
+#include <glib-object.h>
+
+
+#include "../../item.h"
+
+
+
+#define G_TYPE_SCAN_TIME_MAKE_FUNCTION g_scan_time_make_function_get_type()
+#define G_SCAN_TIME_MAKE_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TIME_MAKE_FUNCTION, GScanTimeMakeFunction))
+#define G_IS_SCAN_TIME_MAKE_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TIME_MAKE_FUNCTION))
+#define G_SCAN_TIME_MAKE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TIME_MAKE_FUNCTION, GScanTimeMakeFunctionClass))
+#define G_IS_SCAN_TIME_MAKE_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TIME_MAKE_FUNCTION))
+#define G_SCAN_TIME_MAKE_FUNCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TIME_MAKE_FUNCTION, GScanTimeMakeFunctionClass))
+
+
+/* Convertisseur de date en nombre de secondes depuis le 01/01/1970 (instance) */
+typedef GRegisteredItem GScanTimeMakeFunction;
+
+/* Convertisseur de date en nombre de secondes depuis le 01/01/1970 (classe) */
+typedef GRegisteredItemClass GScanTimeMakeFunctionClass;
+
+
+/* Indique le type défini pour une conversion de date en nombre de secondes. */
+GType g_scan_time_make_function_get_type(void);
+
+/* Constitue une fonction de décompte du temps écoulé. */
+GRegisteredItem *g_scan_time_make_function_new(void);
+
+
+
+#endif /* _ANALYSIS_SCAN_ITEMS_TIME_MAKE_H */
diff --git a/src/analysis/scan/items/time/now.c b/src/analysis/scan/items/time/now.c
new file mode 100644
index 0000000..16c4aef
--- /dev/null
+++ b/src/analysis/scan/items/time/now.c
@@ -0,0 +1,243 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * now.c - décompte du temps écoulé depuis Epoch
+ *
+ * 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 "now.h"
+
+
+#include <time.h>
+
+
+#include "../../item-int.h"
+#include "../../exprs/literal.h"
+
+
+
+/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */
+
+
+/* Initialise la classe des décomptes de temps écoulé. */
+static void g_scan_time_now_function_class_init(GScanTimeNowFunctionClass *);
+
+/* Initialise une instance de décompte de temps écoulé. */
+static void g_scan_time_now_function_init(GScanTimeNowFunction *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_time_now_function_dispose(GScanTimeNowFunction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_time_now_function_finalize(GScanTimeNowFunction *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_scan_time_now_function_get_name(const GScanTimeNowFunction *);
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_scan_time_now_function_run_call(GScanTimeNowFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE FONCTION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un décompte de secondes écoulées depuis le 01/01/1970. */
+G_DEFINE_TYPE(GScanTimeNowFunction, g_scan_time_now_function, G_TYPE_REGISTERED_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des décomptes de temps écoulé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_time_now_function_class_init(GScanTimeNowFunctionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_time_now_function_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_time_now_function_finalize;
+
+ registered = G_REGISTERED_ITEM_CLASS(klass);
+
+ registered->get_name = (get_registered_item_name_fc)g_scan_time_now_function_get_name;
+ registered->run_call = (run_registered_item_call_fc)g_scan_time_now_function_run_call;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance à initialiser. *
+* *
+* Description : Initialise une instance de décompte de temps écoulé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_time_now_function_init(GScanTimeNowFunction *func)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_time_now_function_dispose(GScanTimeNowFunction *func)
+{
+ G_OBJECT_CLASS(g_scan_time_now_function_parent_class)->dispose(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_time_now_function_finalize(GScanTimeNowFunction *func)
+{
+ G_OBJECT_CLASS(g_scan_time_now_function_parent_class)->finalize(G_OBJECT(func));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Constitue une fonction de décompte du temps écoulé. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GRegisteredItem *g_scan_time_now_function_new(void)
+{
+ GRegisteredItem *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_TIME_NOW_FUNCTION, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* *
+* Description : Indique le nom associé à une expression d'évaluation. *
+* *
+* Retour : Désignation humaine de l'expression d'évaluation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_time_now_function_get_name(const GScanTimeNowFunction *item)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("now");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* args = liste d'éventuels arguments fournis. *
+* count = taille de cette liste. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la résolution opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_time_now_function_run_call(GScanTimeNowFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+{
+ bool result; /* Bilan à retourner */
+ time_t now; /* Date relative courante */
+
+ result = (count == 0);
+ if (!result) goto exit;
+
+ now = time(NULL);
+
+ *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ now }));
+
+ exit:
+
+ return result;
+
+}
diff --git a/src/analysis/scan/items/time/now.h b/src/analysis/scan/items/time/now.h
new file mode 100644
index 0000000..6b3faa2
--- /dev/null
+++ b/src/analysis/scan/items/time/now.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * now.h - prototypes pour le décompte du temps écoulé depuis Epoch
+ *
+ * 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_ITEMS_TIME_NOW_H
+#define _ANALYSIS_SCAN_ITEMS_TIME_NOW_H
+
+
+#include <glib-object.h>
+
+
+#include "../../item.h"
+
+
+
+#define G_TYPE_SCAN_TIME_NOW_FUNCTION g_scan_time_now_function_get_type()
+#define G_SCAN_TIME_NOW_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TIME_NOW_FUNCTION, GScanTimeNowFunction))
+#define G_IS_SCAN_TIME_NOW_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TIME_NOW_FUNCTION))
+#define G_SCAN_TIME_NOW_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TIME_NOW_FUNCTION, GScanTimeNowFunctionClass))
+#define G_IS_SCAN_TIME_NOW_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TIME_NOW_FUNCTION))
+#define G_SCAN_TIME_NOW_FUNCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TIME_NOW_FUNCTION, GScanTimeNowFunctionClass))
+
+
+/* Décompte du nombre de seccondes écoulées depuis le 01/01/1970 (instance) */
+typedef GRegisteredItem GScanTimeNowFunction;
+
+/* Décompte du nombre de seccondes écoulées depuis le 01/01/1970 (classe) */
+typedef GRegisteredItemClass GScanTimeNowFunctionClass;
+
+
+/* Indique le type défini pour un décompte de secondes écoulées depuis le 01/01/1970. */
+GType g_scan_time_now_function_get_type(void);
+
+/* Constitue une fonction de décompte du temps écoulé. */
+GRegisteredItem *g_scan_time_now_function_new(void);
+
+
+
+#endif /* _ANALYSIS_SCAN_ITEMS_TIME_NOW_H */
diff --git a/src/analysis/scan/items/uint-int.h b/src/analysis/scan/items/uint-int.h
index 1fa83c5..972d7a0 100644
--- a/src/analysis/scan/items/uint-int.h
+++ b/src/analysis/scan/items/uint-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* uint-int.h - prototypes internes pour la lecture d'un mot à partir de données binaires
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -33,7 +33,7 @@
/* Fonction conduisant à la lecture d'un mot (instance) */
-struct _GUintFunction
+struct _GScanUintFunction
{
GRegisteredItem parent; /* A laisser en premier */
@@ -43,7 +43,7 @@ struct _GUintFunction
};
/* Fonction conduisant à la lecture d'un mot (classe) */
-struct _GUintFunctionClass
+struct _GScanUintFunctionClass
{
GRegisteredItemClass parent; /* A laisser en premier */
@@ -51,7 +51,7 @@ struct _GUintFunctionClass
/* Met en place un nouvelle fonction de lecture d'entiers. */
-bool g_uint_function_create(GUintFunction *, MemoryDataSize);
+bool g_scan_uint_function_create(GScanUintFunction *, MemoryDataSize, SourceEndian);
diff --git a/src/analysis/scan/items/uint.c b/src/analysis/scan/items/uint.c
index 4fea494..66c7fa9 100644
--- a/src/analysis/scan/items/uint.c
+++ b/src/analysis/scan/items/uint.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* uint.c - lecture d'un mot à partir de données binaires
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -29,6 +29,7 @@
#include "uint-int.h"
#include "../exprs/literal.h"
+#include "../../../common/extstr.h"
@@ -36,16 +37,16 @@
/* Initialise la classe des lectures de valeurs entières. */
-static void g_uint_function_class_init(GUintFunctionClass *);
+static void g_scan_uint_function_class_init(GScanUintFunctionClass *);
/* Initialise une instance de lecture de valeur entière. */
-static void g_uint_function_init(GUintFunction *);
+static void g_scan_uint_function_init(GScanUintFunction *);
/* Supprime toutes les références externes. */
-static void g_uint_function_dispose(GUintFunction *);
+static void g_scan_uint_function_dispose(GScanUintFunction *);
/* Procède à la libération totale de la mémoire. */
-static void g_uint_function_finalize(GUintFunction *);
+static void g_scan_uint_function_finalize(GScanUintFunction *);
@@ -53,10 +54,10 @@ static void g_uint_function_finalize(GUintFunction *);
/* Indique le nom associé à une expression d'évaluation. */
-static char *g_uint_function_get_name(const GUintFunction *);
+static char *g_scan_uint_function_get_name(const GScanUintFunction *);
/* Réduit une expression à une forme plus simple. */
-static bool g_uint_function_run_call(GUintFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+static bool g_scan_uint_function_run_call(GScanUintFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
@@ -66,7 +67,7 @@ static bool g_uint_function_run_call(GUintFunction *, GScanExpression **, size_t
/* Indique le type défini pour une lecture de mot à partir de données binaires. */
-G_DEFINE_TYPE(GUintFunction, g_uint_function, G_TYPE_REGISTERED_ITEM);
+G_DEFINE_TYPE(GScanUintFunction, g_scan_uint_function, G_TYPE_REGISTERED_ITEM);
/******************************************************************************
@@ -81,20 +82,20 @@ G_DEFINE_TYPE(GUintFunction, g_uint_function, G_TYPE_REGISTERED_ITEM);
* *
******************************************************************************/
-static void g_uint_function_class_init(GUintFunctionClass *klass)
+static void g_scan_uint_function_class_init(GScanUintFunctionClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GRegisteredItemClass *registered; /* Version de classe parente */
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_uint_function_dispose;
- object->finalize = (GObjectFinalizeFunc)g_uint_function_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_uint_function_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_uint_function_finalize;
registered = G_REGISTERED_ITEM_CLASS(klass);
- registered->get_name = (get_registered_item_name_fc)g_uint_function_get_name;
- registered->run_call = (run_registered_item_call_fc)g_uint_function_run_call;
+ registered->get_name = (get_registered_item_name_fc)g_scan_uint_function_get_name;
+ registered->run_call = (run_registered_item_call_fc)g_scan_uint_function_run_call;
}
@@ -111,7 +112,7 @@ static void g_uint_function_class_init(GUintFunctionClass *klass)
* *
******************************************************************************/
-static void g_uint_function_init(GUintFunction *func)
+static void g_scan_uint_function_init(GScanUintFunction *func)
{
func->size = MDS_UNDEFINED;
func->endian = SRE_LITTLE;
@@ -131,9 +132,9 @@ static void g_uint_function_init(GUintFunction *func)
* *
******************************************************************************/
-static void g_uint_function_dispose(GUintFunction *func)
+static void g_scan_uint_function_dispose(GScanUintFunction *func)
{
- G_OBJECT_CLASS(g_uint_function_parent_class)->dispose(G_OBJECT(func));
+ G_OBJECT_CLASS(g_scan_uint_function_parent_class)->dispose(G_OBJECT(func));
}
@@ -150,9 +151,9 @@ static void g_uint_function_dispose(GUintFunction *func)
* *
******************************************************************************/
-static void g_uint_function_finalize(GUintFunction *func)
+static void g_scan_uint_function_finalize(GScanUintFunction *func)
{
- G_OBJECT_CLASS(g_uint_function_parent_class)->finalize(G_OBJECT(func));
+ G_OBJECT_CLASS(g_scan_uint_function_parent_class)->finalize(G_OBJECT(func));
}
@@ -169,13 +170,13 @@ static void g_uint_function_finalize(GUintFunction *func)
* *
******************************************************************************/
-GUintFunction *g_uint_function_new(MemoryDataSize size)
+GRegisteredItem *g_scan_uint_function_new(MemoryDataSize size, SourceEndian endian)
{
- GUintFunction *result; /* Structure à retourner */
+ GRegisteredItem *result; /* Structure à retourner */
- result = g_object_new(G_TYPE_UINT_FUNCTION, NULL);
+ result = g_object_new(G_TYPE_SCAN_UINT_FUNCTION, NULL);
- if (!g_uint_function_create(result, size))
+ if (!g_scan_uint_function_create(G_SCAN_UINT_FUNCTION(result), size, endian))
g_clear_object(&result);
return result;
@@ -196,13 +197,14 @@ GUintFunction *g_uint_function_new(MemoryDataSize size)
* *
******************************************************************************/
-bool g_uint_function_create(GUintFunction *func, MemoryDataSize size)
+bool g_scan_uint_function_create(GScanUintFunction *func, MemoryDataSize size, SourceEndian endian)
{
bool result; /* Bilan à retourner */
result = true;
func->size = size;
+ func->endian = endian;
return result;
@@ -227,26 +229,26 @@ bool g_uint_function_create(GUintFunction *func, MemoryDataSize size)
* *
******************************************************************************/
-static char *g_uint_function_get_name(const GUintFunction *item)
+static char *g_scan_uint_function_get_name(const GScanUintFunction *item)
{
char *result; /* Désignation à retourner */
- switch (item->size)
+ switch (item->size & ~MDS_SIGN)
{
case MDS_8_BITS_UNSIGNED:
- result = strdup("uint8");
+ result = strdup("int8");
break;
case MDS_16_BITS_UNSIGNED:
- result = strdup("uint16");
+ result = strdup("int16");
break;
case MDS_32_BITS_UNSIGNED:
- result = strdup("uint32");
+ result = strdup("int32");
break;
case MDS_64_BITS_UNSIGNED:
- result = strdup("uint64");
+ result = strdup("int64");
break;
default:
@@ -256,6 +258,16 @@ static char *g_uint_function_get_name(const GUintFunction *item)
}
+ if (result)
+ {
+ if (!MDS_IS_SIGNED(item->size))
+ result = strprep(result, "u");
+
+ if (item->endian == SRE_BIG)
+ result = stradd(result, "be");
+
+ }
+
return result;
}
@@ -278,21 +290,25 @@ static char *g_uint_function_get_name(const GUintFunction *item)
* *
******************************************************************************/
-static bool g_uint_function_run_call(GUintFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
+static bool g_scan_uint_function_run_call(GScanUintFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out)
{
bool result; /* Bilan à retourner */
unsigned long long offset; /* Position du mot ciblé */
GBinContent *content; /* Contenu à manipuler */
vmpa2t pos; /* Tête de lecture */
- uint8_t val_8; /* Valeur entière sur 8 bits */
- uint16_t val_16; /* Valeur entière sur 16 bits */
- uint32_t val_32; /* Valeur entière sur 32 bits */
- uint64_t val_64; /* Valeur entière sur 64 bits */
-
- result = (count == 1 && G_IS_LITERAL_EXPRESSION(args[0]));
+ uint8_t val_s8; /* Valeur entière sur 8 bits */
+ uint8_t val_u8; /* Valeur entière sur 8 bits */
+ uint16_t val_s16; /* Valeur entière sur 16 bits */
+ uint16_t val_u16; /* Valeur entière sur 16 bits */
+ uint32_t val_s32; /* Valeur entière sur 32 bits */
+ uint32_t val_u32; /* Valeur entière sur 32 bits */
+ uint64_t val_s64; /* Valeur entière sur 64 bits */
+ uint64_t val_u64; /* Valeur entière sur 64 bits */
+
+ result = (count == 1 && G_IS_SCAN_LITERAL_EXPRESSION(args[0]));
if (!result) goto exit;
- result = g_literal_expression_get_integer_value(G_LITERAL_EXPRESSION(args[0]), &offset);
+ result = g_scan_literal_expression_get_unsigned_integer_value(G_SCAN_LITERAL_EXPRESSION(args[0]), &offset);
if (!result) goto exit;
content = g_scan_context_get_content(ctx);
@@ -302,29 +318,60 @@ static bool g_uint_function_run_call(GUintFunction *item, GScanExpression **args
switch (item->size)
{
+ case MDS_8_BITS_SIGNED:
+ result = g_binary_content_read_s8(content, &pos, &val_s8);
+ if (result)
+ *out = G_OBJECT(g_scan_literal_expression_new(LVT_SIGNED_INTEGER,
+ (long long []){ val_s8 }));
+ break;
+
case MDS_8_BITS_UNSIGNED:
- result = g_binary_content_read_u8(content, &pos, &val_8);
+ result = g_binary_content_read_u8(content, &pos, &val_u8);
if (result)
- *out = G_OBJECT(g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_8 }));
+ *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER,
+ (unsigned long long []){ val_u8 }));
+ break;
+
+ case MDS_16_BITS_SIGNED:
+ result = g_binary_content_read_s16(content, &pos, item->endian, &val_s16);
+ if (result)
+ *out = G_OBJECT(g_scan_literal_expression_new(LVT_SIGNED_INTEGER,
+ (long long []){ val_s16 }));
break;
case MDS_16_BITS_UNSIGNED:
- result = g_binary_content_read_u16(content, &pos, item->endian, &val_16);
+ result = g_binary_content_read_u16(content, &pos, item->endian, &val_u16);
if (result)
- *out = G_OBJECT(g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_16 }));
+ *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER,
+ (unsigned long long []){ val_u16 }));
+ break;
+
+ case MDS_32_BITS_SIGNED:
+ result = g_binary_content_read_s32(content, &pos, item->endian, &val_s32);
+ if (result)
+ *out = G_OBJECT(g_scan_literal_expression_new(LVT_SIGNED_INTEGER,
+ (long long []){ val_s32 }));
break;
case MDS_32_BITS_UNSIGNED:
- result = g_binary_content_read_u32(content, &pos, item->endian, &val_32);
+ result = g_binary_content_read_u32(content, &pos, item->endian, &val_u32);
if (result)
- *out = G_OBJECT(g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_32 }));
+ *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER,
+ (unsigned long long []){ val_u32 }));
break;
+ case MDS_64_BITS_SIGNED:
+ result = g_binary_content_read_s64(content, &pos, item->endian, &val_s64);
+ if (result)
+ *out = G_OBJECT(g_scan_literal_expression_new(LVT_SIGNED_INTEGER,
+ (long long []){ val_s64 }));
+ break;
case MDS_64_BITS_UNSIGNED:
- result = g_binary_content_read_u64(content, &pos, item->endian, &val_64);
+ result = g_binary_content_read_u64(content, &pos, item->endian, &val_u64);
if (result)
- *out = G_OBJECT(g_literal_expression_new(EVT_INTEGER, (unsigned long long []){ val_64 }));
+ *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER,
+ (unsigned long long []){ val_u64 }));
break;
default:
diff --git a/src/analysis/scan/items/uint.h b/src/analysis/scan/items/uint.h
index 60f2975..abc2231 100644
--- a/src/analysis/scan/items/uint.h
+++ b/src/analysis/scan/items/uint.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* uint.h - prototypes pour la lecture d'un mot à partir de données binaires
*
- * Copyright (C) 2022 Cyrille Bagard
+ * Copyright (C) 2023 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -28,30 +28,31 @@
#include <glib-object.h>
+#include "../item.h"
#include "../../../arch/archbase.h"
-#define G_TYPE_UINT_FUNCTION g_uint_function_get_type()
-#define G_UINT_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_UINT_FUNCTION, GUintFunction))
-#define G_IS_UINT_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_UINT_FUNCTION))
-#define G_UINT_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_UINT_FUNCTION, GUintFunctionClass))
-#define G_IS_UINT_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_UINT_FUNCTION))
-#define G_UINT_FUNCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_UINT_FUNCTION, GUintFunctionClass))
+#define G_TYPE_SCAN_UINT_FUNCTION g_scan_uint_function_get_type()
+#define G_SCAN_UINT_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_UINT_FUNCTION, GScanUintFunction))
+#define G_IS_SCAN_UINT_FUNCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_UINT_FUNCTION))
+#define G_SCAN_UINT_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_UINT_FUNCTION, GScanUintFunctionClass))
+#define G_IS_SCAN_UINT_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_UINT_FUNCTION))
+#define G_SCAN_UINT_FUNCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_UINT_FUNCTION, GScanUintFunctionClass))
/* Fonction conduisant à la lecture d'un mot (instance) */
-typedef struct _GUintFunction GUintFunction;
+typedef struct _GScanUintFunction GScanUintFunction;
/* Fonction conduisant à la lecture d'un mot (classe) */
-typedef struct _GUintFunctionClass GUintFunctionClass;
+typedef struct _GScanUintFunctionClass GScanUintFunctionClass;
/* Indique le type défini pour une lecture de mot à partir de données binaires. */
-GType g_uint_function_get_type(void);
+GType g_scan_uint_function_get_type(void);
/* Constitue une fonction de lecture de valeur entière. */
-GUintFunction *g_uint_function_new(MemoryDataSize);
+GRegisteredItem *g_scan_uint_function_new(MemoryDataSize, SourceEndian);
diff --git a/src/analysis/scan/rule-int.h b/src/analysis/scan/rule-int.h
index b43c20b..cc10b08 100644
--- a/src/analysis/scan/rule-int.h
+++ b/src/analysis/scan/rule-int.h
@@ -38,6 +38,7 @@ struct _GScanRule
GObject parent; /* A laisser en premier */
char *name; /* Désignation de la règle */
+ fnv64_t name_hash; /* Empreinte de la désignation */
GSearchPattern **data_locals; /* Variables de données */
size_t data_allocated; /* Taille allouée du tableau */
diff --git a/src/analysis/scan/rule.c b/src/analysis/scan/rule.c
index bf37585..6ca97ab 100644
--- a/src/analysis/scan/rule.c
+++ b/src/analysis/scan/rule.c
@@ -91,6 +91,7 @@ static void g_scan_rule_class_init(GScanRuleClass *klass)
static void g_scan_rule_init(GScanRule *rule)
{
rule->name = NULL;
+ rule->name_hash = 0;
rule->data_locals = NULL;
rule->data_allocated = 0;
@@ -168,6 +169,33 @@ GScanRule *g_scan_rule_new(const char *name)
result = g_object_new(G_TYPE_SCAN_RULE, NULL);
result->name = strdup(name);
+ result->name_hash = fnv_64a_hash(name);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rule = règle de détection à compléter. *
+* hash = empreinte précalculée associée au nom. [OUT] *
+* *
+* Description : Indique le nom associé à une règle de détection. *
+* *
+* Retour : Désignation humaine associée à la règle. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *g_scan_rule_get_name(const GScanRule *rule, fnv64_t *hash)
+{
+ const char *result; /* Désignation à retourner */
+
+ result = rule->name;
+
+ *hash = rule->name_hash;
return result;
diff --git a/src/analysis/scan/rule.h b/src/analysis/scan/rule.h
index e240da9..12a435c 100644
--- a/src/analysis/scan/rule.h
+++ b/src/analysis/scan/rule.h
@@ -33,6 +33,7 @@
#include "pattern.h"
#include "expr.h"
#include "patterns/backend.h"
+#include "../../common/fnv1a.h"
@@ -57,6 +58,9 @@ GType g_scan_rule_get_type(void);
/* Crée une règle de détection statique à l'aide de motifs. */
GScanRule *g_scan_rule_new(const char *);
+/* Indique le nom associé à une règle de détection. */
+const char *g_scan_rule_get_name(const GScanRule *, fnv64_t *);
+
/* Intègre une nouvelle variable locale à une règle. */
void g_scan_rule_add_local_variable(GScanRule *, GSearchPattern *);
diff --git a/src/analysis/scan/scanner-int.h b/src/analysis/scan/scanner-int.h
index 54b4f62..4fcda87 100644
--- a/src/analysis/scan/scanner-int.h
+++ b/src/analysis/scan/scanner-int.h
@@ -37,6 +37,8 @@ struct _GContentScanner
{
GObject parent; /* A laisser en premier */
+ char *filename; /* Eventuel fichier d'origine */
+
GScanRule **rules; /* Règles de détection */
size_t rule_count; /* Nombre de ces règles */
diff --git a/src/analysis/scan/scanner.c b/src/analysis/scan/scanner.c
index d52c0fc..ce8d677 100644
--- a/src/analysis/scan/scanner.c
+++ b/src/analysis/scan/scanner.c
@@ -25,11 +25,15 @@
#include <assert.h>
+#include <libgen.h>
+#include <malloc.h>
#include "decl.h"
#include "scanner-int.h"
#include "../contents/file.h"
+#include "../../common/extstr.h"
+#include "../../core/logs.h"
@@ -45,6 +49,9 @@ static void g_content_scanner_dispose(GContentScanner *);
/* Procède à la libération totale de la mémoire. */
static void g_content_scanner_finalize(GContentScanner *);
+/* Intègre une nouvelle règle de détection. */
+static bool _g_content_scanner_add_rule(GContentScanner *, GScanRule *);
+
/* Indique le type défini pour une recherche dans du binaire. */
@@ -89,6 +96,8 @@ static void g_content_scanner_class_init(GContentScannerClass *klass)
static void g_content_scanner_init(GContentScanner *scanner)
{
+ scanner->filename = NULL;
+
scanner->rules = NULL;
scanner->rule_count = 0;
@@ -137,6 +146,9 @@ static void g_content_scanner_dispose(GContentScanner *scanner)
static void g_content_scanner_finalize(GContentScanner *scanner)
{
+ if (scanner->filename != NULL)
+ free(scanner->filename);
+
if (scanner->rules != NULL)
free(scanner->rules);
@@ -250,6 +262,8 @@ bool g_content_scanner_create_from_file(GContentScanner *scanner, const char *fi
content = g_file_content_new(filename);
if (content == NULL) goto no_content;
+ scanner->filename = strdup(filename);
+
size = g_binary_content_compute_size(content);
g_binary_content_compute_start_pos(content, &start);
@@ -268,25 +282,187 @@ bool g_content_scanner_create_from_file(GContentScanner *scanner, const char *fi
/******************************************************************************
* *
+* Paramètres : scanner = scanner de contenus à consulter. *
+* *
+* Description : Indique le chemin d'un éventuel fichier de source. *
+* *
+* Retour : Chemin d'un éventuel fichier de définitions ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *g_content_scanner_get_filename(const GContentScanner *scanner)
+{
+ const char *result; /* Chemin à retourner */
+
+ result = scanner->filename;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : scanner = gestionnaire de recherche à compléter. *
+* path = chemin vers une définition de règles à intégrer. *
+* *
+* Description : Inclut les définitions d'un fichier de règles externe. *
+* *
+* Retour : Bilan de l'inclusion à retourner. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_content_scanner_include_resource(GContentScanner *scanner, const char *path)
+{
+ bool result; /* Bilan à retourner */
+ GContentScanner *included; /* Définition à inclure */
+ char *tmp; /* Copie de travail */
+ char *filename; /* Chemin d'accès reconstruit */
+ size_t i; /* Boucle de parcours */
+ const char *inc_name; /* Nom de la nouvelle règle */
+
+ /* Cas le plus simple : un chemin absolu */
+ if (path[0] == '/')
+ included = g_content_scanner_new_from_file(path);
+
+ /* Chemin relatif à l'emplacement de la définition courante ? */
+ else if (scanner->filename != NULL)
+ {
+ tmp = strdup(scanner->filename);
+
+ filename = strdup(dirname(tmp));
+ filename = stradd(filename, G_DIR_SEPARATOR_S);
+ filename = stradd(filename, path);
+
+ included = g_content_scanner_new_from_file(filename);
+
+ free(filename);
+ free(tmp);
+
+ }
+
+ else
+ included = NULL;
+
+ /* Inclusion des règles chargées */
+
+ result = (included != NULL);
+
+ if (result)
+ {
+ for (i = 0; i < included->rule_count && result; i++)
+ {
+ result = _g_content_scanner_add_rule(scanner, included->rules[i]);
+
+ if (!result)
+ {
+ inc_name = g_scan_rule_get_name(included->rules[i], (fnv64_t []) { 0 });
+
+ log_variadic_message(LMT_ERROR, "Can not import from '%s': rule '%s' already exists!",
+ path, inc_name);
+
+ }
+
+ }
+
+ g_object_unref(G_OBJECT(included));
+
+ }
+
+ return result;
+
+
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : scanner = gestionnaire de recherche à compléter. *
* rule = règle de détection à intégrer. *
* *
* Description : Intègre une nouvelle règle de détection. *
* *
-* Retour : - *
+* Retour : Bilan de l'ajout à retourner. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_content_scanner_add_rule(GContentScanner *scanner, GScanRule *rule)
+static bool _g_content_scanner_add_rule(GContentScanner *scanner, GScanRule *rule)
{
+ bool result; /* Bilan à retourner */
+ const char *inc_name; /* Nom de la nouvelle règle */
+ fnv64_t inc_hash; /* Empreinte de ce nom */
+ size_t i; /* Boucle de parcours */
+ const char *cur_name; /* Nom d'une règle en place */
+ fnv64_t cur_hash; /* Empreinte de ce nom */
+
+ result = false;
+
+ inc_name = g_scan_rule_get_name(rule, &inc_hash);
+
+ for (i = 0; i < scanner->rule_count; i++)
+ {
+ cur_name = g_scan_rule_get_name(scanner->rules[i], &cur_hash);
+
+ if (inc_hash != cur_hash)
+ continue;
+
+ if (strcmp(inc_name, cur_name) == 0)
+ goto exit_add;
+
+ }
+
+ result = true;
+
scanner->rules = realloc(scanner->rules, ++scanner->rule_count * sizeof(GScanRule *));
scanner->rules[scanner->rule_count - 1] = rule;
g_object_ref(G_OBJECT(rule));
+ exit_add:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : scanner = gestionnaire de recherche à compléter. *
+* rule = règle de détection à intégrer. *
+* *
+* Description : Intègre une nouvelle règle de détection. *
+* *
+* Retour : Bilan de l'ajout à retourner. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_content_scanner_add_rule(GContentScanner *scanner, GScanRule *rule)
+{
+ bool result; /* Bilan à retourner */
+ const char *inc_name; /* Nom de la nouvelle règle */
+
+ result = _g_content_scanner_add_rule(scanner, rule);
+
+ if (!result)
+ {
+ inc_name = g_scan_rule_get_name(rule, (fnv64_t []) { 0 });
+
+ log_variadic_message(LMT_ERROR, "Can not add rule: '%s' already exists!", inc_name);
+
+ }
+
+ return result;
+
}
diff --git a/src/analysis/scan/scanner.h b/src/analysis/scan/scanner.h
index 8a3919a..f838344 100644
--- a/src/analysis/scan/scanner.h
+++ b/src/analysis/scan/scanner.h
@@ -59,19 +59,18 @@ GContentScanner *g_content_scanner_new_from_text(const char *);
/* Prépare une recherche de motifs dans du contenu binaire. */
GContentScanner *g_content_scanner_new_from_file(const char *);
+/* Indique le chemin d'un éventuel fichier de source. */
+const char *g_content_scanner_get_filename(const GContentScanner *);
+
+/* Inclut les définitions d'un fichier de règles externe. */
+bool g_content_scanner_include_resource(GContentScanner *, const char *);
+
/* Intègre une nouvelle règle de détection. */
-void g_content_scanner_add_rule(GContentScanner *, GScanRule *);
+bool g_content_scanner_add_rule(GContentScanner *, GScanRule *);
/* Définit l'expression d'une correspondance recherchée. */
GScanContext *g_content_scanner_analyze(GContentScanner *, GScanOptions *, GBinContent *);
-
-
-/* Lance une analyse d'un élément, fichier ou répertoire. */
-//void g_content_scanner_analyze(GContentScanner *, const char *);
-
-
-
#endif /* _ANALYSIS_SCAN_SCANNER_H */
diff --git a/src/analysis/scan/tokens.l b/src/analysis/scan/tokens.l
index b541786..f3dbc79 100644
--- a/src/analysis/scan/tokens.l
+++ b/src/analysis/scan/tokens.l
@@ -82,6 +82,7 @@
%option yylineno
%option never-interactive
+%x include_path
%x rule_intro
%x raw_block
@@ -105,6 +106,14 @@
+"include" { PUSH_STATE(include_path); return INCLUDE; }
+
+<include_path>"\"" {
+ POP_STATE;
+ *used = 0;
+ PUSH_STATE(strlit);
+ }
+
"rule" { PUSH_STATE(rule_intro); return RAW_RULE; }
<rule_intro>[A-Za-z0-9_]+ {
@@ -116,8 +125,8 @@
<rule_intro>[ \t]* { }
<rule_intro>"{" { POP_STATE; PUSH_STATE(raw_block); return BRACE_IN; }
-<raw_block>"strings" { PUSH_STATE(strings); PUSH_STATE(wait_for_colon); return STRINGS; }
-<raw_block,strings>"condition" { PUSH_STATE(condition); PUSH_STATE(wait_for_colon); return CONDITION; }
+<raw_block>"strings" { POP_STATE; PUSH_STATE(strings); PUSH_STATE(wait_for_colon); return STRINGS; }
+<raw_block,strings>"condition" { POP_STATE; PUSH_STATE(condition); PUSH_STATE(wait_for_colon); return CONDITION; }
@@ -127,8 +136,11 @@
<condition>"true" { return TRUE_; }
<condition>"false" { return FALSE_; }
-<condition>(0|[1-9][0-9]*) { yylval->integer = strtoull(yytext, NULL, 10); return INTEGER; }
-<condition>0x[0-9a-f]+ { yylval->integer = strtoull(yytext, NULL, 16); return INTEGER; }
+<condition>-(0|[1-9][0-9]*) { yylval->signed_integer = strtoll(yytext, NULL, 10); return SIGNED_INTEGER; }
+<condition>-0x[0-9a-f]+ { yylval->signed_integer = strtoll(yytext, NULL, 16); return SIGNED_INTEGER; }
+
+<condition>(0|[1-9][0-9]*) { yylval->unsigned_integer = strtoull(yytext, NULL, 10); return UNSIGNED_INTEGER; }
+<condition>0x[0-9a-f]+ { yylval->unsigned_integer = strtoull(yytext, NULL, 16); return UNSIGNED_INTEGER; }
<condition>[kK][bB] { return KB; }
<condition>[mM][bB] { return MB; }
@@ -141,8 +153,6 @@
<strlit>"\"" {
POP_STATE;
- EXTEND_BUFFER_IF_NEEDED(1);
- (*buf)[(*used)++] = '\0';
yylval->sized_cstring.data = *buf;
yylval->sized_cstring.len = *used;
return STRING;
@@ -195,7 +205,7 @@
<condition>"+" { return PLUS; }
<condition>"-" { return MINUS; }
<condition>"*" { return MUL; }
-<condition>"\\" { return DIV; }
+<condition>"/" { return DIV; }
<condition>"%" { return MOD; }
<condition>"(" { return PAREN_O; }
@@ -208,6 +218,7 @@
<condition>"all" { return ALL; }
<condition>"of" { return OF; }
<condition>"them" { return THEM; }
+<condition>"in" { return IN; }
<strings,condition>$[A-Za-z0-9_]* {
@@ -215,6 +226,21 @@
yylval->sized_cstring.len = yyleng - 1;
return IDENTIFIER;
}
+
+<condition>$[A-Za-z_][A-Za-z0-9_]* {
+ yylval->sized_cstring.data = yytext + 1;
+ yylval->sized_cstring.len = yyleng - 1;
+ return BYTES_ID;
+ }
+
+<condition>#[A-Za-z_][A-Za-z0-9_]* {
+ yylval->sized_cstring.data = yytext + 1;
+ yylval->sized_cstring.len = yyleng - 1;
+ return BYTES_ID_COUNTER;
+ }
+
+
+
<condition>[A-Za-z_][A-Za-z0-9_]* {
yylval->sized_cstring.data = yytext;
yylval->sized_cstring.len = yyleng;
diff --git a/src/common/szstr.h b/src/common/szstr.h
index 54beb9a..d73e489 100644
--- a/src/common/szstr.h
+++ b/src/common/szstr.h
@@ -29,6 +29,9 @@
#include <sys/types.h>
+#include "sort.h"
+
+
/* Structure associant une chaîne et sa taille */
typedef struct _sized_string_t
@@ -66,9 +69,28 @@ typedef struct _sized_string_t
} \
} \
while (0)
-
-#define szstrcmp(ss, rs) \
- strncmp((ss)->data, (rs)/*->data*/, (ss)->len)
+
+#define szstrcmp(s1, s2) \
+ ({ \
+ int __ret; \
+ size_t __n; \
+ __n = (s1)->len < (s2)->len ? (s1)->len : (s2)->len; \
+ __ret = strncmp((s1)->data, (s2)->data, __n); \
+ if (__ret == 0) \
+ __ret = sort_unsigned_long_long((s1)->len, (s2)->len); \
+ __ret; \
+ })
+
+#define szmemcmp(s1, s2) \
+ ({ \
+ int __ret; \
+ size_t __n; \
+ __n = (s1)->len < (s2)->len ? (s1)->len : (s2)->len; \
+ __ret = memcmp((s1)->data, (s2)->data, __n); \
+ if (__ret == 0) \
+ __ret = sort_unsigned_long_long((s1)->len, (s2)->len); \
+ __ret; \
+ })
diff --git a/src/core/core.c b/src/core/core.c
index 8d4daa7..26469ff 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -41,6 +41,9 @@
#include "processors.h"
#include "queue.h"
#include "../analysis/scan/core.h"
+#ifdef HAVE_MAGIC_SUPPORT
+# include "../analysis/scan/items/magic/cookie.h"
+#endif
#include "../common/io.h"
#include "../common/xdg.h"
#include "../glibext/linesegment.h"
@@ -102,6 +105,10 @@ bool load_all_core_components(bool cs)
explorer = g_content_explorer_new();
set_current_content_explorer(explorer);
+#ifdef HAVE_MAGIC_SUPPORT
+ if (result) result = init_magic_cookie();
+#endif
+
resolver = g_content_resolver_new();
set_current_content_resolver(resolver);
@@ -152,6 +159,10 @@ void unload_all_core_components(bool cs)
set_rost_root_namespace(NULL);
+#ifdef HAVE_MAGIC_SUPPORT
+ exit_magic_cookie();
+#endif
+
set_current_content_resolver(NULL);
set_current_content_explorer(NULL);
diff --git a/src/glibext/comparison-int.h b/src/glibext/comparison-int.h
index efb289a..446f25d 100644
--- a/src/glibext/comparison-int.h
+++ b/src/glibext/comparison-int.h
@@ -48,7 +48,10 @@ typedef GComparableItemIface GComparableItemInterface;
/* Réalise une comparaison riche entre valeurs entière. */
-bool compare_rich_integer_values(unsigned long long, unsigned long long, RichCmpOperation);
+bool compare_rich_integer_values_signed(long long, long long, RichCmpOperation);
+
+/* Réalise une comparaison riche entre valeurs entière. */
+bool compare_rich_integer_values_unsigned(unsigned long long, unsigned long long, RichCmpOperation);
diff --git a/src/glibext/comparison.c b/src/glibext/comparison.c
index 463f354..8ce6941 100644
--- a/src/glibext/comparison.c
+++ b/src/glibext/comparison.c
@@ -101,7 +101,63 @@ bool g_comparable_item_compare_rich(const GComparableItem *item, const GComparab
* *
******************************************************************************/
-bool compare_rich_integer_values(unsigned long long a, unsigned long long b, RichCmpOperation op)
+bool compare_rich_integer_values_signed(long long a, long long b, RichCmpOperation op)
+{
+ bool result; /* Bilan à retourner */
+
+ switch (op)
+ {
+ case RCO_LT:
+ result = (a < b);
+ break;
+
+ case RCO_LE:
+ result = (a <= b);
+ break;
+
+ case RCO_EQ:
+ result = (a == b);
+ break;
+
+ case RCO_NE:
+ result = (a != b);
+ break;
+
+ case RCO_GT:
+ result = (a > b);
+ break;
+
+ case RCO_GE:
+ result = (a >= b);
+ break;
+
+ default:
+ assert(false);
+ result = false;
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier élément à consulter pour une comparaison. *
+* b = second objet à consulter pour une comparaison. *
+* op = opération de comparaison à réaliser. *
+* *
+* Description : Réalise une comparaison riche entre valeurs entière. *
+* *
+* Retour : Bilan des opérations de comparaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool compare_rich_integer_values_unsigned(unsigned long long a, unsigned long long b, RichCmpOperation op)
{
bool result; /* Bilan à retourner */
diff --git a/src/rost.c b/src/rost.c
index 37ca098..40fe587 100644
--- a/src/rost.c
+++ b/src/rost.c
@@ -275,31 +275,33 @@ int main(int argc, char **argv)
set_log_verbosity(verbosity);
- /*
- if (!load_all_core_components(false))
+ if (!load_all_core_components(true))
goto done;
- */
/* Traitement des recherches */
scanner = g_content_scanner_new_from_file(rules);
- content = g_file_content_new(target);
+ if (scanner != NULL)
+ {
+ content = g_file_content_new(target);
+
+ context = g_content_scanner_analyze(scanner, options, content);
- context = g_content_scanner_analyze(scanner, options, content);
+ g_scan_context_display(context);
- g_scan_context_display(context);
+ g_object_unref(G_OBJECT(context));
+ g_object_unref(G_OBJECT(content));
- g_object_unref(G_OBJECT(context));
- g_object_unref(G_OBJECT(content));
+ g_object_unref(G_OBJECT(scanner));
- g_object_unref(G_OBJECT(scanner));
+ }
g_object_unref(G_OBJECT(options));
/* Sortie */
- //unload_all_core_components(false);
+ unload_all_core_components(false);
#ifdef TRACK_GOBJECT_LEAKS
remember_gtypes_for_leaks();
diff --git a/tests/analysis/scan/booleans.py b/tests/analysis/scan/booleans.py
new file mode 100644
index 0000000..aa3c1a3
--- /dev/null
+++ b/tests/analysis/scan/booleans.py
@@ -0,0 +1,98 @@
+
+from common import RostTestClass
+
+
+class TestRostBooleans(RostTestClass):
+ """TestCases for booleans and ROST."""
+
+ def testFinalCondition(self):
+ """Validate the final condition."""
+
+ rule = '''
+rule test {
+
+ condition:
+ false
+
+}
+'''
+
+ self.check_rule_failure(rule)
+
+
+ rule = '''
+rule test {
+
+ condition:
+ true
+
+}
+'''
+
+ self.check_rule_success(rule)
+
+
+ def testBasicBooleanOperations(self):
+ """Evaluate basic boolean operations."""
+
+ rule = '''
+rule test {
+
+ condition:
+ true and false
+
+}
+'''
+
+ self.check_rule_failure(rule)
+
+
+ rule = '''
+rule test {
+
+ condition:
+ true or false
+
+}
+'''
+
+ self.check_rule_success(rule)
+
+
+ def testImplicitCast(self):
+ """Imply implicit casts to booleans."""
+
+ rule = '''
+rule test {
+
+ condition:
+ true and 0
+
+}
+'''
+
+ self.check_rule_failure(rule)
+
+
+ rule = '''
+rule test {
+
+ condition:
+ 1 or false
+
+}
+'''
+
+ self.check_rule_success(rule)
+
+
+ rule = '''
+rule test {
+
+ condition:
+ 1 or ()
+
+}
+'''
+
+ self.check_rule_success(rule)
diff --git a/tests/analysis/scan/common.py b/tests/analysis/scan/common.py
new file mode 100644
index 0000000..3b52e38
--- /dev/null
+++ b/tests/analysis/scan/common.py
@@ -0,0 +1,52 @@
+
+from chrysacase import ChrysalideTestCase
+from pychrysalide.analysis.contents import MemoryContent
+from pychrysalide.analysis.scan import ContentScanner
+from pychrysalide.analysis.scan import ScanOptions
+from pychrysalide.analysis.scan.patterns.backends import AcismBackend
+
+
+class RostTestClass(ChrysalideTestCase):
+ """TestCase for analysis.scan.ScanExpression."""
+
+ @classmethod
+ def setUpClass(cls):
+
+ super(RostTestClass, cls).setUpClass()
+
+ cls._options = ScanOptions()
+ cls._options.backend_for_data = AcismBackend
+
+ cls._empty_content = MemoryContent(b'')
+
+
+ def _validate_rule_result(self, rule, content, expected):
+ """Check for scan success or failure."""
+
+ scanner = ContentScanner(rule)
+ ctx = scanner.analyze(self._options, content)
+
+ self.assertIsNotNone(ctx)
+
+ if expected:
+ self.assertTrue(ctx.has_match_for_rule('test'))
+ else:
+ self.assertFalse(ctx.has_match_for_rule('test'))
+
+
+ def check_rule_success(self, rule, content = None):
+ """Check for scan success."""
+
+ if content is None:
+ content = self._empty_content
+
+ self._validate_rule_result(rule, content, True)
+
+
+ def check_rule_failure(self, rule, content = None):
+ """Check for scan failure."""
+
+ if content is None:
+ content = self._empty_content
+
+ self._validate_rule_result(rule, content, False)
diff --git a/tests/analysis/scan/examples.py b/tests/analysis/scan/examples.py
new file mode 100644
index 0000000..74b5094
--- /dev/null
+++ b/tests/analysis/scan/examples.py
@@ -0,0 +1,70 @@
+
+from common import RostTestClass
+from pychrysalide.analysis.contents import MemoryContent
+
+
+class TestRostExamples(RostTestClass):
+ """TestCases for the examples provides in the ROST documentation."""
+
+ def testComments(self):
+ """Ensure comments do not bother rule definitions."""
+
+ rule = '''
+/*
+ Multi-line header...
+*/
+
+rule test { // comment
+
+ /*
+ * Some context
+ */
+
+ condition: /* List of condition(s) */
+ true // Dummy condition
+
+}
+'''
+
+ self.check_rule_success(rule)
+
+
+ def testArithmeticPrecedence(self):
+ """Take care of arithmetic operators precedence."""
+
+ rule = '''
+rule test { // MulFirst
+
+ condition:
+ 1 + 4 * (3 + 2) == 21
+ and
+ (1 + 4) * (3 + 2) == 25
+
+}
+'''
+
+ self.check_rule_success(rule)
+
+
+ def testUintCast(self):
+ """Process nested integer values from binary content."""
+
+ cnt = MemoryContent(b'\x4d\x5a\x00\x00' + b'\x50\x45\x00\x00' + 52 * b'\x00' + b'\x04\x00\x00\x00')
+
+ rule = '''
+rule test { // IsPE
+
+ condition:
+
+ // MZ signature at offset 0 and ...
+
+ uint16(0) == 0x5a4d and
+
+ // ... PE signature at offset stored in the MZ header at offset 0x3c
+
+ uint32(uint32(0x3c)) == 0x00004550
+
+}
+'''
+
+ self.check_rule_success(rule, cnt)
diff --git a/tests/analysis/scan/expr.py b/tests/analysis/scan/expr.py
deleted file mode 100644
index dbe8c55..0000000
--- a/tests/analysis/scan/expr.py
+++ /dev/null
@@ -1,169 +0,0 @@
-
-
-from chrysacase import ChrysalideTestCase
-from pychrysalide.analysis.scan import ScanExpression
-from pychrysalide.glibext import ComparableItem
-
-
-class TestScanExpression(ChrysalideTestCase):
- """TestCase for analysis.scan.ScanExpression."""
-
-
- def testDirectInstances(self):
- """Reject direct instances."""
-
- with self.assertRaisesRegex(RuntimeError, 'pychrysalide.analysis.scan.ScanExpression is an abstract class'):
-
- e = ScanExpression()
-
-
- def testBooleanComparison(self):
- """Compare custom scan expressions."""
-
- class StrLenExpr(ScanExpression):
-
- def __init__(self, value):
- super().__init__(ScanExpression.ExprValueType.STRING)
- self._value = value
-
- def _cmp_rich(self, other, op):
-
- if op == ComparableItem.RichCmpOperation.EQ:
- return len(self._value) == len(other._value)
-
-
- e0 = StrLenExpr('00000000000')
-
- e1 = StrLenExpr('00000000000')
-
- e2 = StrLenExpr('000000000000000000000000000')
-
- self.assertTrue(e0 == e1)
-
- # !?
- # Python teste e0 != e1 (non implémenté), puis e1 != e0 (pareil) et en déduit une différence !
- # self.assertFalse(e0 != e1)
-
- self.assertFalse(e0 == e2)
-
- # TypeError: '<' not supported between instances of 'StrLenExpr' and 'StrLenExpr'
- with self.assertRaisesRegex(TypeError, '\'<\' not supported between instances'):
- self.assertTrue(e0 < e1)
-
-
-
-
-
-
- # def testTypeSubclassing(self):
- # """Verify the data type subclassing is working."""
-
- # class MyType(DataType):
-
- # def __init__(self, num):
- # super(MyType, self).__init__()
- # self._num = num
-
- # def _to_string(self, include):
- # return '%x' % self._num
-
- # def _dup(self):
- # return MyType(self._num)
-
- # tp = MyType(0x123)
-
- # self.assertEqual(str(tp), '123')
-
- # tp2 = tp.dup()
-
- # self.assertEqual(str(tp), str(tp2))
-
-
- # def testTypeDefaultProperties(self):
- # """Check for default values of some type properties."""
-
- # class MyPropType(DataType):
- # pass
-
- # tp = MyPropType()
-
- # self.assertTrue(tp.handle_namespaces)
-
- # self.assertFalse(tp.is_pointer)
-
- # self.assertFalse(tp.is_reference)
-
- # class MyPropType2(DataType):
-
- # def _handle_namespaces(self):
- # return True
-
- # def _is_pointer(self):
- # return 123 < 1234
-
- # def _is_reference(self):
- # return False
-
- # tp2 = MyPropType2()
-
- # self.assertTrue(tp.handle_namespaces)
-
- # self.assertTrue(tp2.is_pointer)
-
- # self.assertFalse(tp2.is_reference)
-
-
- # def testTypeNamespaces(self):
- # """Test the type namespace property."""
-
- # class MyNSType(DataType):
-
- # def __init__(self, name):
- # super(MyNSType, self).__init__()
- # self._name = name
-
- # def _to_string(self, include):
- # return self._name
-
- # tp = MyNSType('TP')
- # ns = MyNSType('NS')
-
- # self.assertIsNone(tp.namespace)
-
- # tp.namespace = (ns, '.')
-
- # self.assertEqual(str(tp), 'NS.TP')
-
- # self.assertEqual(tp.namespace, (ns, '.'))
-
-
- # def testTypeHash(self):
- # """Hash a user-defined type."""
-
- # class MyUserType(DataType):
-
- # def __init__(self, name):
- # super(MyUserType, self).__init__()
- # self._name = name
-
- # def _hash(self):
- # return hash(self._name)
-
- # tp = MyUserType('random')
-
- # self.assertEqual(tp.hash, hash('random') & ((1 << 32) - 1))
-
- # class MyOutOfRangeUserType(DataType):
-
- # hard_coded_hash = -8752470794866657507
-
- # def __init__(self, name):
- # super(MyOutOfRangeUserType, self).__init__()
- # self._name = name
-
- # def _hash(self):
- # return self.hard_coded_hash
-
- # tp = MyOutOfRangeUserType('out-of-range')
-
- # self.assertEqual(tp.hash, MyOutOfRangeUserType.hard_coded_hash & ((1 << 32) - 1))
diff --git a/tests/analysis/scan/exprs.py b/tests/analysis/scan/exprs.py
deleted file mode 100644
index c89dc59..0000000
--- a/tests/analysis/scan/exprs.py
+++ /dev/null
@@ -1,122 +0,0 @@
-
-from chrysacase import ChrysalideTestCase
-from pychrysalide.analysis.contents import MemoryContent
-from pychrysalide.analysis.scan import ContentScanner
-from pychrysalide.analysis.scan import ScanOptions
-from pychrysalide.analysis.scan.patterns.backends import AcismBackend
-
-
-class TestScanExpressions(ChrysalideTestCase):
- """TestCase for analysis.scan.exprs.*."""
-
- @classmethod
- def setUpClass(cls):
-
- super(TestScanExpressions, cls).setUpClass()
-
- cls._options = ScanOptions()
- cls._options.backend_for_data = AcismBackend
-
-
- def testBasicStringOperations(self):
- """Evaluate basic string operations."""
-
- cnt = MemoryContent(b'empty')
-
- rule = '''
-rule test {
-
- condition:
- "123abc456" contains "abc"
-
-}
-'''
-
- scanner = ContentScanner(rule)
- ctx = scanner.analyze(self._options, cnt)
-
- self.assertTrue(ctx.has_match_for_rule('test'))
-
- rule = '''
-rule test {
-
- condition:
- "123\t456" contains "\t"
-
-}
-'''
-
- scanner = ContentScanner(rule)
- ctx = scanner.analyze(self._options, cnt)
-
- self.assertTrue(ctx.has_match_for_rule('test'))
-
- rule = '''
-rule test {
-
- condition:
- "123-456" startswith "1"
-
-}
-'''
-
- scanner = ContentScanner(rule)
- ctx = scanner.analyze(self._options, cnt)
-
- self.assertTrue(ctx.has_match_for_rule('test'))
-
- rule = '''
-rule test {
-
- condition:
- "123-456" startswith "1234"
-
-}
-'''
-
- scanner = ContentScanner(rule)
- ctx = scanner.analyze(self._options, cnt)
-
- self.assertFalse(ctx.has_match_for_rule('test'))
-
- rule = '''
-rule test {
-
- condition:
- "123-456" endswith "6"
-
-}
-'''
-
- scanner = ContentScanner(rule)
- ctx = scanner.analyze(self._options, cnt)
-
- self.assertTrue(ctx.has_match_for_rule('test'))
-
- rule = '''
-rule test {
-
- condition:
- "123-456" endswith "3456"
-
-}
-'''
-
- scanner = ContentScanner(rule)
- ctx = scanner.analyze(self._options, cnt)
-
- self.assertFalse(ctx.has_match_for_rule('test'))
-
- rule = '''
-rule test {
-
- condition:
- "ABCD" iequals "AbCd"
-
-}
-'''
-
- scanner = ContentScanner(rule)
- ctx = scanner.analyze(self._options, cnt)
-
- self.assertTrue(ctx.has_match_for_rule('test'))
diff --git a/tests/analysis/scan/func.py b/tests/analysis/scan/func.py
deleted file mode 100644
index bd7d0ce..0000000
--- a/tests/analysis/scan/func.py
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-from chrysacase import ChrysalideTestCase
-from pychrysalide.analysis.scan import ScanFunction
-
-
-class TestScanFunction(ChrysalideTestCase):
- """TestCase for analysis.scan.ScanFunction."""
-
-
- def testDirectInstances(self):
- """Reject direct instances."""
-
- with self.assertRaisesRegex(RuntimeError, 'pychrysalide.analysis.scan.ScanFunction is an abstract class'):
-
- f = ScanFunction('name')
diff --git a/tests/analysis/scan/functions.py b/tests/analysis/scan/functions.py
new file mode 100644
index 0000000..8553018
--- /dev/null
+++ b/tests/analysis/scan/functions.py
@@ -0,0 +1,104 @@
+
+from common import RostTestClass
+from pychrysalide.analysis.contents import MemoryContent
+
+
+class TestRostFunctions(RostTestClass):
+ """TestCases for the core functions of ROST."""
+
+ # Core
+ # ====
+
+ def testDatasize(self):
+ """Handle the size of the provided data."""
+
+ cnt = MemoryContent(b'\x01\x02\x03\x04')
+
+ cases = [
+ 'datasize == 4',
+ 'uint16(0) == 0x201 and uint16(datasize - 2) == 0x0403',
+ ]
+
+ for c in cases:
+
+ rule = '''
+rule test {
+
+ condition:
+ %s
+
+}
+''' % c
+
+ self.check_rule_success(rule, cnt)
+
+
+ # Modules
+ # =======
+
+ def testConsole(self):
+ """Ensure logging always returns true."""
+
+ rule = '''
+rule test {
+
+ condition:
+ console.log()
+
+}
+'''
+
+ self.check_rule_success(rule)
+
+
+ def testMagic(self):
+ """Scan text content with the Magic module."""
+
+ cnt = MemoryContent(b'aaaa')
+
+ cases = [
+ [ 'type', 'ASCII text, with no line terminators' ],
+ [ 'mime_encoding', 'us-ascii' ],
+ [ 'mime_type', 'text/plain' ],
+ ]
+
+ for target, expected in cases:
+
+ rule = '''
+rule test {
+
+ condition:
+ magic.%s() == "%s"
+
+}
+''' % (target, expected)
+
+ self.check_rule_success(rule, cnt)
+
+
+ def testTime(self):
+ """Check current time."""
+
+ # Cf. https://www.epochconverter.com/
+
+ rule = '''
+rule test {
+
+ condition:
+ time.make(2023, 8, 5, 22, 8, 41) == 0x64cec869
+
+}
+'''
+
+ self.check_rule_success(rule)
+
+ rule = '''
+rule test {
+
+ condition:
+ time.now() >= 0x64cec874 and time.now() <= time.now()
+
+}
+'''
+
+ self.check_rule_success(rule)
diff --git a/tests/analysis/scan/grammar.py b/tests/analysis/scan/grammar.py
index 5a2e1d5..8b18f81 100644
--- a/tests/analysis/scan/grammar.py
+++ b/tests/analysis/scan/grammar.py
@@ -1,286 +1,191 @@
-from chrysacase import ChrysalideTestCase
-from pychrysalide.analysis.contents import MemoryContent
-from pychrysalide.analysis.scan import ContentScanner
-from pychrysalide.analysis.scan import ScanOptions
-from pychrysalide.analysis.scan.patterns.backends import AcismBackend
+from common import RostTestClass
-class TestRostGrammar(ChrysalideTestCase):
- """TestCase for analysis.scan.ScanExpression."""
+class TestRostGrammar(RostTestClass):
+ """TestCases for the ROST grammar."""
- @classmethod
- def setUpClass(cls):
+ def testRelationalExpressions(self):
+ """Build expressions with relational comparisons."""
- super(TestRostGrammar, cls).setUpClass()
+ cases = [
- cls._options = ScanOptions()
- cls._options.backend_for_data = AcismBackend
+ # Regular
+ [ '-1', '<=', '2', True ],
+ [ '-1', '<=', '2', True ],
+ [ '"aaa"', '==', '"aaa"', True ],
+ [ '"aaa"', '<', '"aaaa"', True ],
+ [ '""', '<', '"aaaa"', True ],
+ # Cast
+ [ 'false', '==', '0', True ],
+ [ 'false', '==', '1', False ],
+ [ 'true', '!=', '0', True ],
+ [ '1', '==', 'true', True ],
+ [ 'false', '==', '()', True ],
+ [ 'true', '==', '(0,)', True ],
- def testComments(self):
- """Ensure comments do not bother rule definitions."""
+ ]
- cnt = MemoryContent(b'no_real_content')
+ for op1, kwd, op2, expected in cases:
- rule = '''
-/*
- Multi-line header...
-*/
-
-rule test { // comment
-
- /*
- * Some context
- */
-
- condition: /* List of condition(s) */
- true // Dummy condition
-
-}
-'''
-
- scanner = ContentScanner(rule)
- ctx = scanner.analyze(self._options, cnt)
-
- self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
-
-
- def testUintCast(self):
- """Process nested integer values from binary content."""
-
- cnt = MemoryContent(b'\x4d\x5a\x00\x00' + b'\x50\x45\x00\x00' + 52 * b'\x00' + b'\x04\x00\x00\x00')
-
- rule = '''
-rule IsPE {
-
- condition:
-
- // MZ signature at offset 0 and ...
-
- uint16(0) == 0x5a4d and
-
- // ... PE signature at offset stored in the MZ header at offset 0x3c
-
- uint32(uint32(0x3c)) == 0x00004550
-
-}
-'''
-
- scanner = ContentScanner(rule)
- ctx = scanner.analyze(self._options, cnt)
-
- self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('IsPE'))
-
-
- def testBasicBooleanConditions(self):
- """Evaluate basic boolean conditions."""
-
- cnt = MemoryContent(b'0123')
-
- rule = '''
-rule test {
-
- condition:
- true and false
-
-}
-'''
-
- scanner = ContentScanner(rule)
-
- ctx = scanner.analyze(self._options, cnt)
-
- self.assertTrue(not(ctx is None))
- self.assertFalse(ctx.has_match_for_rule('test'))
-
- rule = '''
+ rule = '''
rule test {
condition:
- true or false
+ %s %s %s
}
-'''
+''' % (op1, kwd, op2)
- scanner = ContentScanner(rule)
+ if expected:
+ self.check_rule_success(rule)
+ else:
+ self.check_rule_failure(rule)
- ctx = scanner.analyze(self._options, cnt)
- self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+ def testLogicalOperations(self):
+ """Evaluate some logical operations."""
+ cases = [
+ [ 'true and false', False ],
+ [ 'false or false', False ],
+ [ 'true and true or false', True ],
+ [ 'false or true and false', False ],
+ [ '1 or false', True ],
+ ]
- def testArithmeticOpeations(self):
- """Compute some arithmetic operations."""
+ for cond, expected in cases:
- cnt = MemoryContent(b'0123')
-
- rule = '''
+ rule = '''
rule test {
condition:
- 1 + 4 * 3 + 2 == 15
+ %s
}
-'''
-
- scanner = ContentScanner(rule)
-
- ctx = scanner.analyze(self._options, cnt)
+''' % (cond)
- self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+ if expected:
+ self.check_rule_success(rule)
+ else:
+ self.check_rule_failure(rule)
- rule = '''
-rule test {
+ def testArithmeticOperations(self):
+ """Evaluate some arithmetic operations."""
- condition:
- (1 + 4) * 3 + 2 == 17
+ cases = [
-}
-'''
+ # Clever
+ '1 + 2 == 3',
+ '10 + -3 == 7',
+ '-3 + 10 == 7',
+ '-10 - 1 < 0',
+ '-10 - 1 == -11',
+ '(-10 - 1) == -11',
+ '(-1 - -10) == 9',
+ '-2 * -3 == 6',
+ '-2 * 3 == -6',
- scanner = ContentScanner(rule)
+ # Legacy
+ '1 + 4 * 3 + 2 == 15',
+ '(1 + 4) * 3 + 2 == 17',
+ '1 + 4 * (3 + 2) == 21',
+ '(1 + 4) * (3 + 2) == 25',
- ctx = scanner.analyze(self._options, cnt)
+ ]
- self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+ for c in cases:
-
- rule = '''
+ rule = '''
rule test {
condition:
- 1 + 4 * (3 + 2) == 21
+ %s
}
-'''
+''' % (c)
- scanner = ContentScanner(rule)
+ self.check_rule_success(rule)
- ctx = scanner.analyze(self._options, cnt)
- self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+ def testBasicStringsOperations(self):
+ """Build expressions with basic strings operations."""
+ cases = [
- rule = '''
-rule test {
+ # Clever
+ [ '123---456', 'contains', '---', True ],
+ [ '123---456', 'contains', 'xxx', False ],
+ [ '---123---456', 'startswith', '---', True ],
+ [ '---123---456', 'startswith', 'xxx', False ],
+ [ '123---456---', 'endswith', '---', True ],
+ [ '123---456---', 'endswith', 'xxx', False ],
+ [ 'AAA---BBB', 'icontains', 'aaa', True ],
+ [ 'AAA---BBB', 'icontains', 'xxx', False ],
+ [ 'AAA---BBB', 'istartswith', 'aAa', True ],
+ [ 'AAA---BBB', 'istartswith', 'xxx', False ],
+ [ 'AAA---BBB', 'iendswith', 'bBb', True ],
+ [ 'AAA---BBB', 'iendswith', 'xxx', False ],
+ [ 'AzertY', 'iequals', 'AZERTY', True ],
+ [ 'AzertY', 'iequals', 'AZERTY-', False ],
- condition:
- (1 + 4) * (3 + 2) == 25
-
-}
-'''
+ # Legacy
+ [ '123\t456', 'contains', '\t', True ],
+ [ '123-456', 'startswith', '1', True ],
+ [ '123-456', 'startswith', '1234', False ],
+ [ '123-456', 'endswith', '6', True ],
+ [ '123-456', 'endswith', '3456', False ],
- scanner = ContentScanner(rule)
+ ]
- ctx = scanner.analyze(self._options, cnt)
+ for op1, kwd, op2, expected in cases:
- self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
-
-
- def testSizeUnits(self):
- """Evaluate size units."""
-
- cnt = MemoryContent(b'0123')
-
-
- rule = '''
-rule test {
-
- condition:
- 1KB == 1024
-
-}
-'''
-
- scanner = ContentScanner(rule)
-
- ctx = scanner.analyze(self._options, cnt)
-
- self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
-
-
- rule = '''
+ rule = '''
rule test {
condition:
- 2MB == 2 * 1024 * 1024
+ "%s" %s "%s"
}
-'''
+''' % (op1, kwd, op2)
- scanner = ContentScanner(rule)
+ if expected:
+ self.check_rule_success(rule)
+ else:
+ self.check_rule_failure(rule)
- ctx = scanner.analyze(self._options, cnt)
-
- self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
-
-
- rule = '''
-rule test {
-
- condition:
- 4Kb == (4 * 1024)
-
-}
-'''
-
- scanner = ContentScanner(rule)
-
- ctx = scanner.analyze(self._options, cnt)
-
- self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
-
-
- rule = '''
-rule test {
-
- condition:
- 1KB <= 1024 and 1024 < 1MB
-
-}
-'''
-
- scanner = ContentScanner(rule)
-
- ctx = scanner.analyze(self._options, cnt)
-
- self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+ def testSizeUnits(self):
+ """Evaluate size units."""
- def testNamespace(self):
- """Resolve main functions with the root scan namesapce."""
+ cases = [
+ '1KB == 1024',
+ '2MB == 2 * 1024 * 1024',
+ '4Kb == (4 * 1024)',
+ '1KB <= 1024 and 1024 < 1MB',
+ ]
- cnt = MemoryContent(b'\x01\x02\x03\x04')
+ for c in cases:
- rule = '''
+ rule = '''
rule test {
condition:
- datasize == 4
+ %s
}
-'''
+''' % (c)
- scanner = ContentScanner(rule)
+ self.check_rule_success(rule)
- ctx = scanner.analyze(self._options, cnt)
- self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
- rule = '''
-rule test {
- condition:
- uint16(0) == 0x201 and uint16(datasize - 2) == 0x0403
-}
-'''
+# TODO : test <haystack> matches <regex>
- scanner = ContentScanner(rule)
- ctx = scanner.analyze(self._options, cnt)
- self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
diff --git a/tests/analysis/scan/matches.py b/tests/analysis/scan/matches.py
new file mode 100644
index 0000000..0d7556e
--- /dev/null
+++ b/tests/analysis/scan/matches.py
@@ -0,0 +1,27 @@
+
+from common import RostTestClass
+from pychrysalide.analysis.contents import MemoryContent
+
+
+class TestRostMatchs(RostTestClass):
+ """TestCases for the ROST pattern matching engine."""
+
+ def testCountMatches(self):
+ """Count matches patterns."""
+
+ cnt = MemoryContent(b'aaa aaa bbb aaa')
+
+ rule = '''
+rule test {
+
+ strings:
+ $a = "aaa"
+ $b = "bbb"
+
+ condition:
+ #a == 3 and #b < 2
+
+}
+'''
+
+ self.check_rule_success(rule, cnt)
diff --git a/tests/analysis/scan/options.py b/tests/analysis/scan/options.py
deleted file mode 100644
index 7617b3a..0000000
--- a/tests/analysis/scan/options.py
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-from chrysacase import ChrysalideTestCase
-from gi._constants import TYPE_INVALID
-from pychrysalide.analysis.scan import ScanOptions
-
-
-class TestScanOptions(ChrysalideTestCase):
- """TestCase for analysis.scan.ScanOptions."""
-
- def testEmptyOptions(self):
- """Check default scan options."""
-
- ops = ScanOptions()
-
- self.assertEqual(ops.backend_for_data, TYPE_INVALID)
diff --git a/tests/analysis/scan/pyapi.py b/tests/analysis/scan/pyapi.py
new file mode 100644
index 0000000..1bba44e
--- /dev/null
+++ b/tests/analysis/scan/pyapi.py
@@ -0,0 +1,58 @@
+
+from chrysacase import ChrysalideTestCase
+from gi._constants import TYPE_INVALID
+from pychrysalide.analysis.scan import ScanExpression
+from pychrysalide.analysis.scan import ScanOptions
+from pychrysalide.glibext import ComparableItem
+
+
+class TestRostPythonAPI(ChrysalideTestCase):
+ """TestCase for the ROST Python API."""
+
+ def testEmptyOptions(self):
+ """Check default scan options."""
+
+ ops = ScanOptions()
+
+ self.assertEqual(ops.backend_for_data, TYPE_INVALID)
+
+
+ def testDirectInstancesOfExpression(self):
+ """Reject direct instances of ROST expressions."""
+
+ with self.assertRaisesRegex(RuntimeError, 'pychrysalide.analysis.scan.ScanExpression is an abstract class'):
+
+ e = ScanExpression()
+
+ def testBooleanComparison(self):
+ """Compare custom scan expressions."""
+
+ class StrLenExpr(ScanExpression):
+
+ def __init__(self, value):
+ super().__init__(ScanExpression.ExprValueType.STRING)
+ self._value = value
+
+ def _cmp_rich(self, other, op):
+
+ if op == ComparableItem.RichCmpOperation.EQ:
+ return len(self._value) == len(other._value)
+
+
+ e0 = StrLenExpr('00000000000')
+
+ e1 = StrLenExpr('00000000000')
+
+ e2 = StrLenExpr('000000000000000000000000000')
+
+ self.assertTrue(e0 == e1)
+
+ # !?
+ # Python teste e0 != e1 (non implémenté), puis e1 != e0 (pareil) et en déduit une différence !
+ # self.assertFalse(e0 != e1)
+
+ self.assertFalse(e0 == e2)
+
+ # TypeError: '<' not supported between instances of 'StrLenExpr' and 'StrLenExpr'
+ with self.assertRaisesRegex(TypeError, '\'<\' not supported between instances'):
+ self.assertTrue(e0 < e1)
diff --git a/tests/analysis/scan/sets.py b/tests/analysis/scan/sets.py
new file mode 100644
index 0000000..1d10fbf
--- /dev/null
+++ b/tests/analysis/scan/sets.py
@@ -0,0 +1,118 @@
+
+from common import RostTestClass
+
+
+class TestRostSets(RostTestClass):
+ """TestCases for sets support in ROST."""
+
+ def testSetsAsBooleans(self):
+ """Convert sets to boolean."""
+
+ rule = '''
+rule test {
+
+ condition:
+ ()
+
+}
+'''
+
+ self.check_rule_failure(rule)
+
+
+ rule = '''
+rule test {
+
+ condition:
+ (1, )
+
+}
+'''
+
+ self.check_rule_success(rule)
+
+
+ rule = '''
+rule test {
+
+ condition:
+ ("aaa", true, 123)
+
+}
+'''
+
+ self.check_rule_success(rule)
+
+
+ def testStringAsArray(self):
+ """Handle strings as arrays."""
+
+ rule = '''
+rule test {
+
+ condition:
+ count("aaa")
+
+}
+'''
+
+ self.check_rule_success(rule)
+
+
+ rule = '''
+rule test {
+
+ condition:
+ count("aaa") == 3
+
+}
+'''
+
+ self.check_rule_success(rule)
+
+
+ def testSetsIntersections(self):
+ """Perform sets intersections."""
+
+ rule = '''
+rule test {
+
+ condition:
+ ("aaa", "bbb") in ("AAA", "BBB", "aaa")
+
+}
+'''
+
+ self.check_rule_success(rule)
+
+
+ rule = '''
+rule test {
+
+ condition:
+ ("aaa", "bbb") in ("123", )
+
+}
+'''
+
+ self.check_rule_failure(rule)
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # TODO :
+
+ # test : intersection(a, a) == a
+
+ # test : "123" in "0123456789"
+ # test : "123" in "012987"
+