From 656ad4582cb1d7a7fa8bafe3ce8aec6aa3c17da0 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Thu, 16 Apr 2026 15:08:10 +0100 Subject: [PATCH 1/4] gdbusintrospection: Add some assertions before array dereferences MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The state handling inside the D-Bus introspection XML parser is complicated, and it’s possible that these dereferences of the `len - 1`th element might get reached when the array is empty. Make failures like that more debuggable by adding an assertion on the length beforehand. Signed-off-by: Philip Withnall Helps: #3932 --- gio/gdbusintrospection.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gio/gdbusintrospection.c b/gio/gdbusintrospection.c index df5daa32ce..1138ba9d75 100644 --- a/gio/gdbusintrospection.c +++ b/gio/gdbusintrospection.c @@ -1096,6 +1096,7 @@ parse_data_get_annotation (ParseData *data, { if (create_new) g_ptr_array_add (data->annotations, g_new0 (GDBusAnnotationInfo, 1)); + g_assert (data->annotations->len > 0); return data->annotations->pdata[data->annotations->len - 1]; } @@ -1105,6 +1106,7 @@ parse_data_get_arg (ParseData *data, { if (create_new) g_ptr_array_add (data->args, g_new0 (GDBusArgInfo, 1)); + g_assert (data->args->len > 0); return data->args->pdata[data->args->len - 1]; } @@ -1114,6 +1116,7 @@ parse_data_get_out_arg (ParseData *data, { if (create_new) g_ptr_array_add (data->out_args, g_new0 (GDBusArgInfo, 1)); + g_assert (data->out_args->len > 0); return data->out_args->pdata[data->out_args->len - 1]; } @@ -1123,6 +1126,7 @@ parse_data_get_method (ParseData *data, { if (create_new) g_ptr_array_add (data->methods, g_new0 (GDBusMethodInfo, 1)); + g_assert (data->methods->len > 0); return data->methods->pdata[data->methods->len - 1]; } @@ -1132,6 +1136,7 @@ parse_data_get_signal (ParseData *data, { if (create_new) g_ptr_array_add (data->signals, g_new0 (GDBusSignalInfo, 1)); + g_assert (data->signals->len > 0); return data->signals->pdata[data->signals->len - 1]; } @@ -1141,6 +1146,7 @@ parse_data_get_property (ParseData *data, { if (create_new) g_ptr_array_add (data->properties, g_new0 (GDBusPropertyInfo, 1)); + g_assert (data->properties->len > 0); return data->properties->pdata[data->properties->len - 1]; } @@ -1150,6 +1156,7 @@ parse_data_get_interface (ParseData *data, { if (create_new) g_ptr_array_add (data->interfaces, g_new0 (GDBusInterfaceInfo, 1)); + g_assert (data->interfaces->len > 0); return data->interfaces->pdata[data->interfaces->len - 1]; } @@ -1159,6 +1166,7 @@ parse_data_get_node (ParseData *data, { if (create_new) g_ptr_array_add (data->nodes, g_new0 (GDBusNodeInfo, 1)); + g_assert (data->nodes->len > 0); return data->nodes->pdata[data->nodes->len - 1]; } -- GitLab From 7b276f05f66cc0df609ba68f76b8a8f4cd5297cb Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Thu, 16 Apr 2026 15:17:48 +0100 Subject: [PATCH 2/4] tests: Improve D-Bus introspection test paths This makes them more consistent with how test paths are meant to be used. Signed-off-by: Philip Withnall --- gio/tests/gdbus-introspection.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gio/tests/gdbus-introspection.c b/gio/tests/gdbus-introspection.c index cb99c94108..f08847511a 100644 --- a/gio/tests/gdbus-introspection.c +++ b/gio/tests/gdbus-introspection.c @@ -313,10 +313,10 @@ main (int argc, /* all the tests rely on a shared main loop */ loop = g_main_loop_new (NULL, FALSE); - g_test_add_func ("/gdbus/introspection-parser", test_introspection_parser); - g_test_add_func ("/gdbus/introspection-generate", test_generate); - g_test_add_func ("/gdbus/introspection-default-direction", test_default_direction); - g_test_add_func ("/gdbus/introspection-extra-data", test_extra_data); + g_test_add_func ("/gdbus/introspection/parser", test_introspection_parser); + g_test_add_func ("/gdbus/introspection/generate", test_generate); + g_test_add_func ("/gdbus/introspection/default-direction", test_default_direction); + g_test_add_func ("/gdbus/introspection/extra-data", test_extra_data); ret = session_bus_run (); -- GitLab From c9da977c178fbfc0e4caf99f9fdf5dc433d6fcc2 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Thu, 16 Apr 2026 15:27:37 +0100 Subject: [PATCH 3/4] gdbusintrospection: Fix XML parser state handling for element nesting The check for whether a `` element in D-Bus introspection XML was nested correctly was broken. `` elements can only be at the top level, or nested immediately within another `` element. Fix the check and add some unit tests for it. Spotted by linhlhq as #YWH-PGM9867-204. The fix is mine, and the unit test uses example XML strings adapted from their report. Signed-off-by: Philip Withnall Fixes: #3932 --- gio/gdbusintrospection.c | 2 +- gio/tests/gdbus-introspection.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/gio/gdbusintrospection.c b/gio/gdbusintrospection.c index 1138ba9d75..4df8e87dba 100644 --- a/gio/gdbusintrospection.c +++ b/gio/gdbusintrospection.c @@ -1266,7 +1266,7 @@ parser_start_element (GMarkupParseContext *context, /* ---------------------------------------------------------------------------------------------------- */ if (strcmp (element_name, "node") == 0) { - if (!(g_slist_length (stack) >= 1 || strcmp (stack->next->data, "node") != 0)) + if (stack->next != NULL && strcmp (stack->next->data, "node") != 0) { g_set_error_literal (error, G_MARKUP_ERROR, diff --git a/gio/tests/gdbus-introspection.c b/gio/tests/gdbus-introspection.c index f08847511a..b755aae4be 100644 --- a/gio/tests/gdbus-introspection.c +++ b/gio/tests/gdbus-introspection.c @@ -300,6 +300,38 @@ test_extra_data (void) g_dbus_node_info_unref (info); } +static void +test_invalid (void) +{ + const struct + { + const char *xml; + GMarkupError expected_error_code; + } + vectors[] = + { + { "", G_MARKUP_ERROR_EMPTY }, + { "", G_MARKUP_ERROR_INVALID_CONTENT }, + { "", G_MARKUP_ERROR_INVALID_CONTENT }, + { "", G_MARKUP_ERROR_INVALID_CONTENT }, + { "", G_MARKUP_ERROR_INVALID_CONTENT }, + }; + + for (size_t i = 0; i < G_N_ELEMENTS (vectors); i++) + { + GDBusNodeInfo *node; + GError *local_error = NULL; + + g_test_message ("Testing parsing of %s gives an error", vectors[i].xml); + + node = g_dbus_node_info_new_for_xml (vectors[i].xml, &local_error); + g_assert_error (local_error, G_MARKUP_ERROR, (int) vectors[i].expected_error_code); + g_assert_null (node); + + g_clear_error (&local_error); + } +} + /* ---------------------------------------------------------------------------------------------------- */ int @@ -317,6 +349,7 @@ main (int argc, g_test_add_func ("/gdbus/introspection/generate", test_generate); g_test_add_func ("/gdbus/introspection/default-direction", test_default_direction); g_test_add_func ("/gdbus/introspection/extra-data", test_extra_data); + g_test_add_func ("/gdbus/introspection/invalid", test_invalid); ret = session_bus_run (); -- GitLab From 4b3e3b6b69ddbca73a888c53bd98ef6916a84490 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Sun, 19 Apr 2026 12:16:03 +0100 Subject: [PATCH 4/4] fuzzing: Add a fuzz test for g_dbus_node_info_new_for_xml() Signed-off-by: Philip Withnall Helps: #3932 --- fuzzing/fuzz_dbus_node_info_new_for_xml.c | 42 +++++++++++++++++++++++ fuzzing/meson.build | 1 + 2 files changed, 43 insertions(+) create mode 100644 fuzzing/fuzz_dbus_node_info_new_for_xml.c diff --git a/fuzzing/fuzz_dbus_node_info_new_for_xml.c b/fuzzing/fuzz_dbus_node_info_new_for_xml.c new file mode 100644 index 0000000000..e16c824ef4 --- /dev/null +++ b/fuzzing/fuzz_dbus_node_info_new_for_xml.c @@ -0,0 +1,42 @@ +/* + * Copyright 2026 Philip Withnall + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "fuzz.h" + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + char *nul_terminated_data = NULL; + GDBusNodeInfo *node = NULL; + GError *local_error = NULL; + + fuzz_set_logging_func (); + + /* ignore @size (g_dbus_node_info_new_for_xml() doesn’t support it); ensure @data is nul-terminated */ + nul_terminated_data = g_strndup ((const gchar *) data, size); + node = g_dbus_node_info_new_for_xml (nul_terminated_data, &local_error); + g_free (nul_terminated_data); + + g_assert ((node == NULL) == (local_error != NULL)); + + g_clear_pointer (&node, g_dbus_node_info_unref); + g_clear_error (&local_error); + + return 0; +} diff --git a/fuzzing/meson.build b/fuzzing/meson.build index b3a931c281..2738eee3ef 100644 --- a/fuzzing/meson.build +++ b/fuzzing/meson.build @@ -25,6 +25,7 @@ fuzz_targets = [ 'fuzz_date_parse', 'fuzz_date_time_new_from_iso8601', 'fuzz_dbus_message', + 'fuzz_dbus_node_info_new_for_xml', 'fuzz_filename_from_uri', 'fuzz_filename_to_uri', 'fuzz_get_locale_variants', -- GitLab