summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2023-10-07 23:27:24 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2023-10-07 23:27:24 (GMT)
commit22c06200eca1ecda455a8d68bf73ec4fc458f59f (patch)
tree043ace80df905152094840072f45fd9eb836a4c4
parentedb4cc9c11c417d81b1948d93dfd171f0696217a (diff)
Create some glue between ROST and Kaitai.
-rw-r--r--configure.ac2
-rw-r--r--plugins/kaitai/Makefile.am4
-rw-r--r--plugins/kaitai/core.c4
-rw-r--r--plugins/kaitai/python/Makefile.am5
-rw-r--r--plugins/kaitai/python/module.c3
-rw-r--r--plugins/kaitai/python/rost/Makefile.am14
-rw-r--r--plugins/kaitai/python/rost/module.c115
-rw-r--r--plugins/kaitai/python/rost/module.h41
-rw-r--r--plugins/kaitai/python/rost/trigger.c236
-rw-r--r--plugins/kaitai/python/rost/trigger.h45
-rw-r--r--plugins/kaitai/rost/Makefile.am18
-rw-r--r--plugins/kaitai/rost/browser-int.h58
-rw-r--r--plugins/kaitai/rost/browser.c474
-rw-r--r--plugins/kaitai/rost/browser.h58
-rw-r--r--plugins/kaitai/rost/core.c66
-rw-r--r--plugins/kaitai/rost/core.h37
-rw-r--r--plugins/kaitai/rost/space-int.h55
-rw-r--r--plugins/kaitai/rost/space.c240
-rw-r--r--plugins/kaitai/rost/space.h59
-rw-r--r--plugins/kaitai/rost/trigger-int.h59
-rw-r--r--plugins/kaitai/rost/trigger.c320
-rw-r--r--plugins/kaitai/rost/trigger.h58
-rw-r--r--plugins/pychrysalide/analysis/scan/space.c2
-rw-r--r--src/analysis/scan/exprs/Makefile.am2
-rw-r--r--src/analysis/scan/exprs/call.c2
-rw-r--r--src/analysis/scan/exprs/extract-int.h57
-rw-r--r--src/analysis/scan/exprs/extract.c396
-rw-r--r--src/analysis/scan/exprs/extract.h56
-rw-r--r--src/analysis/scan/grammar.y139
-rw-r--r--src/analysis/scan/item-int.h5
-rw-r--r--src/analysis/scan/item.c33
-rw-r--r--src/analysis/scan/item.h3
-rw-r--r--src/analysis/scan/space.c1
-rw-r--r--tests/plugins/kaitai/__init__.py0
-rw-r--r--tests/plugins/kaitai/rost.py170
35 files changed, 2766 insertions, 71 deletions
diff --git a/configure.ac b/configure.ac
index 7673a96..3ecd8de 100644
--- a/configure.ac
+++ b/configure.ac
@@ -680,9 +680,11 @@ AC_CONFIG_FILES([Makefile
plugins/kaitai/Makefile
plugins/kaitai/parsers/Makefile
plugins/kaitai/records/Makefile
+ plugins/kaitai/rost/Makefile
plugins/kaitai/python/Makefile
plugins/kaitai/python/parsers/Makefile
plugins/kaitai/python/records/Makefile
+ plugins/kaitai/python/rost/Makefile
plugins/libcsem/Makefile
plugins/lnxsyscalls/Makefile
plugins/mobicore/Makefile
diff --git a/plugins/kaitai/Makefile.am b/plugins/kaitai/Makefile.am
index cbc0f25..6c612ba 100644
--- a/plugins/kaitai/Makefile.am
+++ b/plugins/kaitai/Makefile.am
@@ -67,6 +67,7 @@ libkaitai_la_SOURCES = \
libkaitai_la_LIBADD = \
parsers/libkaitaiparsers.la \
records/libkaitairecords.la \
+ rost/libkaitairost.la \
$(PYTHON3_LIBADD)
libkaitai_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
@@ -88,5 +89,4 @@ CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h
EXTRA_DIST = tokens.h
-# misc
-SUBDIRS = parsers records $(PYTHON3_SUBDIRS)
+SUBDIRS = parsers records rost $(PYTHON3_SUBDIRS)
diff --git a/plugins/kaitai/core.c b/plugins/kaitai/core.c
index 7483fbc..c41d96d 100644
--- a/plugins/kaitai/core.c
+++ b/plugins/kaitai/core.c
@@ -30,6 +30,8 @@
#ifdef INCLUDE_PYTHON3_BINDINGS
# include "python/module.h"
#endif
+#include "rost/core.h"
+
#ifdef INCLUDE_PYTHON3_BINDINGS
@@ -62,7 +64,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
{
bool result; /* Bilan à retourner */
- result = true;
+ result = add_kaitai_support_to_rost();
#ifdef INCLUDE_PYTHON3_BINDINGS
diff --git a/plugins/kaitai/python/Makefile.am b/plugins/kaitai/python/Makefile.am
index ab40744..f222a66 100644
--- a/plugins/kaitai/python/Makefile.am
+++ b/plugins/kaitai/python/Makefile.am
@@ -11,7 +11,8 @@ libkaitaipython_la_SOURCES = \
libkaitaipython_la_LIBADD = \
parsers/libkaitaipythonparsers.la \
- records/libkaitaipythonrecords.la
+ records/libkaitaipythonrecords.la \
+ rost/libkaitaipythonrost.la
libkaitaipython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
@@ -22,4 +23,4 @@ devdir = $(includedir)/chrysalide-$(subdir)
dev_HEADERS = $(libkaitaipython_la_SOURCES:%c=)
-SUBDIRS = parsers records
+SUBDIRS = parsers records rost
diff --git a/plugins/kaitai/python/module.c b/plugins/kaitai/python/module.c
index fa1f9c2..07fb962 100644
--- a/plugins/kaitai/python/module.c
+++ b/plugins/kaitai/python/module.c
@@ -39,6 +39,7 @@
#include "stream.h"
#include "parsers/module.h"
#include "records/module.h"
+#include "rost/module.h"
@@ -89,6 +90,7 @@ bool add_kaitai_module_to_python_module(void)
if (result) result = add_kaitai_parsers_module();
if (result) result = add_kaitai_records_module();
+ if (result) result = add_kaitai_rost_module();
if (!result)
Py_XDECREF(module);
@@ -124,6 +126,7 @@ bool populate_kaitai_module(void)
if (result) result = populate_kaitai_parsers_module();
if (result) result = populate_kaitai_records_module();
+ if (result) result = populate_kaitai_rost_module();
assert(result);
diff --git a/plugins/kaitai/python/rost/Makefile.am b/plugins/kaitai/python/rost/Makefile.am
new file mode 100644
index 0000000..cae0419
--- /dev/null
+++ b/plugins/kaitai/python/rost/Makefile.am
@@ -0,0 +1,14 @@
+
+noinst_LTLIBRARIES = libkaitaipythonrost.la
+
+libkaitaipythonrost_la_SOURCES = \
+ module.h module.c \
+ trigger.h trigger.c
+
+libkaitaipythonrost_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libkaitaipythonrost_la_SOURCES:%c=)
diff --git a/plugins/kaitai/python/rost/module.c b/plugins/kaitai/python/rost/module.c
new file mode 100644
index 0000000..66a5a82
--- /dev/null
+++ b/plugins/kaitai/python/rost/module.c
@@ -0,0 +1,115 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire rost en tant que module
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "trigger.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Ajoute le module 'plugins.kaitai.rost' au module Python. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_kaitai_rost_module(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *super; /* Module à compléter */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_PLUGINS_KAITAI_ROST_DOC \
+ "This module creates some glue to extend the ROST features" \
+ " using Kaitai definitions for analyzing and filtering" \
+ " contents."
+
+ static PyModuleDef py_chrysalide_kaitai_rost_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.plugins.kaitai.rost",
+ .m_doc = PYCHRYSALIDE_PLUGINS_KAITAI_ROST_DOC,
+
+ .m_size = -1,
+
+ };
+
+ result = false;
+
+ super = get_access_to_python_module("pychrysalide.plugins.kaitai");
+
+ module = build_python_module(super, &py_chrysalide_kaitai_rost_module);
+
+ result = (module != NULL);
+
+ assert(result);
+
+ if (!result)
+ Py_XDECREF(module);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'plugins.kaitai.rost'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_kaitai_rost_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_kaitai_trigger_is_registered();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/rost/module.h b/plugins/kaitai/python/rost/module.h
new file mode 100644
index 0000000..8415c2e
--- /dev/null
+++ b/plugins/kaitai/python/rost/module.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire rost en tant que module
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_ROST_MODULE_H
+#define _PLUGINS_KAITAI_PYTHON_ROST_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'plugins.kaitai.rost' au module Python. */
+bool add_kaitai_rost_module(void);
+
+/* Intègre les objets du module 'plugins.kaitai.rost'. */
+bool populate_kaitai_rost_module(void);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_ROST_MODULE_H */
diff --git a/plugins/kaitai/python/rost/trigger.c b/plugins/kaitai/python/rost/trigger.c
new file mode 100644
index 0000000..180ef6e
--- /dev/null
+++ b/plugins/kaitai/python/rost/trigger.c
@@ -0,0 +1,236 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * trigger.c - équivalent Python du fichier "plugins/kaitai/rost/trigger.c"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "trigger.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/scan/item.h>
+
+
+#include "../parsers/struct.h"
+#include "../../parsers/struct.h"
+#include "../../rost/trigger-int.h"
+
+
+
+CREATE_DYN_CONSTRUCTOR(kaitai_trigger, G_TYPE_KAITAI_TRIGGER);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_kaitai_trigger_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_kaitai_trigger_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ GKaitaiStruct *kstruct; /* Définition Kaitai en place */
+ int ret; /* Bilan de lecture des args. */
+ GKaitaiTrigger *trigger; /* Création GLib à transmettre */
+
+#define KAITAI_TRIGGER_DOC \
+ "The KaitaiTrigger object store an access to a loaded Kaitai definition" \
+ " creates as many as required instances from it when ROST filters contents" \
+ " with the help of the Kaitai module.\n" \
+ "\n" \
+ "Instances can be created using following constructor:\n" \
+ "\n" \
+ " KaitaiTrigger(kstruct)" \
+ "\n" \
+ "Where *kstruct* is a pychrysalide.plugins.kaitai.parsers.KaitaiStruct" \
+ " instance loaded with a valid Kaitai definition."
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_kaitai_structure, &kstruct);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ trigger = G_KAITAI_TRIGGER(pygobject_get(self));
+
+ if (!g_kaitai_trigger_create(trigger, kstruct))
+ {
+ PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai stream."));
+ return -1;
+
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_kaitai_trigger_type(void)
+{
+ static PyMethodDef py_kaitai_trigger_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_kaitai_trigger_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_kaitai_trigger_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.plugins.kaitai.rost.KaitaiTrigger",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = KAITAI_TRIGGER_DOC,
+
+ .tp_methods = py_kaitai_trigger_methods,
+ .tp_getset = py_kaitai_trigger_getseters,
+
+ .tp_init = py_kaitai_trigger_init,
+ .tp_new = py_kaitai_trigger_new,
+
+ };
+
+ return &py_kaitai_trigger_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....rost.KaitaiTrigger. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_kaitai_trigger_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'RecordEmpty' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_kaitai_trigger_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.plugins.kaitai.rost");
+
+ dict = PyModule_GetDict(module);
+
+ if (!ensure_python_scan_registered_item_is_registered())
+ return false;
+
+ if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_TRIGGER, type))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en accès à une définition Kaitai. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_kaitai_trigger(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_trigger_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai trigger");
+ break;
+
+ case 1:
+ *((GKaitaiTrigger **)dst) = G_KAITAI_TRIGGER(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/kaitai/python/rost/trigger.h b/plugins/kaitai/python/rost/trigger.h
new file mode 100644
index 0000000..44776f7
--- /dev/null
+++ b/plugins/kaitai/python/rost/trigger.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * trigger.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/rost/trigger.h"
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_KAITAI_PYTHON_ROST_TRIGGER_H
+#define _PLUGINS_KAITAI_PYTHON_ROST_TRIGGER_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_kaitai_trigger_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.rost.KaitaiTrigger'. */
+bool ensure_python_kaitai_trigger_is_registered(void);
+
+/* Tente de convertir en accès à une définition Kaitai. */
+int convert_to_kaitai_trigger(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_KAITAI_PYTHON_ROST_TRIGGER_H */
diff --git a/plugins/kaitai/rost/Makefile.am b/plugins/kaitai/rost/Makefile.am
new file mode 100644
index 0000000..c7ea84a
--- /dev/null
+++ b/plugins/kaitai/rost/Makefile.am
@@ -0,0 +1,18 @@
+
+noinst_LTLIBRARIES = libkaitairost.la
+
+libkaitairost_la_SOURCES = \
+ browser-int.h \
+ browser.h browser.c \
+ core.h core.c \
+ space-int.h \
+ space.h space.c \
+ trigger-int.h \
+ trigger.h trigger.c
+
+libkaitairost_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libkaitairost_la_SOURCES:%c=)
diff --git a/plugins/kaitai/rost/browser-int.h b/plugins/kaitai/rost/browser-int.h
new file mode 100644
index 0000000..4b49680
--- /dev/null
+++ b/plugins/kaitai/rost/browser-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * browser-int.h - prototypes internes pour le parcours des résultats d'analyse Kaitai pour ROST
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef PLUGINS_KAITAI_ROST_BROWSER_INT_H
+#define PLUGINS_KAITAI_ROST_BROWSER_INT_H
+
+
+#include <analysis/scan/item-int.h>
+
+
+#include "browser.h"
+
+
+
+/* Parcours des résultats d'une analyse Kaitai pour ROST (instance) */
+struct _GKaitaiBrowser
+{
+ GScanRegisteredItem parent; /* A laisser en premier */
+
+ char *path; /* Chamin vers l'enregistrement*/
+ GMatchRecord *record; /* Correspondance à parcourir */
+
+};
+
+/* Parcours des résultats d'une analyse Kaitai pour ROST (classe) */
+struct _GKaitaiBrowserClass
+{
+ GScanRegisteredItemClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un nouveau parcours de correspondances Kaitai. */
+bool g_kaitai_browser_create(GKaitaiBrowser *, const char *, GMatchRecord *);
+
+
+
+#endif /* PLUGINS_KAITAI_ROST_BROWSER_INT_H */
diff --git a/plugins/kaitai/rost/browser.c b/plugins/kaitai/rost/browser.c
new file mode 100644
index 0000000..075c5ff
--- /dev/null
+++ b/plugins/kaitai/rost/browser.c
@@ -0,0 +1,474 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * browser.c - accès à des définitions Kaitai depuis ROST
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "browser.h"
+
+
+#include <assert.h>
+#include <string.h>
+
+
+#include <analysis/scan/exprs/literal.h>
+
+
+#include "browser-int.h"
+#include "../records/item.h"
+#include "../records/list.h"
+#include "../records/value.h"
+
+
+
+/* ---------------------- PARCOURS DE CORRESPONDANCES ETABLIES ---------------------- */
+
+
+/* Initialise la classe des parcours de correspondances Kaitai. */
+static void g_kaitai_browser_class_init(GKaitaiBrowserClass *);
+
+/* Initialise un parcours de correspondances Kaitai. */
+static void g_kaitai_browser_init(GKaitaiBrowser *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_browser_dispose(GKaitaiBrowser *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_browser_finalize(GKaitaiBrowser *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_kaitai_browser_get_name(const GKaitaiBrowser *);
+
+/* Lance une résolution d'élément à solliciter. */
+static bool g_kaitai_browser_resolve(GKaitaiBrowser *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **);
+
+/* Réduit une expression à une forme plus simple. */
+static bool g_kaitai_browser_reduce(GKaitaiBrowser *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Effectue une extraction d'élément à partir d'une série. */
+static GObject *g_kaitai_browser_extract_at(GKaitaiBrowser *, const GScanExpression *, GScanContext *, GScanScope *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* PARCOURS DE CORRESPONDANCES ETABLIES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un parcours de correspondances Kaitai pour ROST. */
+G_DEFINE_TYPE(GKaitaiBrowser, g_kaitai_browser, G_TYPE_SCAN_REGISTERED_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des parcours de correspondances Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_browser_class_init(GKaitaiBrowserClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_browser_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_browser_finalize;
+
+ registered = G_SCAN_REGISTERED_ITEM_CLASS(klass);
+
+ registered->get_name = (get_registered_item_name_fc)g_kaitai_browser_get_name;
+ registered->resolve = (resolve_registered_item_fc)g_kaitai_browser_resolve;
+ registered->reduce = (reduce_registered_item_fc)g_kaitai_browser_reduce;
+ registered->extract = (extract_registered_item_at)g_kaitai_browser_extract_at;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : browser = instance à initialiser. *
+* *
+* Description : Initialise un parcours de correspondances Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_browser_init(GKaitaiBrowser *browser)
+{
+ browser->path = NULL;
+ browser->record = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : browser = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_browser_dispose(GKaitaiBrowser *browser)
+{
+ g_clear_object(&browser->record);
+
+ G_OBJECT_CLASS(g_kaitai_browser_parent_class)->dispose(G_OBJECT(browser));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : browser = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_browser_finalize(GKaitaiBrowser *browser)
+{
+ if (browser->path != NULL)
+ free(browser->path);
+
+ G_OBJECT_CLASS(g_kaitai_browser_parent_class)->finalize(G_OBJECT(browser));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : path = chemin vers l'enregistrement fourni. *
+* record = correspondance racine à considérer. *
+* *
+* Description : Crée un nouveau parcours de correspondances Kaitai. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiBrowser *g_kaitai_browser_new(const char *path, GMatchRecord *record)
+{
+ GKaitaiBrowser *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_BROWSER, NULL);
+
+ if (!g_kaitai_browser_create(result, path, record))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : browser = encadrement d'un parcours de correspondances. *
+* path = chemin vers l'enregistrement fourni. *
+* record = correspondance racine à considérer. *
+* *
+* Description : Met en place un nouveau parcours de correspondances Kaitai. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_browser_create(GKaitaiBrowser *browser, const char *path, GMatchRecord *record)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (path != NULL)
+ browser->path = strdup(path);
+
+ browser->record = record;
+ g_object_ref(G_OBJECT(browser->record));
+
+ 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_kaitai_browser_get_name(const GKaitaiBrowser *item)
+{
+ char *result; /* Désignation à retourner */
+ int ret; /* Statut de construction */
+
+ if (item->path == NULL)
+ result = strdup("kaitai://");
+
+ else
+ {
+ ret = asprintf(&result, "kaitai://%s", item->path);
+ assert(ret > 0);
+
+ if (ret <= 0)
+ result = strdup("kaitai://???");
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* target = désignation de l'objet d'appel à identifier. *
+* 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 : Lance une résolution d'élément à solliciter. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_browser_resolve(GKaitaiBrowser *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out)
+{
+ bool result; /* Bilan à retourner */
+ GMatchRecord *found; /* Correspondance trouvée */
+ char *path;
+ int ret; /* Statut de construction */
+
+ found = g_match_record_find_by_name(item->record, target, strlen(target), 1);
+ result = (found != NULL);
+
+ if (result)
+ {
+ ret = asprintf(&path, "%s.%s", item->path, target);
+ assert(ret > 0);
+
+ if (ret <= 0)
+ path = strdup("!?");
+
+ *out = G_SCAN_REGISTERED_ITEM(g_kaitai_browser_new(path, found));
+
+ free(path);
+ g_object_unref(G_OBJECT(found));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à 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_kaitai_browser_reduce(GKaitaiBrowser *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+ size_t count; /* Décompte total à considérer */
+ resolved_value_t value; /* Valeur brute à transformer */
+
+ if (G_IS_RECORD_LIST(item->record))
+ {
+ count = g_record_list_count_records(G_RECORD_LIST(item->record));
+
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ count > 0 });
+
+ result = true;
+
+ }
+
+ else
+ {
+ if (G_IS_RECORD_ITEM(item->record))
+ result = g_record_item_get_value(G_RECORD_ITEM(item->record), &value);
+
+ else if (G_IS_RECORD_VALUE(item->record))
+ result = g_record_value_compute_and_aggregate_value(G_RECORD_VALUE(item->record), &value);
+
+ else
+ result = false;
+
+ if (result)
+ {
+ switch (value.type)
+ {
+ case GVT_UNSIGNED_INTEGER:
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &value.unsigned_integer);
+ break;
+
+ case GVT_SIGNED_INTEGER:
+ *out = g_scan_literal_expression_new(LVT_SIGNED_INTEGER, &value.signed_integer);
+ break;
+
+ case GVT_FLOAT:
+ /* TODO */
+ break;
+
+ case GVT_BOOLEAN:
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, &value.status);
+ break;
+
+ case GVT_BYTES:
+ *out = g_scan_literal_expression_new(LVT_STRING, &value.bytes);
+ break;
+
+ default:
+ break;
+
+ }
+
+ EXIT_RESOLVED_VALUE(value);
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* index = indice de l'élément à cibler. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* *
+* Description : Effectue une extraction d'élément à partir d'une série. *
+* *
+* Retour : Elément de série obtenu ou NULL si erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GObject *g_kaitai_browser_extract_at(GKaitaiBrowser *item, const GScanExpression *index, GScanContext *ctx, GScanScope *scope)
+{
+ GObject *result; /* Elément récupéré à renvoyer */
+ GScanLiteralExpression *literal; /* Accès direct à l'indice */
+ LiteralValueType vtype; /* Type de valeur portée */
+ unsigned long long at; /* Valeur concrète du point */
+ bool status; /* Bilan d'obtention d'indice */
+ GRecordList *list; /* Accès direct à la liste */
+ size_t count; /* Décompte total à considérer */
+ GMatchRecord *found; /* Correspondance trouvée */
+ char *path;
+ int ret; /* Statut de construction */
+
+ result = NULL;
+
+ /* Validations préliminaires */
+
+ if (!G_IS_RECORD_LIST(item->record)) goto exit;
+ if (!G_IS_SCAN_LITERAL_EXPRESSION(index)) goto exit;
+
+ literal = G_SCAN_LITERAL_EXPRESSION(index);
+
+ vtype = g_scan_literal_expression_get_value_type(literal);
+ if (vtype != LVT_UNSIGNED_INTEGER) goto exit;
+
+ status = g_scan_literal_expression_get_unsigned_integer_value(literal, &at);
+ if (!status) goto exit;
+
+ list = G_RECORD_LIST(item->record);
+
+ count = g_record_list_count_records(list);
+ if (at >= count) goto exit;
+
+ /* Récupération de l'élément visé */
+
+ found = g_record_list_get_record(list, at);
+ if (found == NULL) goto exit;
+
+ ret = asprintf(&path, "%s[%llu]", item->path, at);
+ assert(ret > 0);
+
+ if (ret <= 0)
+ path = strdup("!?");
+
+ result = G_OBJECT(g_kaitai_browser_new(path, found));
+
+ free(path);
+ g_object_unref(G_OBJECT(found));
+
+ exit:
+
+ return result;
+
+}
diff --git a/plugins/kaitai/rost/browser.h b/plugins/kaitai/rost/browser.h
new file mode 100644
index 0000000..89b9f6f
--- /dev/null
+++ b/plugins/kaitai/rost/browser.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * browser.h - prototypes pour le parcours des résultats d'analyse Kaitai pour ROST
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef PLUGINS_KAITAI_ROST_BROWSER_H
+#define PLUGINS_KAITAI_ROST_BROWSER_H
+
+
+#include <glib-object.h>
+
+
+#include "../record.h"
+
+
+
+#define G_TYPE_KAITAI_BROWSER g_kaitai_browser_get_type()
+#define G_KAITAI_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_BROWSER, GKaitaiBrowser))
+#define G_IS_KAITAI_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_BROWSER))
+#define G_KAITAI_BROWSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_BROWSER, GKaitaiBrowserClass))
+#define G_IS_KAITAI_BROWSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_BROWSER))
+#define G_KAITAI_BROWSER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_BROWSER, GKaitaiBrowserClass))
+
+
+/* Parcours des résultats d'une analyse Kaitai pour ROST (instance) */
+typedef struct _GKaitaiBrowser GKaitaiBrowser;
+
+/* Parcours des résultats d'une analyse Kaitai pour ROST (classe) */
+typedef struct _GKaitaiBrowserClass GKaitaiBrowserClass;
+
+
+/* Indique le type défini pour un parcours de correspondances Kaitai pour ROST. */
+GType g_kaitai_browser_get_type(void);
+
+/* Crée un nouveau parcours de correspondances Kaitai. */
+GKaitaiBrowser *g_kaitai_browser_new(const char *, GMatchRecord *);
+
+
+
+#endif /* PLUGINS_KAITAI_ROST_BROWSER_H */
diff --git a/plugins/kaitai/rost/core.c b/plugins/kaitai/rost/core.c
new file mode 100644
index 0000000..8271389
--- /dev/null
+++ b/plugins/kaitai/rost/core.c
@@ -0,0 +1,66 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.c - mise à disposition d'un support Kaitai pour ROST
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "core.h"
+
+
+#include <core/global.h>
+
+
+#include "space.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre un support de Kaitai pour ROST. *
+* *
+* Retour : Bilan du chargement mené. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_kaitai_support_to_rost(void)
+{
+ bool result; /* Bilan à retourner */
+ GScanNamespace *root_ns; /* Espace de noms ROST racine */
+ GScanNamespace *kaitai_ns; /* Espace de noms pour Kaitai */
+
+ result = true;
+
+ root_ns = get_rost_root_namespace();
+
+ kaitai_ns = g_kaitai_namespace_new();
+
+ result = g_scan_namespace_register_item(root_ns, G_SCAN_REGISTERED_ITEM(kaitai_ns));
+
+ g_object_unref(G_OBJECT(kaitai_ns));
+
+ g_object_unref(G_OBJECT(root_ns));
+
+ return result;
+
+}
diff --git a/plugins/kaitai/rost/core.h b/plugins/kaitai/rost/core.h
new file mode 100644
index 0000000..6f810eb
--- /dev/null
+++ b/plugins/kaitai/rost/core.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.h - prototypes pour la mise à disposition d'un support Kaitai pour ROST
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_ROST_CORE_H
+#define _PLUGINS_KAITAI_ROST_CORE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Intègre un support de Kaitai pour ROST. */
+bool add_kaitai_support_to_rost(void);
+
+
+
+#endif /* _PLUGINS_KAITAI_ROST_CORE_H */
diff --git a/plugins/kaitai/rost/space-int.h b/plugins/kaitai/rost/space-int.h
new file mode 100644
index 0000000..47ec707
--- /dev/null
+++ b/plugins/kaitai/rost/space-int.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * space-int.h - prototypes internes pour la définition d'un espace de noms pour les fonctions de scan
+ *
+ * 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 _PLUGINS_KAITAI_ROST_SPACE_INT_H
+#define _PLUGINS_KAITAI_ROST_SPACE_INT_H
+
+
+#include "space.h"
+
+
+#include <analysis/scan/space-int.h>
+
+
+
+/* Espace de noms avec chargement dynamique de définitions Kaitai (instance) */
+struct _GKaitaiNamespace
+{
+ GScanNamespace parent; /* A laisser en premier */
+
+};
+
+/* Espace de noms avec chargement dynamique de définitions Kaitai (classe) */
+struct _GKaitaiNamespaceClass
+{
+ GScanNamespaceClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un nouvel espace de noms pour scan. */
+bool g_kaitai_namespace_create(GKaitaiNamespace *);
+
+
+
+#endif /* _PLUGINS_KAITAI_ROST_SPACE_INT_H */
diff --git a/plugins/kaitai/rost/space.c b/plugins/kaitai/rost/space.c
new file mode 100644
index 0000000..ed24562
--- /dev/null
+++ b/plugins/kaitai/rost/space.c
@@ -0,0 +1,240 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * space.c - définition d'un espace de noms pour les fonctions de scan
+ *
+ * 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/>.
+ */
+
+
+#include "space.h"
+
+
+#include <string.h>
+
+
+#include "space-int.h"
+
+
+
+/* ------------------------- SOCLE POUR LES ESPACES DE NOMS ------------------------- */
+
+
+/* Initialise la classe des espaces de noms dynamiques Kaitai. */
+static void g_kaitai_namespace_class_init(GKaitaiNamespaceClass *);
+
+/* Initialise une instance d'espace de noms dynamiques Kaitai. */
+static void g_kaitai_namespace_init(GKaitaiNamespace *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_namespace_dispose(GKaitaiNamespace *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_namespace_finalize(GKaitaiNamespace *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Lance une résolution d'élément à solliciter. */
+static bool g_kaitai_namespace_resolve(GKaitaiNamespace *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* SOCLE POUR LES ESPACES DE NOMS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une définition d'espace de noms dynamique Kaitai. */
+G_DEFINE_TYPE(GKaitaiNamespace, g_kaitai_namespace, G_TYPE_SCAN_NAMESPACE);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des espaces de noms dynamiques Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_namespace_class_init(GKaitaiNamespaceClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_namespace_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_namespace_finalize;
+
+ registered = G_SCAN_REGISTERED_ITEM_CLASS(klass);
+
+ registered->resolve = (resolve_registered_item_fc)g_kaitai_namespace_resolve;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : space = instance à initialiser. *
+* *
+* Description : Initialise une instance d'espace de noms dynamiques Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_namespace_init(GKaitaiNamespace *space)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : space = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_namespace_dispose(GKaitaiNamespace *space)
+{
+ G_OBJECT_CLASS(g_kaitai_namespace_parent_class)->dispose(G_OBJECT(space));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : space = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_namespace_finalize(GKaitaiNamespace *space)
+{
+ G_OBJECT_CLASS(g_kaitai_namespace_parent_class)->finalize(G_OBJECT(space));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un nouvel espace de noms dynamique pour Kaitai. *
+* *
+* Retour : Adresse de la structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanNamespace *g_kaitai_namespace_new(void)
+{
+ GScanNamespace *result; /* Instance à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_NAMESPACE, NULL);
+
+ if (!g_kaitai_namespace_create(G_KAITAI_NAMESPACE(result)))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : space = instance d'espace de noms à initialiser. *
+* name = désignation du futur espace de noms. *
+* *
+* Description : Met en place un nouvel espace de noms pour scan. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_namespace_create(GKaitaiNamespace *space)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_scan_namespace_create(G_SCAN_NAMESPACE(space), "kaitai");
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* target = désignation de l'objet d'appel à identifier. *
+* 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 : Lance une résolution d'élément à solliciter. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_namespace_resolve(GKaitaiNamespace *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out)
+{
+ bool result; /* Bilan à retourner */
+ GScanRegisteredItemClass *parent; /* Version de classe parente */
+
+ parent = G_SCAN_REGISTERED_ITEM_CLASS(g_kaitai_namespace_parent_class);
+
+ result = parent->resolve(G_SCAN_REGISTERED_ITEM(item), target, ctx, scope, out);
+
+
+ if (!result)
+ printf("NEED external def!!!!\n");
+
+ return result;
+
+}
diff --git a/plugins/kaitai/rost/space.h b/plugins/kaitai/rost/space.h
new file mode 100644
index 0000000..5dcea5e
--- /dev/null
+++ b/plugins/kaitai/rost/space.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * space.h - prototypes pour la définition d'un espace de noms pour les fonctions de scan
+ *
+ * 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 _PLUGINS_KAITAI_ROST_SPACE_H
+#define _PLUGINS_KAITAI_ROST_SPACE_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include <analysis/scan/space.h>
+
+
+
+#define G_TYPE_KAITAI_NAMESPACE g_kaitai_namespace_get_type()
+#define G_KAITAI_NAMESPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_NAMESPACE, GKaitaiNamespace))
+#define G_IS_KAITAI_NAMESPACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_NAMESPACE))
+#define G_KAITAI_NAMESPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_NAMESPACE, GKaitaiNamespaceClass))
+#define G_IS_KAITAI_NAMESPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_NAMESPACE))
+#define G_KAITAI_NAMESPACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_NAMESPACE, GKaitaiNamespaceClass))
+
+
+/* Espace de noms avec chargement dynamique de définitions Kaitai (instance) */
+typedef struct _GKaitaiNamespace GKaitaiNamespace;
+
+/* Espace de noms avec chargement dynamique de définitions Kaitai (classe) */
+typedef struct _GKaitaiNamespaceClass GKaitaiNamespaceClass;
+
+
+/* Indique le type défini pour une définition d'espace de noms dynamique Kaitai. */
+GType g_kaitai_namespace_get_type(void);
+
+/* Construit un nouvel espace de noms dynamique pour Kaitai. */
+GScanNamespace *g_kaitai_namespace_new(void);
+
+
+
+#endif /* _PLUGINS_KAITAI_ROST_SPACE_H */
diff --git a/plugins/kaitai/rost/trigger-int.h b/plugins/kaitai/rost/trigger-int.h
new file mode 100644
index 0000000..6830cd7
--- /dev/null
+++ b/plugins/kaitai/rost/trigger-int.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * trigger-int.h - prototypes internes pour l'accès à des définitions Kaitai depuis ROST
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_KAITAI_ROST_TRIGGER_INT_H
+#define _PLUGINS_KAITAI_ROST_TRIGGER_INT_H
+
+
+#include <analysis/scan/item-int.h>
+
+
+#include "trigger.h"
+
+
+
+/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (instance) */
+struct _GKaitaiTrigger
+{
+ GScanRegisteredItem parent; /* A laisser en premier */
+
+ char *name; /* Désignation arbitraire */
+
+ GKaitaiStruct *kstruct; /* Définition à décliner */
+
+};
+
+/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (classe) */
+struct _GKaitaiTriggerClass
+{
+ GScanRegisteredItemClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un accès à une définition Kaitai pour ROST. */
+bool g_kaitai_trigger_create(GKaitaiTrigger *, GKaitaiStruct *);
+
+
+
+#endif /* _PLUGINS_KAITAI_ROST_TRIGGER_INT_H */
diff --git a/plugins/kaitai/rost/trigger.c b/plugins/kaitai/rost/trigger.c
new file mode 100644
index 0000000..64e6fe4
--- /dev/null
+++ b/plugins/kaitai/rost/trigger.c
@@ -0,0 +1,320 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * trigger.c - accès à des définitions Kaitai depuis ROST
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "trigger.h"
+
+
+#include <string.h>
+
+
+#include "browser.h"
+#include "trigger-int.h"
+
+
+
+/* ---------------------- ACCES ET DECLENCHEMENT D'UNE ANALYSE ---------------------- */
+
+
+/* Initialise la classe des accès aux définitions Kaitai. */
+static void g_kaitai_trigger_class_init(GKaitaiTriggerClass *);
+
+/* Initialise un accès à une définition Kaitai. */
+static void g_kaitai_trigger_init(GKaitaiTrigger *);
+
+/* Supprime toutes les références externes. */
+static void g_kaitai_trigger_dispose(GKaitaiTrigger *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_kaitai_trigger_finalize(GKaitaiTrigger *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique le nom associé à une expression d'évaluation. */
+static char *g_kaitai_trigger_get_name(const GKaitaiTrigger *);
+
+/* Lance une résolution d'élément à solliciter. */
+static bool g_kaitai_trigger_resolve(GKaitaiTrigger *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* ACCES ET DECLENCHEMENT D'UNE ANALYSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un accès à une définition Kaitai pour ROST. */
+G_DEFINE_TYPE(GKaitaiTrigger, g_kaitai_trigger, G_TYPE_SCAN_REGISTERED_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des accès aux définitions Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_trigger_class_init(GKaitaiTriggerClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanRegisteredItemClass *registered; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_trigger_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_kaitai_trigger_finalize;
+
+ registered = G_SCAN_REGISTERED_ITEM_CLASS(klass);
+
+ registered->get_name = (get_registered_item_name_fc)g_kaitai_trigger_get_name;
+ registered->resolve = (resolve_registered_item_fc)g_kaitai_trigger_resolve;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : trigger = instance à initialiser. *
+* *
+* Description : Initialise un accès à une définition Kaitai. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_trigger_init(GKaitaiTrigger *trigger)
+{
+ trigger->name = NULL;
+
+ trigger->kstruct = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : trigger = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_trigger_dispose(GKaitaiTrigger *trigger)
+{
+ g_clear_object(&trigger->kstruct);
+
+ G_OBJECT_CLASS(g_kaitai_trigger_parent_class)->dispose(G_OBJECT(trigger));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : trigger = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_kaitai_trigger_finalize(GKaitaiTrigger *trigger)
+{
+ if (trigger->name != NULL)
+ free(trigger->name);
+
+ G_OBJECT_CLASS(g_kaitai_trigger_parent_class)->finalize(G_OBJECT(trigger));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : kstruct = définition Kaitai à manipuler avec du contenu. *
+* *
+* Description : Crée un nouvel accès à une définition Kaitai à instancier. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GKaitaiTrigger *g_kaitai_trigger_new(GKaitaiStruct *kstruct)
+{
+ GKaitaiTrigger *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_KAITAI_TRIGGER, NULL);
+
+ if (!g_kaitai_trigger_create(result, kstruct))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : trigger = lien vers une définition Kaitai à instancier. *
+* kstruct = définition Kaitai à manipuler avec du contenu. *
+* *
+* Description : Met en place un accès à une définition Kaitai pour ROST. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_kaitai_trigger_create(GKaitaiTrigger *trigger, GKaitaiStruct *kstruct)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ trigger->kstruct = kstruct;
+ g_object_ref(G_OBJECT(trigger->kstruct));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : trigger = é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_kaitai_trigger_get_name(const GKaitaiTrigger *trigger)
+{
+ char *result; /* Désignation à retourner */
+ GKaitaiMeta *meta; /* Eventuelles métadonnées */
+ const char *id; /* Identifiant de définition */
+
+ if (trigger->name != NULL)
+ result = strdup(trigger->name);
+
+ else
+ {
+ result = NULL;
+
+ meta = g_kaitai_structure_get_meta(trigger->kstruct);
+ if (meta == NULL) goto done;
+
+ id = g_kaitai_meta_get_id(meta);
+ if (id == NULL) goto done;
+
+ result = strdup(id);
+
+ g_object_unref(G_OBJECT(meta));
+
+ done:
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* target = désignation de l'objet d'appel à identifier. *
+* 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 : Lance une résolution d'élément à solliciter. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_kaitai_trigger_resolve(GKaitaiTrigger *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out)
+{
+ bool result; /* Bilan à retourner */
+ GKaitaiBrowser *browser; /* Navigateur pour résultats */
+ GBinContent *content; /* Contenu binaire à analyser */
+ GMatchRecord *record; /* Premier niveau de résultats */
+
+ browser = g_object_get_data(G_OBJECT(item), "kaitai_browser");
+
+ if (browser == NULL)
+ {
+ content = g_scan_context_get_content(ctx);
+
+ record = g_kaitai_structure_parse(item->kstruct, content);
+
+ g_object_unref(G_OBJECT(content));
+
+ if (record != NULL)
+ {
+ browser = g_kaitai_browser_new(NULL, record);
+
+ g_object_set_data_full(G_OBJECT(item), "kaitai_browser", browser, g_object_unref);
+
+ }
+
+ }
+
+ if (browser == NULL)
+ result = false;
+
+ else
+ result = g_scan_registered_item_resolve(G_SCAN_REGISTERED_ITEM(browser), target, ctx, scope, out);
+
+ return result;
+
+}
diff --git a/plugins/kaitai/rost/trigger.h b/plugins/kaitai/rost/trigger.h
new file mode 100644
index 0000000..3de2e8d
--- /dev/null
+++ b/plugins/kaitai/rost/trigger.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * trigger.h - prototypes pour l'accès à des définitions Kaitai depuis ROST
+ *
+ * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef PLUGINS_KAITAI_ROST_TRIGGER_H
+#define PLUGINS_KAITAI_ROST_TRIGGER_H
+
+
+#include <glib-object.h>
+
+
+#include "../parsers/struct.h"
+
+
+
+#define G_TYPE_KAITAI_TRIGGER g_kaitai_trigger_get_type()
+#define G_KAITAI_TRIGGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_TRIGGER, GKaitaiTrigger))
+#define G_IS_KAITAI_TRIGGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_TRIGGER))
+#define G_KAITAI_TRIGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_TRIGGER, GKaitaiTriggerClass))
+#define G_IS_KAITAI_TRIGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_TRIGGER))
+#define G_KAITAI_TRIGGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_TRIGGER, GKaitaiTriggerClass))
+
+
+/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (instance) */
+typedef struct _GKaitaiTrigger GKaitaiTrigger;
+
+/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (classe) */
+typedef struct _GKaitaiTriggerClass GKaitaiTriggerClass;
+
+
+/* Indique le type défini pour un accès à une définition Kaitai pour ROST. */
+GType g_kaitai_trigger_get_type(void);
+
+/* Crée un nouvel accès à une définition Kaitai à instancier. */
+GKaitaiTrigger *g_kaitai_trigger_new(GKaitaiStruct *);
+
+
+
+#endif /* PLUGINS_KAITAI_ROST_TRIGGER_H */
diff --git a/plugins/pychrysalide/analysis/scan/space.c b/plugins/pychrysalide/analysis/scan/space.c
index c901cd9..6ea87b8 100644
--- a/plugins/pychrysalide/analysis/scan/space.c
+++ b/plugins/pychrysalide/analysis/scan/space.c
@@ -185,7 +185,7 @@ PyTypeObject *get_python_scan_namespace_type(void)
.tp_name = "pychrysalide.analysis.scan.ScanNamespace",
.tp_basicsize = sizeof(PyGObject),
- .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.tp_doc = SCAN_NAMESPACE_DOC,
diff --git a/src/analysis/scan/exprs/Makefile.am b/src/analysis/scan/exprs/Makefile.am
index a0b2f3d..37f4133 100644
--- a/src/analysis/scan/exprs/Makefile.am
+++ b/src/analysis/scan/exprs/Makefile.am
@@ -11,6 +11,8 @@ libanalysisscanexprs_la_SOURCES = \
call.h call.c \
counter-int.h \
counter.h counter.c \
+ extract-int.h \
+ extract.h extract.c \
handler-int.h \
handler.h handler.c \
intersect-int.h \
diff --git a/src/analysis/scan/exprs/call.c b/src/analysis/scan/exprs/call.c
index 74e0cba..e335933 100644
--- a/src/analysis/scan/exprs/call.c
+++ b/src/analysis/scan/exprs/call.c
@@ -271,9 +271,9 @@ static ScanReductionState g_scan_pending_call_reduce(const GScanPendingCall *exp
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 */
+ GScanExpression *new_next; /* Nouvelle version du suivant */
access = G_SCAN_NAMED_ACCESS(expr);
diff --git a/src/analysis/scan/exprs/extract-int.h b/src/analysis/scan/exprs/extract-int.h
new file mode 100644
index 0000000..562e537
--- /dev/null
+++ b/src/analysis/scan/exprs/extract-int.h
@@ -0,0 +1,57 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * extract-int.h - prototypes internes pour l'organisation d'une extraction d'un élément d'une série interne
+ *
+ * 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_EXTRACT_INT_H
+#define _ANALYSIS_SCAN_EXPRS_EXTRACT_INT_H
+
+
+#include "extract.h"
+
+
+#include "access-int.h"
+
+
+
+/* Extraction d'un élément donné au sein d'une série interne (instance) */
+struct _GScanPendingExtraction
+{
+ GScanNamedAccess parent; /* A laisser en premier */
+
+ GScanExpression *index; /* Arguments d'appel fournis */
+
+};
+
+/* Extraction d'un élément donné au sein d'une série interne (classe) */
+struct _GScanPendingExtractionClass
+{
+ GScanNamedAccessClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une expression d'extraction d'élément interne. */
+bool g_scan_pending_extraction_create(GScanPendingExtraction *, const sized_string_t *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_EXTRACT_INT_H */
diff --git a/src/analysis/scan/exprs/extract.c b/src/analysis/scan/exprs/extract.c
new file mode 100644
index 0000000..b140ed9
--- /dev/null
+++ b/src/analysis/scan/exprs/extract.c
@@ -0,0 +1,396 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * extract.c - organisation d'une extraction d'un élément d'une série interne
+ *
+ * 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 "extract.h"
+
+
+#include <assert.h>
+#include <string.h>
+
+
+#include "extract-int.h"
+#include "../../../core/global.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des extractions d'éléments internes. */
+static void g_scan_pending_extraction_class_init(GScanPendingExtractionClass *);
+
+/* Initialise une instance d'extraction d'élément interne. */
+static void g_scan_pending_extraction_init(GScanPendingExtraction *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_pending_extraction_dispose(GScanPendingExtraction *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_pending_extraction_finalize(GScanPendingExtraction *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_pending_extraction_reduce(const GScanPendingExtraction *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Reproduit un accès en place dans une nouvelle instance. */
+static void g_scan_pending_extraction_copy(GScanPendingExtraction *, const GScanPendingExtraction *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une extraction d'élément de série interne. */
+G_DEFINE_TYPE(GScanPendingExtraction, g_scan_pending_extraction, G_TYPE_SCAN_NAMED_ACCESS);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des extractions d'éléments internes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pending_extraction_class_init(GScanPendingExtractionClass *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_scan_pending_extraction_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_pending_extraction_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->cmp_rich = (compare_expr_rich_fc)NULL;
+ expr->reduce = (reduce_expr_fc)g_scan_pending_extraction_reduce;
+
+ access = G_SCAN_NAMED_ACCESS_CLASS(klass);
+
+ access->copy = (copy_scan_access_fc)g_scan_pending_extraction_copy;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : extract = instance à initialiser. *
+* *
+* Description : Initialise une instance d'extraction d'élément interne. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pending_extraction_init(GScanPendingExtraction *extract)
+{
+ extract->index = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : extract = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pending_extraction_dispose(GScanPendingExtraction *extract)
+{
+ g_clear_object(&extract->index);
+
+ G_OBJECT_CLASS(g_scan_pending_extraction_parent_class)->dispose(G_OBJECT(extract));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : extract = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pending_extraction_finalize(GScanPendingExtraction *extract)
+{
+ G_OBJECT_CLASS(g_scan_pending_extraction_parent_class)->finalize(G_OBJECT(extract));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : target = désignation de l'objet d'appel à identifier. *
+* index = indice de l'élément à extraire. *
+* *
+* Description : Organise l'extraction d'un élément d'une série interne. *
+* *
+* Retour : Fonction mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_pending_extraction_new(const sized_string_t *target, GScanExpression *index)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_PENDING_EXTRACTION, NULL);
+
+ if (!g_scan_pending_extraction_create(G_SCAN_PENDING_EXTRACTION(result), target, index))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : extract = instance à initialiser pleinement. *
+* target = désignation de l'objet d'appel à identifier. *
+* index = indice de l'élément à extraire. *
+* *
+* Description : Met en place une expression d'extraction d'élément interne. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_pending_extraction_create(GScanPendingExtraction *extract, const sized_string_t *target, GScanExpression *index)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_scan_named_access_create(G_SCAN_NAMED_ACCESS(extract), target);
+ if (!result) goto exit;
+
+ extract->index = index;
+ g_object_ref(G_OBJECT(index));
+
+ exit:
+
+ 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_pending_extraction_reduce(const GScanPendingExtraction *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanNamedAccess *access; /* Autre vision de l'expression*/
+ GScanRegisteredItem *resolved; /* Cible concrète obtenue */
+ GScanExpression *new; /* Nouvelle réduction obtenue */
+ GObject *final; /* Expression ou élément ? */
+ GScanExpression *new_next; /* Nouvelle version du suivant */
+
+ access = G_SCAN_NAMED_ACCESS(expr);
+
+ resolved = _g_scan_named_access_prepare_reduction(access, ctx, scope);
+
+ if (resolved == NULL)
+ result = SRS_UNRESOLVABLE;
+
+ else
+ {
+ /* Actualisation nécessaire des arguments ? */
+
+ result = g_scan_expression_reduce(expr->index, ctx, scope, &new);
+
+ /* Suite des traitements */
+
+ if (result == SRS_WAIT_FOR_SCAN)
+ {
+ /**
+ * Si changement il y a eu...
+ */
+ if (new != expr->index)
+ {
+ *out = g_scan_pending_extraction_new(NULL, new);
+
+ /**
+ * 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_REDUCED)
+ {
+ final = g_scan_registered_item_extract_at(resolved, new, ctx, scope);
+
+ if (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_SCAN_REGISTERED_ITEM(final))
+ {
+ if (access->next != NULL)
+ result = SRS_UNRESOLVABLE;
+
+ else
+ {
+ *out = G_SCAN_EXPRESSION(final);
+ g_object_ref(G_OBJECT(final));
+
+ result = SRS_REDUCED;
+
+ }
+
+ }
+ else
+ {
+ if (access->next != NULL)
+ {
+ new_next = g_scan_named_access_duplicate(access->next, G_SCAN_REGISTERED_ITEM(final));
+
+ result = g_scan_expression_reduce(new_next, ctx, scope, out);
+
+ g_object_unref(G_OBJECT(new_next));
+
+ }
+
+ /**
+ * Le cas ci-après est typique de l'extension Kaitai : field[n]
+ * renvoie vers une instance GScanRegisteredItem (GKaitaiBrowser).
+ *
+ * Il n'y a donc pas d'expression en jeu, et l'élément est le dernier
+ * de la liste.
+ */
+ else
+ {
+ if (g_scan_registered_item_reduce(G_SCAN_REGISTERED_ITEM(final), ctx, scope, out))
+ result = SRS_REDUCED;
+ else
+ result = SRS_UNRESOLVABLE;
+
+ }
+
+ }
+
+ }
+
+ else
+ result = SRS_UNRESOLVABLE;
+
+ g_clear_object(&final);
+
+ }
+
+ /* Libération locale des arguments reconstruits */
+
+ g_clear_object(&new);
+
+ 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_extraction_copy(GScanPendingExtraction *dest, const GScanPendingExtraction *src)
+{
+ GScanNamedAccessClass *class; /* Classe parente à solliciter */
+
+ class = G_SCAN_NAMED_ACCESS_CLASS(g_scan_pending_extraction_parent_class);
+
+ class->copy(G_SCAN_NAMED_ACCESS(dest), G_SCAN_NAMED_ACCESS(src));
+
+ dest->index = src->index;
+ g_object_ref(G_OBJECT(src->index));
+
+}
diff --git a/src/analysis/scan/exprs/extract.h b/src/analysis/scan/exprs/extract.h
new file mode 100644
index 0000000..8ed1cfa
--- /dev/null
+++ b/src/analysis/scan/exprs/extract.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * extract.h - prototypes pour l'organisation d'une extraction d'un élément d'une série interne
+ *
+ * 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_EXTRACT_H
+#define _ANALYSIS_SCAN_EXPRS_EXTRACT_H
+
+
+#include "../expr.h"
+#include "../../../common/szstr.h"
+
+
+
+#define G_TYPE_SCAN_PENDING_EXTRACTION g_scan_pending_extraction_get_type()
+#define G_SCAN_PENDING_EXTRACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_PENDING_EXTRACTION, GScanPendingExtraction))
+#define G_IS_SCAN_PENDING_EXTRACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_PENDING_EXTRACTION))
+#define G_SCAN_PENDING_EXTRACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_PENDING_EXTRACTION, GScanPendingExtractionClass))
+#define G_IS_SCAN_PENDING_EXTRACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_PENDING_EXTRACTION))
+#define G_SCAN_PENDING_EXTRACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_PENDING_EXTRACTION, GScanPendingExtractionClass))
+
+
+/* Extraction d'un élément donné au sein d'une série interne (instance) */
+typedef struct _GScanPendingExtraction GScanPendingExtraction;
+
+/* Extraction d'un élément donné au sein d'une série interne (classe) */
+typedef struct _GScanPendingExtractionClass GScanPendingExtractionClass;
+
+
+/* Indique le type défini pour une extraction d'élément de série interne. */
+GType g_scan_pending_extraction_get_type(void);
+
+/* Organise l'extraction d'un élément d'une série interne. */
+GScanExpression *g_scan_pending_extraction_new(const sized_string_t *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_EXTRACT_H */
diff --git a/src/analysis/scan/grammar.y b/src/analysis/scan/grammar.y
index c63dda7..2863e21 100644
--- a/src/analysis/scan/grammar.y
+++ b/src/analysis/scan/grammar.y
@@ -31,6 +31,7 @@ typedef void *yyscan_t;
#include "exprs/arithmetic.h"
#include "exprs/call.h"
#include "exprs/counter.h"
+#include "exprs/extract.h"
#include "exprs/handler.h"
#include "exprs/intersect.h"
#include "exprs/item.h"
@@ -274,7 +275,8 @@ YY_DECL;
%type <expr> cexpression _cexpression
%type <expr> literal
-%type <expr> item_chain
+%type <expr> chain_items
+%type <expr> chain_item
%type <args_list> call_args
%type <expr> logical_expr
%type <expr> relational_expr
@@ -285,9 +287,9 @@ YY_DECL;
%type <expr> pattern_set_items
%type <expr> set
%type <expr> set_items
-%type <expr> set_access
%type <expr> intersection
%type <expr> pattern_handler
+%type <expr> _pattern_handler
@@ -942,14 +944,13 @@ YY_DECL;
cexpression : _cexpression { $$ = $1; if ($$ == NULL) { printf("ERROR !!!\n"); YYERROR; } }
_cexpression : literal { $$ = $1; }
- | item_chain { $$ = $1; }
+ | chain_items { $$ = $1; }
| logical_expr { $$ = $1; }
| relational_expr { $$ = $1; }
| string_op { $$ = $1; }
| arithm_expr { $$ = $1; }
| set_match_counter { $$ = $1; }
| set { $$ = $1; }
- | set_access { $$ = $1; }
| intersection { $$ = $1; }
| pattern_handler { $$ = $1; }
| "(" cexpression ")" { $$ = $2; }
@@ -993,42 +994,48 @@ YY_DECL;
{
$$ = g_scan_literal_expression_new(LVT_STRING, &$1);
}
+ | STRING "[" cexpression "]"
+ {
+ GScanExpression *__src;
+ __src = g_scan_literal_expression_new(LVT_STRING, &$1);
+ $$ = g_scan_set_item_new(__src, $3);
+ g_object_unref(G_OBJECT(__src));
+ g_object_unref(G_OBJECT($3));
+ }
;
- item_chain : NAME { $$ = g_scan_named_access_new(&$1); }
- | NAME "(" ")" { $$ = g_scan_pending_call_new(&$1, NULL, 0); }
- | NAME "(" call_args ")"
+
+ chain_items : chain_item
{
- 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);
+ $$ = $1;
}
- | item_chain "." NAME
+ | chain_items "." chain_item
{
- 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));
+ g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS($1), G_SCAN_NAMED_ACCESS($3));
$$ = $1;
}
- | item_chain "." NAME "(" ")"
+ ;
+
+ chain_item : NAME
+ {
+ $$ = g_scan_named_access_new(&$1);
+ }
+ | 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;
+ $$ = g_scan_pending_call_new(&$1, NULL, 0);
}
- | item_chain "." NAME "(" call_args ")"
+ | 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;
+ $$ = 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);
+ }
+ | NAME "[" cexpression "]"
+ {
+ $$ = g_scan_pending_extraction_new(&$1, $3);
+ g_object_unref(G_OBJECT($3));
}
;
@@ -1307,46 +1314,39 @@ relational_expr : cexpression "<" cexpression { $$ = g_scan_relational_operatio
;
- 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));
- }
- ;
+ 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_access : cexpression "[" cexpression "]"
+ set_items : cexpression "," cexpression
{
- $$ = g_scan_set_item_new($1, $3);
+ $$ = 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);
@@ -1355,7 +1355,20 @@ relational_expr : cexpression "<" cexpression { $$ = g_scan_relational_operatio
}
;
- pattern_handler : BYTES_ID
+
+ pattern_handler : _pattern_handler
+ {
+ $$ = $1;
+ }
+ | pattern_handler "[" cexpression "]"
+ {
+ $$ = g_scan_set_item_new($1, $3);
+ g_object_unref(G_OBJECT($1));
+ g_object_unref(G_OBJECT($3));
+ }
+ ;
+
+ _pattern_handler : BYTES_ID
{
GSearchPattern *__pat;
__pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
diff --git a/src/analysis/scan/item-int.h b/src/analysis/scan/item-int.h
index 76431c9..a04b861 100644
--- a/src/analysis/scan/item-int.h
+++ b/src/analysis/scan/item-int.h
@@ -44,6 +44,9 @@ typedef bool (* reduce_registered_item_fc) (GScanRegisteredItem *, GScanContext
/* Effectue un appel à une fonction enregistrée. */
typedef bool (* run_registered_item_call_fc) (GScanRegisteredItem *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+/* Effectue une extraction d'élément à partir d'une série. */
+typedef GObject * (* extract_registered_item_at) (GScanRegisteredItem *, GScanExpression *, GScanContext *, GScanScope *);
+
/* Expression d'évaluation généraliste (instance) */
struct _GScanRegisteredItem
@@ -58,9 +61,11 @@ struct _GScanRegisteredItemClass
GObjectClass parent; /* A laisser en premier */
get_registered_item_name_fc get_name; /* Obtention du nom associé */
+
resolve_registered_item_fc resolve; /* Opération de résolution */
reduce_registered_item_fc reduce; /* Opération de réduction */
run_registered_item_call_fc run_call; /* Appel à une fonction connue */
+ extract_registered_item_at extract; /* Extraction d'un élément */
};
diff --git a/src/analysis/scan/item.c b/src/analysis/scan/item.c
index 930a334..509ad28 100644
--- a/src/analysis/scan/item.c
+++ b/src/analysis/scan/item.c
@@ -290,3 +290,36 @@ bool g_scan_registered_item_run_call(GScanRegisteredItem *item, GScanExpression
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = élément d'appel à consulter. *
+* index = indice de l'élément à cibler. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* *
+* Description : Effectue une extraction d'élément à partir d'une série. *
+* *
+* Retour : Elément de série obtenu ou NULL si erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GObject *g_scan_registered_item_extract_at(GScanRegisteredItem *item, GScanExpression *index, GScanContext *ctx, GScanScope *scope)
+{
+ GObject *result; /* Elément récupéré à renvoyer */
+ GScanRegisteredItemClass *class; /* Classe à activer */
+
+ class = G_SCAN_REGISTERED_ITEM_GET_CLASS(item);
+
+ if (class->extract == NULL)
+ result = NULL;
+
+ else
+ result = class->extract(item, index, ctx, scope);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/item.h b/src/analysis/scan/item.h
index 904064e..a6c56c3 100644
--- a/src/analysis/scan/item.h
+++ b/src/analysis/scan/item.h
@@ -64,6 +64,9 @@ bool g_scan_registered_item_reduce(GScanRegisteredItem *, GScanContext *, GScanS
/* Effectue un appel à une fonction enregistrée. */
bool g_scan_registered_item_run_call(GScanRegisteredItem *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **);
+/* Effectue une extraction d'élément à partir d'une série. */
+GObject *g_scan_registered_item_extract_at(GScanRegisteredItem *, GScanExpression *, GScanContext *, GScanScope *);
+
#endif /* _ANALYSIS_SCAN_ITEM_H */
diff --git a/src/analysis/scan/space.c b/src/analysis/scan/space.c
index e4d5049..909b96d 100644
--- a/src/analysis/scan/space.c
+++ b/src/analysis/scan/space.c
@@ -24,7 +24,6 @@
#include "space.h"
-#include <assert.h>
#include <string.h>
diff --git a/tests/plugins/kaitai/__init__.py b/tests/plugins/kaitai/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/plugins/kaitai/__init__.py
diff --git a/tests/plugins/kaitai/rost.py b/tests/plugins/kaitai/rost.py
new file mode 100644
index 0000000..1950222
--- /dev/null
+++ b/tests/plugins/kaitai/rost.py
@@ -0,0 +1,170 @@
+#!/usr/bin/python3-dbg
+# -*- coding: utf-8 -*-
+
+import locale
+
+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 pychrysalide import core
+from pychrysalide.plugins.kaitai.parsers import KaitaiStruct
+from pychrysalide.plugins.kaitai.rost import KaitaiTrigger
+
+
+class TestScansWithKaitai(ChrysalideTestCase):
+ """TestCase for ROST scan with the KaitaiStruct parsing."""
+
+ @classmethod
+ def setUpClass(cls):
+
+ super(TestScansWithKaitai, cls).setUpClass()
+
+ cls._options = ScanOptions()
+ cls._options.backend_for_data = AcismBackend
+
+
+ def ZZZtestSimpleKaitaiDefinitionForScanning(self):
+ """Rely on basic Kaitai simple definition for scanning."""
+
+ definitions = '''
+meta:
+ id: basic_test
+seq:
+ - id: field0
+ type: u1
+'''
+
+ kstruct = KaitaiStruct(definitions)
+
+ trigger = KaitaiTrigger(kstruct)
+
+ root_ns = core.get_rost_root_namespace()
+
+ ns = root_ns.resolve('kaitai')
+ ns.register_item(trigger)
+
+ ns = ns.resolve('basic_test')
+ self.assertEqual(ns, trigger)
+
+ cnt = MemoryContent(b'\x01\x02\x03')
+
+ rule = '''
+rule testing {
+
+ condition:
+ kaitai.basic_test.field0 == 1
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertIsNotNone(ctx)
+
+ self.assertFalse(ctx.has_match_for_rule('no_such_rule'))
+
+ self.assertTrue(ctx.has_match_for_rule('testing'))
+
+
+ definitions = '''
+meta:
+ id: other_basic_test
+seq:
+ - id: field0
+ type: u1
+ - id: field1
+ type: u1
+'''
+
+ kstruct = KaitaiStruct(definitions)
+
+ trigger = KaitaiTrigger(kstruct)
+
+ root_ns = core.get_rost_root_namespace()
+
+ ns = root_ns.resolve('kaitai')
+ ns.register_item(trigger)
+
+ ns = ns.resolve('other_basic_test')
+ self.assertEqual(ns, trigger)
+
+ cnt = MemoryContent(b'\x01\x02\x03')
+
+ rule = '''
+rule testing {
+
+ condition:
+ kaitai.other_basic_test.field0 == 1 and kaitai.other_basic_test.field1 == 2
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertIsNotNone(ctx)
+
+ self.assertTrue(ctx.has_match_for_rule('testing'))
+
+
+ rule = '''
+rule testing {
+
+ condition:
+ kaitai.other_basic_test.field0 == 1 and kaitai.other_basic_testXXXX.field1 == 2
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertIsNotNone(ctx)
+
+ self.assertFalse(ctx.has_match_for_rule('testing'))
+
+
+ def testKaitaiDefinitionWithListForScanning(self):
+ """Access list items from Kaitai definition when scanning with ROST."""
+
+ definitions = '''
+meta:
+ id: test_with_list
+seq:
+ - id: field0
+ type: u1
+ repeat: eos
+'''
+
+ kstruct = KaitaiStruct(definitions)
+
+ trigger = KaitaiTrigger(kstruct)
+
+ root_ns = core.get_rost_root_namespace()
+
+ ns = root_ns.resolve('kaitai')
+ ns.register_item(trigger)
+
+ ns = ns.resolve('test_with_list')
+ self.assertEqual(ns, trigger)
+
+ cnt = MemoryContent(b'\x01\x02\x03')
+
+ rule = '''
+rule testing {
+
+ condition:
+ kaitai.test_with_list.field0[0] == 1 and kaitai.test_with_list.field0[1] == 2 and kaitai.test_with_list.field0[2] == 3
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertIsNotNone(ctx)
+
+ self.assertTrue(ctx.has_match_for_rule('testing'))