/
githubmirror
/
libxmlb
Обзор
Документация
Войти
/
githubmirror
/
libxmlb
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/xb-common.c
168 строк
5 KB
Richard Hughes
Fix a potential out of bounds read when building a XbBuilderNode
31 июл 2026, 14:36
31 июл 2026, 14:36
d9dbfb1
Код
Авторство
О чём код?
/* * Copyright 2020 Richard Hughes <richard@hughsie.com> * * SPDX-License-Identifier: LGPL-2.1-or-later */ #define G_LOG_DOMAIN "XbCommon" #include "config.h" #include <string.h> #include "xb-common-private.h" static const gchar * xb_content_type_guess_from_fn(const gchar *filename) { gchar *ext; /* no ownership */ g_return_val_if_fail(filename != NULL, NULL); /* get file extension with dot */ ext = g_strrstr(filename, "."); if (ext == NULL) return NULL; /* map Windows "mime-type" to a content type */ if (g_strcmp0(ext, ".gz") == 0) return "application/gzip"; if (g_strcmp0(ext, ".xz") == 0) return "application/x-xz"; if (g_strcmp0(ext, ".zst") == 0) return "application/zstd"; if (g_strcmp0(ext, ".xml") == 0) return "application/xml"; if (g_strcmp0(ext, ".desktop") == 0) return "application/x-desktop"; if (g_strcmp0(ext, ".quirk") == 0) return "text/plain"; return NULL; } static gboolean xb_content_type_match(const guchar *buf, gsize bufsz, gsize offset, const gchar *magic, gsize magic_size) { /* document too small */ if (offset + magic_size > bufsz) return FALSE; return memcmp(buf + offset, magic, magic_size) == 0; } /** * xb_content_type_guess: (skip) * @filename: (nullable): filename * @buf: (nullable): file data buffer * @bufsz: size of file data buffer * * Guesses the content type based on example data. Either @filename or @buf may * be %NULL, in which case the guess will be based solely on the other argument. * * Returns: a string indicating a guessed content type **/ gchar * xb_content_type_guess(const gchar *filename, const guchar *buf, gsize bufsz) { g_autofree gchar *content_type = NULL; /* check for bad results, e.g. from Chrome OS */ content_type = g_content_type_guess(filename, buf, bufsz, NULL); if (g_strstr_len(content_type, -1, "/") == NULL || g_strcmp0(content_type, "application/octet-stream") == 0 || g_strcmp0(content_type, "text/plain") == 0) { /* magic */ if (bufsz > 0) { if (xb_content_type_match(buf, bufsz, 0x0, "\x1f\x8b", 2)) return g_strdup("application/gzip"); if (xb_content_type_match(buf, bufsz, 0x0, "\xfd\x37\x7a\x58\x5a\x00", 6)) return g_strdup("application/x-xz"); if (xb_content_type_match(buf, bufsz, 0x0, "\x28\xb5\x2f\xfd", 4)) return g_strdup("application/zstd"); if (xb_content_type_match(buf, bufsz, 0x0, "<?xml", 5)) return g_strdup("application/xml"); if (xb_content_type_match(buf, bufsz, 0x0, "[Desktop Entry]", 15)) return g_strdup("application/x-desktop"); } /* file extensions */ if (filename != NULL) { const gchar *tmp = xb_content_type_guess_from_fn(filename); if (tmp != NULL) return g_strdup(tmp); } } #ifdef _WIN32 /* fall back harder as there is no mime data at all */ if (filename != NULL) { const gchar *tmp = xb_content_type_guess_from_fn(filename); if (tmp != NULL) return g_strdup(tmp); } #endif return g_steal_pointer(&content_type); } /** * xb_file_set_contents: (skip) * @file: (nullable): file to write * @buf: (nullable): data buffer * @bufsz: size of @buf * @cancellable: (nullable): optional #GCancellable * @error: (nullable): optional return location for an error * * Writes data to a file. * * Returns: %TRUE for success **/ gboolean xb_file_set_contents(GFile *file, const guint8 *buf, gsize bufsz, GCancellable *cancellable, GError **error) { g_return_val_if_fail(G_IS_FILE(file), FALSE); g_return_val_if_fail(buf != NULL, FALSE); g_return_val_if_fail(cancellable == NULL || G_IS_CANCELLABLE(cancellable), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); return g_file_replace_contents(file, (const gchar *)buf, (gsize)bufsz, NULL, FALSE, G_FILE_CREATE_NONE, NULL, cancellable, error); } /** * xb_strsplit: * @str: (not nullable): a string to split * @sz: size of @str, which must be more than 0 * @delimiter: a string which specifies the places at which to split the string * @max_tokens: the maximum number of pieces to split @str into * * Splits a string into a maximum of @max_tokens pieces, using the given * delimiter. If @max_tokens is reached, the remainder of string is appended * to the last token. * * Returns: (transfer full): a newly-allocated NULL-terminated array of strings **/ gchar ** xb_strsplit(const gchar *str, gsize sz, const gchar *delimiter, gint max_tokens) { g_return_val_if_fail(str != NULL, NULL); g_return_val_if_fail(sz > 0, NULL); if (str[sz - 1] != '\0') { g_autofree gchar *str2 = g_strndup(str, sz); return g_strsplit(str2, delimiter, max_tokens); } return g_strsplit(str, delimiter, max_tokens); }