diff options
Diffstat (limited to 'plugins/kaitai/array.c')
-rw-r--r-- | plugins/kaitai/array.c | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/plugins/kaitai/array.c b/plugins/kaitai/array.c new file mode 100644 index 0000000..86f0856 --- /dev/null +++ b/plugins/kaitai/array.c @@ -0,0 +1,376 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * array.c - données associées à un flux de données Kaitai + * + * 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 "array.h" + + +#include <assert.h> +#include <limits.h> +#include <malloc.h> +#include <string.h> + + +#include "array-int.h" +#include "expression.h" + + + +/* Initialise la classe des flux de données pour Kaitai. */ +static void g_kaitai_array_class_init(GKaitaiArrayClass *); + +/* Initialise un flux de données accessibles à Kaitai. */ +static void g_kaitai_array_init(GKaitaiArray *); + +/* Supprime toutes les références externes. */ +static void g_kaitai_array_dispose(GKaitaiArray *); + +/* Procède à la libération totale de la mémoire. */ +static void g_kaitai_array_finalize(GKaitaiArray *); + +/* Détermine la taille de la séquence d'octets du tableau. */ +static bool g_kaitai_array_compute_bytes_length(const GKaitaiArray *, size_t *); + + + +/* Indique le type défini pour un tableau rassemblant des éléments Kaitai. */ +G_DEFINE_TYPE(GKaitaiArray, g_kaitai_array, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des tableau d'éléments Kaitai. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_array_class_init(GKaitaiArrayClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_array_dispose; + object->finalize = (GObjectFinalizeFunc)g_kaitai_array_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : array = instance à initialiser. * +* * +* Description : Initialise un tableau rassemblant des éléments divers. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_array_init(GKaitaiArray *array) +{ + array->items = NULL; + array->count = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : array = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_array_dispose(GKaitaiArray *array) +{ + G_OBJECT_CLASS(g_kaitai_array_parent_class)->dispose(G_OBJECT(array)); + +} + + +/****************************************************************************** +* * +* Paramètres : array = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_array_finalize(GKaitaiArray *array) +{ + G_OBJECT_CLASS(g_kaitai_array_parent_class)->finalize(G_OBJECT(array)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Constitue une amorce de tableau pour rassembler des éléments.* +* * +* Retour : Instance mise en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GKaitaiArray *g_kaitai_array_new(void) +{ + GKaitaiArray *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_KAITAI_ARRAY, NULL); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : array = tableau Kaitai à consulter. * +* * +* Description : Dénombre le nombre d'éléments enregistrés. * +* * +* Retour : Taille du tableau manipulé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_kaitai_array_count_items(const GKaitaiArray *array) +{ + size_t result; /* Quantité à retourner */ + + result = array->count; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : array = tableau Kaitai à compléter. * +* item = élément Kaitai à archiver. * +* * +* Description : Intègre un élément supplémentaire dans un tableau Kaitai. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_kaitai_array_append_item(GKaitaiArray *array, const resolved_value_t *item) +{ + array->items = realloc(array->items, ++array->count * sizeof(resolved_value_t)); + + COPY_RESOLVED_VALUE(array->items[array->count - 1], *item); + +} + + +/****************************************************************************** +* * +* Paramètres : list = ensemble de correspondances attribut/binaire. * +* index = indice de la correspondance visée. * +* item = élément archivé dans le talbeau à fournir. [OUT] * +* * +* Description : Fournit un élément ciblé dans un tableau Kaitai. * +* * +* Retour : Validité de l'emplacmeent pour élément à renseigner. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_kaitai_array_get_item(const GKaitaiArray *array, size_t index, resolved_value_t *item) +{ + bool result; /* Bilan à retourner */ + + result = (index < array->count); + + if (result) + COPY_RESOLVED_VALUE(*item, array->items[index]); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : array = tableau Kaitai à consulter. * +* length = nombre d'octets représentés. [OUT] * +* * +* Description : Détermine la taille de la séquence d'octets du tableau. * +* * +* Retour : true si le tableau peut être converti en octets, ou false. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_kaitai_array_compute_bytes_length(const GKaitaiArray *array, size_t *length) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + const resolved_value_t *item; /* Elément en cours d'analyse */ + size_t extra; /* Taille d'un sous-tableau */ + + result = true; + + *length = 0; + + for (i = 0; i < array->count && result; i++) + { + item = &array->items[i]; + + switch (item->type) + { + case GVT_UNSIGNED_INTEGER: + result = (item->unsigned_integer <= UCHAR_MAX); + if (result) (*length)++; + break; + + case GVT_SIGNED_INTEGER: + result = (0 <= item->signed_integer && item->signed_integer <= SCHAR_MAX); + if (result) (*length)++; + break; + + case GVT_BYTES: + *length += item->bytes.len; + break; + + case GVT_ARRAY: + result = g_kaitai_array_compute_bytes_length(item->array, &extra); + if (result) *length += extra; + break; + + default: + result = false; + break; + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : array = tableau Kaitai à consulter. * +* bytes = conversion en série d'octets équivalent. [OUT] * +* * +* Description : Convertit un tableau d'éléments en séquence d'octets. * +* * +* Retour : true si une série d'octets a pu être constituée, ou false. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_kaitai_array_convert_to_bytes(const GKaitaiArray *array, sized_string_t *bytes) +{ + bool result; /* Bilan à retourner */ + size_t length; /* Taille de la chaîne finale */ + size_t i; /* Boucle de parcours */ + const resolved_value_t *item; /* Elément en cours d'analyse */ + char *iter; /* Tête d'écriture */ + sized_string_t extra; /* Données d'un sous-tableau */ + + /* Détermination de la taille finale */ + + result = g_kaitai_array_compute_bytes_length(array, &length); + + /* Construction d'une chaîne d'octets si possible */ + + if (result) + { + bytes->data = malloc(length * sizeof(char)); + bytes->len = length; + + iter = bytes->data; + + for (i = 0; i < array->count; i++) + { + item = &array->items[i]; + + switch (item->type) + { + case GVT_UNSIGNED_INTEGER: + *iter = item->unsigned_integer; + iter++; + break; + + case GVT_SIGNED_INTEGER: + *iter = item->signed_integer; + iter++; + break; + + case GVT_BYTES: + memcpy(iter, item->bytes.data, item->bytes.len); + iter += item->bytes.len; + break; + + case GVT_ARRAY: + result = g_kaitai_array_convert_to_bytes(item->array, &extra); + assert(result); + + memcpy(iter, extra.data, extra.len); + iter += extra.len; + + exit_szstr(&extra); + break; + + default: + break; + + } + + } + + } + + return result; + +} |