From 7d63f9446c6c94740204492673e808d97ab54809 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Tue, 26 Apr 2022 11:50:23 +0100 Subject: [PATCH 01/38] gthread: Fix futex timespec type on 32-bit kernels with 64-bit userspace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `struct timespec` type documented as being passed to the `futex()` syscall actually needs to be the *kernel’s* timespec type. This will be a different width from the userspace timespec type if running a 64-bit userspace on a 32-bit kernel. That mismatch will cause `g_cond_wait_until()` to return `FALSE` immediately. No other uses of `futex()` in GLib use the timeout argument, so they’re all OK. Following a detailed suggestion by Rich Felker, pass a different timespec type into `futex()` if `__NR_futex_time64` is defined. That’s the 64-bit time version of `futex()` which was added in kernel 5.1, and which was only added for 32-bit kernels. Signed-off-by: Philip Withnall Fixes: #2634 (cherry-picked from commit eec65c761bb406beccf674e371ea38b231136707) --- glib/gthread-posix.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/glib/gthread-posix.c b/glib/gthread-posix.c index 8e2e66db5..8c403f975 100644 --- a/glib/gthread-posix.c +++ b/glib/gthread-posix.c @@ -1599,6 +1599,13 @@ g_cond_wait_until (GCond *cond, { struct timespec now; struct timespec span; +#ifdef __NR_futex_time64 + long span_arg[2]; + G_STATIC_ASSERT (sizeof (span_arg[0]) == 4); +#else + struct timespec span_arg; +#endif + guint sampled; int res; gboolean success; @@ -1618,9 +1625,33 @@ g_cond_wait_until (GCond *cond, if (span.tv_sec < 0) return FALSE; + /* On x32 (ILP32 ABI on x86_64) and potentially sparc64, the raw futex() + * syscall takes a 32-bit timespan argument *regardless* of whether userspace + * is using 32-bit or 64-bit `struct timespec`. This means that we can’t + * unconditionally pass a `struct timespec` pointer into the syscall. + * + * Assume that any such platform is new enough to define the + * `__NR_futex_time64` workaround syscall (which accepts 64-bit timespecs, + * introduced in kernel 5.1), and use that as a proxy for whether to pass in + * `long[2]` or `struct timespec`. + * + * As per https://lwn.net/Articles/776427/, the `time64` syscalls only exist + * on 32-bit platforms, so in this case `sizeof(long)` should always be + * 32 bits. + * + * Don’t bother actually calling `__NR_futex_time64` as the `span` is relative + * and hence very unlikely to overflow, even if using 32-bit longs. + */ +#ifdef __NR_futex_time64 + span_arg[0] = span.tv_sec; + span_arg[1] = span.tv_nsec; +#else + span_arg = span; +#endif + sampled = cond->i[0]; g_mutex_unlock (mutex); - res = syscall (__NR_futex, &cond->i[0], (gsize) FUTEX_WAIT_PRIVATE, (gsize) sampled, &span); + res = syscall (__NR_futex, &cond->i[0], (gsize) FUTEX_WAIT_PRIVATE, (gsize) sampled, &span_arg); success = (res < 0 && errno == ETIMEDOUT) ? FALSE : TRUE; g_mutex_lock (mutex); From e77f036cb677bf04963b1ef14d7e9dd3cac57c99 Mon Sep 17 00:00:00 2001 From: Hodong Date: Tue, 26 Apr 2022 18:54:57 +0900 Subject: [PATCH 02/38] Fix the annotation of g_utf8_strncpy() (cherry-picked from commit 797bcf3224ef87992c0a7eaa10d5bf888ad7120e) --- glib/gutf8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glib/gutf8.c b/glib/gutf8.c index a4368d5f1..bb9d6fba0 100644 --- a/glib/gutf8.c +++ b/glib/gutf8.c @@ -437,7 +437,7 @@ g_utf8_pointer_to_offset (const gchar *str, * must be valid UTF-8 encoded text. (Use g_utf8_validate() on all * text before trying to use UTF-8 utility functions with it.) * - * Note you must ensure @dest is at least 4 * @n to fit the + * Note you must ensure @dest is at least 4 * @n + 1 to fit the * largest possible UTF-8 characters * * Returns: (transfer none): @dest From aafa45e583d8998853ca97f35f89f34ddbfaca56 Mon Sep 17 00:00:00 2001 From: Sebastian Keller Date: Tue, 30 Aug 2022 21:39:36 +0200 Subject: [PATCH 03/38] documentportal: Fix small leak in add_documents with empty URI list When called with an empty URI list (or only inaccessible files), g_document_portal_add_documents would not call g_variant_builder_end, leaking the memory allocated by the variant builder. Closes: https://gitlab.gnome.org/GNOME/glib/-/issues/2733 (cherry-picked from commit 27203e48c91ab8b55033dcf1773cb60c0aaed3fa) --- gio/gdocumentportal.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gio/gdocumentportal.c b/gio/gdocumentportal.c index 644829a71..276a1dce6 100644 --- a/gio/gdocumentportal.c +++ b/gio/gdocumentportal.c @@ -201,6 +201,7 @@ g_document_portal_add_documents (GList *uris, else { ruris = g_list_copy_deep (uris, (GCopyFunc)g_strdup, NULL); + g_variant_builder_clear (&builder); } out: From ba9ed375e92be7c912d30944dd21ce7f55389fea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 2 Sep 2022 18:56:35 +0200 Subject: [PATCH 04/38] tests/dbus-appinfo: Add test case for flatpak opening an invalid file We were testing the case in which we were opening an actual file, and so potentially using a fd-list, however we were missing the case in which a file was not existent. And in such case we are incidentally hitting a leak now. (cherry-picked from commit 511627b7356af527c85c049e2020a36694d7de54) --- gio/tests/dbus-appinfo.c | 79 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/gio/tests/dbus-appinfo.c b/gio/tests/dbus-appinfo.c index 86bdfebee..f24e3a85a 100644 --- a/gio/tests/dbus-appinfo.c +++ b/gio/tests/dbus-appinfo.c @@ -358,6 +358,84 @@ test_flatpak_doc_export (void) g_object_unref (flatpak_appinfo); } +static void +on_flatpak_launch_invalid_uri_finish (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GApplication *app = user_data; + GError *error = NULL; + + g_app_info_launch_uris_finish (G_APP_INFO (object), result, &error); + g_assert_no_error (error); + + g_application_release (app); +} + +static void +on_flatpak_activate_invalid_uri (GApplication *app, + gpointer user_data) +{ + GDesktopAppInfo *flatpak_appinfo = user_data; + GList *uris; + + /* The app will be released in on_flatpak_launch_uris_finish */ + g_application_hold (app); + + uris = g_list_prepend (NULL, "file:///hopefully/an/invalid/path.desktop"); + g_app_info_launch_uris_async (G_APP_INFO (flatpak_appinfo), uris, NULL, + NULL, on_flatpak_launch_invalid_uri_finish, app); + g_list_free (uris); +} + +static void +on_flatpak_open_invalid_uri (GApplication *app, + GFile **files, + gint n_files, + const char *hint) +{ + GFile *f; + + g_assert_cmpint (n_files, ==, 1); + g_test_message ("on_flatpak_open received file '%s'", g_file_peek_path (files[0])); + + /* The file has been exported via the document portal */ + f = g_file_new_for_uri ("file:///hopefully/an/invalid/path.desktop"); + g_assert_true (g_file_equal (files[0], f)); + g_object_unref (f); +} + +static void +test_flatpak_missing_doc_export (void) +{ + const gchar *argv[] = { "myapp", NULL }; + gchar *desktop_file = NULL; + GDesktopAppInfo *flatpak_appinfo; + GApplication *app; + int status; + + g_test_summary ("Test that files launched via Flatpak apps are made available via the document portal."); + + desktop_file = g_test_build_filename (G_TEST_DIST, + "org.gtk.test.dbusappinfo.flatpak.desktop", + NULL); + flatpak_appinfo = g_desktop_app_info_new_from_filename (desktop_file); + g_assert_nonnull (flatpak_appinfo); + + app = g_application_new ("org.gtk.test.dbusappinfo.flatpak", + G_APPLICATION_HANDLES_OPEN); + g_signal_connect (app, "activate", G_CALLBACK (on_flatpak_activate_invalid_uri), + flatpak_appinfo); + g_signal_connect (app, "open", G_CALLBACK (on_flatpak_open_invalid_uri), NULL); + + status = g_application_run (app, 1, (gchar **) argv); + g_assert_cmpint (status, ==, 0); + + g_object_unref (app); + g_object_unref (flatpak_appinfo); + g_free (desktop_file); +} + int main (int argc, char **argv) { @@ -365,6 +443,7 @@ main (int argc, char **argv) g_test_add_func ("/appinfo/dbusappinfo", test_dbus_appinfo); g_test_add_func ("/appinfo/flatpak-doc-export", test_flatpak_doc_export); + g_test_add_func ("/appinfo/flatpak-missing-doc-export", test_flatpak_missing_doc_export); return session_bus_run (); } From 7c6ba9315111faf1275adfc28e36d4478d99697a Mon Sep 17 00:00:00 2001 From: Andy Holmes Date: Sun, 21 Aug 2022 15:52:38 -0700 Subject: [PATCH 05/38] gparamspec: mark nick/blurb as nullable GParamSpec nicks and blurbs are effectively a deprecated feature, or at least unused by most libraries these days. Since a number of C libraries (i.e. GTK4) have started to null these out, annotate them as `(nullable)` so bindings can do the same. Closes #2719 (cherry-picked from commit 79c70d7a362f4b793363275cbe37d3c08f7ea884) --- gobject/gparam.c | 15 ++++---- gobject/gparamspecs.c | 88 +++++++++++++++++++++---------------------- 2 files changed, 52 insertions(+), 51 deletions(-) diff --git a/gobject/gparam.c b/gobject/gparam.c index e9d9eacb0..d761d9275 100644 --- a/gobject/gparam.c +++ b/gobject/gparam.c @@ -423,8 +423,8 @@ g_param_spec_is_valid_name (const gchar *name) * g_param_spec_internal: (skip) * @param_type: the #GType for the property; must be derived from %G_TYPE_PARAM * @name: the canonical name of the property - * @nick: the nickname of the property - * @blurb: a short description of the property + * @nick: (nullable): the nickname of the property + * @blurb: (nullable): a short description of the property * @flags: a combination of #GParamFlags * * Creates a new #GParamSpec instance. @@ -433,11 +433,12 @@ g_param_spec_is_valid_name (const gchar *name) * the rules for @name. Names which violate these rules lead to undefined * behaviour. * - * Beyond the name, #GParamSpecs have two more descriptive - * strings associated with them, the @nick, which should be suitable - * for use as a label for the property in a property editor, and the - * @blurb, which should be a somewhat longer description, suitable for - * e.g. a tooltip. The @nick and @blurb should ideally be localized. + * Beyond the name, #GParamSpecs have two more descriptive strings, the + * @nick and @blurb, which may be used as a localized label and description. + * For GTK and related libraries these are considered deprecated and may be + * omitted, while for other libraries such as GStreamer and its plugins they + * are essential. When in doubt, follow the conventions used in the + * surrounding code and supporting libraries. * * Returns: (type GObject.ParamSpec): (transfer floating): a newly allocated * #GParamSpec instance, which is initially floating diff --git a/gobject/gparamspecs.c b/gobject/gparamspecs.c index d4ad8c21a..c937a6a44 100644 --- a/gobject/gparamspecs.c +++ b/gobject/gparamspecs.c @@ -1634,8 +1634,8 @@ _g_param_spec_types_init (void) /** * g_param_spec_char: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @minimum: minimum value for the property specified * @maximum: maximum value for the property specified * @default_value: default value for the property specified @@ -1676,8 +1676,8 @@ g_param_spec_char (const gchar *name, /** * g_param_spec_uchar: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @minimum: minimum value for the property specified * @maximum: maximum value for the property specified * @default_value: default value for the property specified @@ -1718,8 +1718,8 @@ g_param_spec_uchar (const gchar *name, /** * g_param_spec_boolean: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @default_value: default value for the property specified * @flags: flags for the property specified * @@ -1760,8 +1760,8 @@ g_param_spec_boolean (const gchar *name, /** * g_param_spec_int: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @minimum: minimum value for the property specified * @maximum: maximum value for the property specified * @default_value: default value for the property specified @@ -1804,8 +1804,8 @@ g_param_spec_int (const gchar *name, /** * g_param_spec_uint: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @minimum: minimum value for the property specified * @maximum: maximum value for the property specified * @default_value: default value for the property specified @@ -1848,8 +1848,8 @@ g_param_spec_uint (const gchar *name, /** * g_param_spec_long: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @minimum: minimum value for the property specified * @maximum: maximum value for the property specified * @default_value: default value for the property specified @@ -1892,8 +1892,8 @@ g_param_spec_long (const gchar *name, /** * g_param_spec_ulong: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @minimum: minimum value for the property specified * @maximum: maximum value for the property specified * @default_value: default value for the property specified @@ -1937,8 +1937,8 @@ g_param_spec_ulong (const gchar *name, /** * g_param_spec_int64: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @minimum: minimum value for the property specified * @maximum: maximum value for the property specified * @default_value: default value for the property specified @@ -1981,8 +1981,8 @@ g_param_spec_int64 (const gchar *name, /** * g_param_spec_uint64: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @minimum: minimum value for the property specified * @maximum: maximum value for the property specified * @default_value: default value for the property specified @@ -2026,8 +2026,8 @@ g_param_spec_uint64 (const gchar *name, /** * g_param_spec_unichar: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @default_value: default value for the property specified * @flags: flags for the property specified * @@ -2064,8 +2064,8 @@ g_param_spec_unichar (const gchar *name, /** * g_param_spec_enum: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @enum_type: a #GType derived from %G_TYPE_ENUM * @default_value: default value for the property specified * @flags: flags for the property specified @@ -2115,8 +2115,8 @@ g_param_spec_enum (const gchar *name, /** * g_param_spec_flags: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @flags_type: a #GType derived from %G_TYPE_FLAGS * @default_value: default value for the property specified * @flags: flags for the property specified @@ -2166,8 +2166,8 @@ g_param_spec_flags (const gchar *name, /** * g_param_spec_float: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @minimum: minimum value for the property specified * @maximum: maximum value for the property specified * @default_value: default value for the property specified @@ -2210,8 +2210,8 @@ g_param_spec_float (const gchar *name, /** * g_param_spec_double: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @minimum: minimum value for the property specified * @maximum: maximum value for the property specified * @default_value: default value for the property specified @@ -2255,8 +2255,8 @@ g_param_spec_double (const gchar *name, /** * g_param_spec_string: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @default_value: (nullable): default value for the property specified * @flags: flags for the property specified * @@ -2290,8 +2290,8 @@ g_param_spec_string (const gchar *name, /** * g_param_spec_param: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @param_type: a #GType derived from %G_TYPE_PARAM * @flags: flags for the property specified * @@ -2329,8 +2329,8 @@ g_param_spec_param (const gchar *name, /** * g_param_spec_boxed: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @boxed_type: %G_TYPE_BOXED derived type of this property * @flags: flags for the property specified * @@ -2369,8 +2369,8 @@ g_param_spec_boxed (const gchar *name, /** * g_param_spec_pointer: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @flags: flags for the property specified * * Creates a new #GParamSpecPointer instance specifying a pointer property. @@ -2403,8 +2403,8 @@ g_param_spec_pointer (const gchar *name, /** * g_param_spec_gtype: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @is_a_type: a #GType whose subtypes are allowed as values * of the property (use %G_TYPE_NONE for any type) * @flags: flags for the property specified @@ -2443,8 +2443,8 @@ g_param_spec_gtype (const gchar *name, /** * g_param_spec_value_array: (skip) * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @element_spec: a #GParamSpec describing the elements contained in * arrays of this property, may be %NULL * @flags: flags for the property specified @@ -2490,8 +2490,8 @@ g_param_spec_value_array (const gchar *name, /** * g_param_spec_object: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @object_type: %G_TYPE_OBJECT derived type of this property * @flags: flags for the property specified * @@ -2574,8 +2574,8 @@ g_param_spec_override (const gchar *name, /** * g_param_spec_variant: * @name: canonical name of the property specified - * @nick: nick name for the property specified - * @blurb: description of the property specified + * @nick: (nullable): nick name for the property specified + * @blurb: (nullable): description of the property specified * @type: a #GVariantType * @default_value: (nullable) (transfer full): a #GVariant of type @type to * use as the default value, or %NULL From 679a624600984d99bba5497d84d29b8412337f03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 15 Jun 2022 21:46:51 +0200 Subject: [PATCH 06/38] glib-unix: Mark GLib.unix_open_pipe fds input array as fixed-size (cherry-picked from commit 3a197d7500f20894f6832645502270b20d1e446a) --- glib/glib-unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glib/glib-unix.c b/glib/glib-unix.c index fd799eaf7..958a9f1f5 100644 --- a/glib/glib-unix.c +++ b/glib/glib-unix.c @@ -70,7 +70,7 @@ g_unix_set_error_from_errno (GError **error, /** * g_unix_open_pipe: - * @fds: Array of two integers + * @fds: (array fixed-size=2): Array of two integers * @flags: Bitfield of file descriptor flags, as for fcntl() * @error: a #GError * From b34b4ebe8cf2a134c93efc58a1800061d71aad2c Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 27 May 2022 14:27:12 +0100 Subject: [PATCH 07/38] garray: Add missing (transfer full) introspection annotations Signed-off-by: Philip Withnall (cherry-picked from commit a9321c365222c4fe0fe7a33e0d3c0a0cb635b318) --- glib/garray.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/glib/garray.c b/glib/garray.c index 1ab3beeda..739141e3d 100644 --- a/glib/garray.c +++ b/glib/garray.c @@ -1169,8 +1169,9 @@ g_ptr_array_new (void) * g_assert (chunk_buffer->len == 0); * ]| * - * Returns: (transfer full): the element data, which should be - * freed using g_free(). + * Returns: (transfer full) (nullable): the element data, which should be + * freed using g_free(). This may be %NULL if the array doesn’t have any + * elements (i.e. if `*len` is zero). * * Since: 2.64 */ @@ -1307,7 +1308,7 @@ g_array_copy (GArray *array) * either via g_ptr_array_unref(), when g_ptr_array_free() is called with * @free_segment set to %TRUE or when removing elements. * - * Returns: A new #GPtrArray + * Returns: (transfer full): A new #GPtrArray * * Since: 2.22 */ @@ -1331,7 +1332,7 @@ g_ptr_array_new_with_free_func (GDestroyNotify element_free_func) * g_ptr_array_unref(), when g_ptr_array_free() is called with * @free_segment set to %TRUE or when removing elements. * - * Returns: A new #GPtrArray + * Returns: (transfer full): A new #GPtrArray * * Since: 2.30 */ From ab47152bfa2549580856371d0ee0cce839a0d14f Mon Sep 17 00:00:00 2001 From: Tom Levy Date: Fri, 16 Sep 2022 08:25:46 +0000 Subject: [PATCH 08/38] docs: Improve wording in documentation of g_unix_signal_source_new() - Insert missing word "from". - Remove space between function name and "()" so syntax highlighting can recognise it as a function. - Avoid "you"/"your" when discussing the reentrancy issues of regular UNIX signal handlers, because it gives the false impression that these issues are applicable to g_unix_signal_source_new(). Unrelated: - Fix missing space in documentation of g_signal_new_class_handler(). (cherry-picked from commit eeaef8b950580dd76f1c87748e336453301bae9a) --- glib/glib-unix.c | 10 +++++----- gobject/gsignal.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/glib/glib-unix.c b/glib/glib-unix.c index 958a9f1f5..9a148cb8f 100644 --- a/glib/glib-unix.c +++ b/glib/glib-unix.c @@ -203,11 +203,11 @@ g_unix_set_fd_nonblocking (gint fd, * * For example, an effective use of this function is to handle `SIGTERM` * cleanly; flushing any outstanding files, and then calling - * g_main_loop_quit (). It is not safe to do any of this a regular - * UNIX signal handler; your handler may be invoked while malloc() or - * another library function is running, causing reentrancy if you - * attempt to use it from the handler. None of the GLib/GObject API - * is safe against this kind of reentrancy. + * g_main_loop_quit(). It is not safe to do any of this from a regular + * UNIX signal handler; such a handler may be invoked while malloc() or + * another library function is running, causing reentrancy issues if the + * handler attempts to use those functions. None of the GLib/GObject + * API is safe against this kind of reentrancy. * * The interaction of this source when combined with native UNIX * functions like sigprocmask() is not defined. diff --git a/gobject/gsignal.c b/gobject/gsignal.c index fb85fd6ba..1fafcae5d 100644 --- a/gobject/gsignal.c +++ b/gobject/gsignal.c @@ -1547,7 +1547,7 @@ g_signal_new (const gchar *signal_name, * an object definition, instead the function pointer is passed * directly and can be overridden by derived classes with * g_signal_override_class_closure() or - * g_signal_override_class_handler()and chained to with + * g_signal_override_class_handler() and chained to with * g_signal_chain_from_overridden() or * g_signal_chain_from_overridden_handler(). * From b918a257ff89a76bb865cdd0d7a7bebdb3eae231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 2 Sep 2022 20:34:21 +0200 Subject: [PATCH 09/38] gdesktopappinfo: Unref GDBus call result GVariant if no callback is set When launching URIs via dbus we may ignore the callback if one was not provided, however in such case we were also leaking the return value for the gdbus call. Unref it properly. Helps with: https://gitlab.gnome.org/GNOME/glib/-/issues/333 (cherry-picked from commit 026a69905eec18e9ea0486ea351496e461c8681e) --- gio/gdesktopappinfo.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c index 60d6debb2..6416c6a08 100644 --- a/gio/gdesktopappinfo.c +++ b/gio/gdesktopappinfo.c @@ -3107,6 +3107,9 @@ launch_uris_with_dbus_signal_cb (GObject *object, if (data->callback) data->callback (object, result, data->user_data); + else if (!g_task_had_error (G_TASK (result))) + g_variant_unref (g_dbus_connection_call_finish (G_DBUS_CONNECTION (object), + result, NULL)); launch_uris_with_dbus_data_free (data); } From af10448a05a873303a75bda01fd31c5cda82e5dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 2 Sep 2022 20:38:46 +0200 Subject: [PATCH 10/38] gdesktopappinfo: Unref the GDBus call results On our GDBus call callback wrapper we were completing the gdbus call but ignoring the returned value, that was always leaked. Fix this. Helps with: https://gitlab.gnome.org/GNOME/glib/-/issues/333 (cherry-picked from commit 221f22b6e18fdd306e676e28a79afd3697bddd03) --- gio/gdesktopappinfo.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c index 6416c6a08..a35574516 100644 --- a/gio/gdesktopappinfo.c +++ b/gio/gdesktopappinfo.c @@ -3283,15 +3283,19 @@ launch_uris_with_dbus_cb (GObject *object, { GTask *task = G_TASK (user_data); GError *error = NULL; + GVariant *ret; - g_dbus_connection_call_finish (G_DBUS_CONNECTION (object), result, &error); + ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (object), result, &error); if (error != NULL) { g_dbus_error_strip_remote_error (error); g_task_return_error (task, g_steal_pointer (&error)); } else - g_task_return_boolean (task, TRUE); + { + g_task_return_boolean (task, TRUE); + g_variant_unref (ret); + } g_object_unref (task); } From cd657d692d24289dd8c32dc036400cdccebde4ce Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Tue, 7 Jun 2022 11:19:06 +0100 Subject: [PATCH 11/38] gobject: Sink floating pspecs if adding them to a class fails This may fix Coverity assuming that pspecs are leaked, which is causing tens and tens of false positives in the latest Coverity reports for GLib. Ensure that the pspecs are sunk (if floating) even if adding them to the class fails (due to validation failure or an identically named property already existing). Signed-off-by: Philip Withnall (cherry-picked from commit 8f7df344b636d5fda3d05560f5142d5d8515662a) --- gobject/gobject.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/gobject/gobject.c b/gobject/gobject.c index d33d8e5b0..c33ee3580 100644 --- a/gobject/gobject.c +++ b/gobject/gobject.c @@ -572,22 +572,25 @@ g_object_do_class_init (GObjectClass *class) g_type_add_interface_check (NULL, object_interface_check_properties); } +/* Sinks @pspec if it’s a floating ref. */ static inline gboolean install_property_internal (GType g_type, guint property_id, GParamSpec *pspec) { + g_param_spec_ref_sink (pspec); + if (g_param_spec_pool_lookup (pspec_pool, pspec->name, g_type, FALSE)) { g_warning ("When installing property: type '%s' already has a property named '%s'", g_type_name (g_type), pspec->name); + g_param_spec_unref (pspec); return FALSE; } - g_param_spec_ref_sink (pspec); PARAM_SPEC_SET_PARAM_ID (pspec, property_id); - g_param_spec_pool_insert (pspec_pool, pspec, g_type); + g_param_spec_pool_insert (pspec_pool, g_steal_pointer (&pspec), g_type); return TRUE; } @@ -608,6 +611,7 @@ validate_pspec_to_install (GParamSpec *pspec) return TRUE; } +/* Sinks @pspec if it’s a floating ref. */ static gboolean validate_and_install_class_property (GObjectClass *class, GType oclass_type, @@ -616,7 +620,11 @@ validate_and_install_class_property (GObjectClass *class, GParamSpec *pspec) { if (!validate_pspec_to_install (pspec)) - return FALSE; + { + g_param_spec_ref_sink (pspec); + g_param_spec_unref (pspec); + return FALSE; + } if (pspec->flags & G_PARAM_WRITABLE) g_return_val_if_fail (class->set_property != NULL, FALSE); @@ -824,7 +832,11 @@ g_object_interface_install_property (gpointer g_iface, g_return_if_fail (!G_IS_PARAM_SPEC_OVERRIDE (pspec)); /* paranoid */ if (!validate_pspec_to_install (pspec)) - return; + { + g_param_spec_ref_sink (pspec); + g_param_spec_unref (pspec); + return; + } (void) install_property_internal (iface_class->g_type, 0, pspec); } From 491059294eee944c95aa6efac650e2974d8894fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 17 May 2022 15:01:04 +0200 Subject: [PATCH 12/38] glib/tests/spawn-path-search: fix stack-buffer-overflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ==24477==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffde020de20 at pc 0x7f2e6f6413f1 bp 0x7ffde020c9d0 sp 0x7ffde020c180 READ of size 4101 at 0x7ffde020de20 thread T0 #0 0x7f2e6f6413f0 in __interceptor_strlen.part.0 (/lib64/libasan.so.8+0x4c3f0) #1 0x7f2e6ef4abee in g_build_path_va ../glib/gfileutils.c:1908 #2 0x7f2e6f085956 in g_test_build_filename_va ../glib/gtestutils.c:4294 #3 0x7f2e6f086684 in g_test_build_filename ../glib/gtestutils.c:4365 #4 0x403a33 in test_search_path_heap_allocation ../glib/tests/spawn-path-search.c:422 #5 0x7f2e6f0839a5 in test_case_run ../glib/gtestutils.c:2930 #6 0x7f2e6f0839a5 in g_test_run_suite_internal ../glib/gtestutils.c:3018 #7 0x7f2e6f0834ed in g_test_run_suite_internal ../glib/gtestutils.c:3035 #8 0x7f2e6f084879 in g_test_run_suite ../glib/gtestutils.c:3112 #9 0x7f2e6f084995 in g_test_run ../glib/gtestutils.c:2231 #10 0x40145f in main ../glib/tests/spawn-path-search.c:488 #11 0x7f2e6e31258f in __libc_start_call_main (/lib64/libc.so.6+0x2d58f) #12 0x7f2e6e312648 in __libc_start_main_alias_1 (/lib64/libc.so.6+0x2d648) #13 0x401524 in _start (/home/elmarco/src/gnome/glib/build/glib/tests/spawn-path-search+0x401524) Address 0x7ffde020de20 is located in stack of thread T0 at offset 4256 in frame #0 0x40387f in test_search_path_heap_allocation ../glib/tests/spawn-path-search.c:401 Signed-off-by: Marc-André Lureau (cherry-picked from 15ce3c9b37c2767c82de249e60781439c9abaf78) --- glib/tests/spawn-path-search.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/glib/tests/spawn-path-search.c b/glib/tests/spawn-path-search.c index 5008fc960..221849d5c 100644 --- a/glib/tests/spawn-path-search.c +++ b/glib/tests/spawn-path-search.c @@ -417,7 +417,8 @@ test_search_path_heap_allocation (void) if (skip_win32 ()) return; - memset (placeholder, '_', sizeof (placeholder)); + memset (placeholder, '_', sizeof (placeholder) - 1); + placeholder[sizeof (placeholder) - 1] = '\0'; /* Force search_path_buffer to be heap-allocated */ long_dir = g_test_build_filename (G_TEST_BUILT, "path-test-subdir", placeholder, NULL); long_path = g_strjoin (G_SEARCHPATH_SEPARATOR_S, subdir, long_dir, NULL); From 091e409dee357b69549b5c50c656a17cf601e373 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 7 Apr 2022 17:49:36 +0400 Subject: [PATCH 13/38] glib/win32: fix potential leak on spawn error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau (cherry-picked from commit 982b074fa97bcabc5e7624ac883b035a403f401e) --- glib/gspawn-win32.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/glib/gspawn-win32.c b/glib/gspawn-win32.c index fc2a96c94..29bdf4d79 100644 --- a/glib/gspawn-win32.c +++ b/glib/gspawn-win32.c @@ -903,7 +903,8 @@ fork_exec (gint *exit_status, 0, TRUE, DUPLICATE_SAME_ACCESS)) { char *emsg = g_win32_error_message (GetLastError ()); - g_print("%s\n", emsg); + g_print ("%s\n", emsg); + g_free (emsg); *child_pid = 0; } } From 38d727524af9fd0c3b5ca6ab73f2e1f480808597 Mon Sep 17 00:00:00 2001 From: Andy Holmes Date: Sun, 4 Sep 2022 17:29:39 -0700 Subject: [PATCH 14/38] GActionGroup: Fix ownership transfer annotation for query_action() The `(transfer none)` behaviour for `parameter_type` and `state_type` parameters is implicit with the `const` attribute, but was incorrectly determined to be `(transfer full)` in the GIR. Add explicit `(transfer none)` annotations for these two parameters. (cherry-picked from commit 1eb1a47a50f31b2cea71cf8c94c8989727abb98c) --- gio/gactiongroup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gio/gactiongroup.c b/gio/gactiongroup.c index ecd3af1c3..7c7b0e7f8 100644 --- a/gio/gactiongroup.c +++ b/gio/gactiongroup.c @@ -739,8 +739,8 @@ g_action_group_action_state_changed (GActionGroup *action_group, * @action_group: a #GActionGroup * @action_name: the name of an action in the group * @enabled: (out): if the action is presently enabled - * @parameter_type: (out) (optional): the parameter type, or %NULL if none needed - * @state_type: (out) (optional): the state type, or %NULL if stateless + * @parameter_type: (out) (transfer none) (optional): the parameter type, or %NULL if none needed + * @state_type: (out) (transfer none) (optional): the state type, or %NULL if stateless * @state_hint: (out) (optional): the state hint, or %NULL if none * @state: (out) (optional): the current state, or %NULL if stateless * From 3f10df2d7b66074d59f7af7ed255af79a2089d26 Mon Sep 17 00:00:00 2001 From: Michael Catanzaro Date: Fri, 17 Jun 2022 08:48:10 -0500 Subject: [PATCH 15/38] xdgmime: fix double free We free xdg_dirs[i] twice, but fail to free xdg_dirs itself. Also, since free() is NULL-safe, there is no need for the second check here. Discovered in: https://gitlab.freedesktop.org/xdg/xdgmime/-/merge_requests/16#note_1432025 (cherry-picked from commit f95ca6cb713383548f16f9a8ba2f6c51a4d25e25) --- gio/xdgmime/xdgmime.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gio/xdgmime/xdgmime.c b/gio/xdgmime/xdgmime.c index 9ab676048..c3c11625e 100644 --- a/gio/xdgmime/xdgmime.c +++ b/gio/xdgmime/xdgmime.c @@ -350,8 +350,7 @@ xdg_mime_set_dirs (const char * const *dirs) for (i = 0; xdg_dirs != NULL && xdg_dirs[i] != NULL; i++) free (xdg_dirs[i]); - if (xdg_dirs != NULL) - free (xdg_dirs[i]); + free (xdg_dirs); xdg_dirs = NULL; if (dirs != NULL) From 8434e704f1a225aa59a4a17506ca3d0fcf7f6c0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 23 Jun 2022 04:27:11 +0200 Subject: [PATCH 16/38] gthread: Fix Since tag typo in documentation for some methods --- glib/gthread-posix.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/glib/gthread-posix.c b/glib/gthread-posix.c index 8c403f975..171125c35 100644 --- a/glib/gthread-posix.c +++ b/glib/gthread-posix.c @@ -193,7 +193,7 @@ g_mutex_init (GMutex *mutex) * Calling g_mutex_clear() on a locked mutex leads to undefined * behaviour. * - * Sine: 2.32 + * Since: 2.32 */ void g_mutex_clear (GMutex *mutex) @@ -368,7 +368,7 @@ g_rec_mutex_init (GRecMutex *rec_mutex) * Calling g_rec_mutex_clear() on a locked recursive mutex leads * to undefined behaviour. * - * Sine: 2.32 + * Since: 2.32 */ void g_rec_mutex_clear (GRecMutex *rec_mutex) @@ -525,7 +525,7 @@ g_rw_lock_init (GRWLock *rw_lock) * Calling g_rw_lock_clear() when any thread holds the lock * leads to undefined behaviour. * - * Sine: 2.32 + * Since: 2.32 */ void g_rw_lock_clear (GRWLock *rw_lock) From e52494c49bfe0573036c846f5aa91de9a81b855e Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Tue, 21 Jun 2022 12:10:06 +0100 Subject: [PATCH 17/38] gtlscertificate: Hold a ref on the root certificate when building chains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is unlikely to be a bug in practice, as the certificate pointed to by `root` should have a ref held on it as the issuer of another certificate in the chain. However, we can’t guarantee that’s how the `GTlsCertificate` implementation behaves, so keep a temporary ref on `root` until it’s no longer needed. Signed-off-by: Philip Withnall Coverity CID: #1489985 (cherry-picked from commit 2c75c392eb76a12c3fd18b63508b1f971a3afecd) --- gio/gtlscertificate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gio/gtlscertificate.c b/gio/gtlscertificate.c index d0a326b27..975117042 100644 --- a/gio/gtlscertificate.c +++ b/gio/gtlscertificate.c @@ -624,7 +624,7 @@ create_certificate_chain_from_list (GSList *pem_list, /* root will point to the last certificate in the file. */ if (!root) - root = cert; + root = g_object_ref (cert); pem = g_slist_next (pem); } @@ -639,6 +639,8 @@ create_certificate_chain_from_list (GSList *pem_list, g_clear_object (&cert); } + g_clear_object (&root); + return cert; } From 60410766dfd75b4a34845a5a5dc09bea8c341e7b Mon Sep 17 00:00:00 2001 From: Matteo Biggio Date: Tue, 31 May 2022 11:19:07 +0200 Subject: [PATCH 18/38] gsocketaddressenumerator: add nullable annotation to the result of `next` The returned `SocketAddress` is going to be NULL when the stream of socket addresses is finished (cherry-picked from commit ac3fc84ff41ad1fbcad765d170f5d741813dc84e) --- gio/gsocketaddressenumerator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gio/gsocketaddressenumerator.c b/gio/gsocketaddressenumerator.c index fabd242e7..458c7942d 100644 --- a/gio/gsocketaddressenumerator.c +++ b/gio/gsocketaddressenumerator.c @@ -85,7 +85,7 @@ g_socket_address_enumerator_class_init (GSocketAddressEnumeratorClass *enumerato * internal errors (other than @cancellable being triggered) will be * ignored. * - * Returns: (transfer full): a #GSocketAddress (owned by the caller), or %NULL on + * Returns: (transfer full) (nullable): a #GSocketAddress (owned by the caller), or %NULL on * error (in which case *@error will be set) or if there are no * more addresses. */ @@ -179,7 +179,7 @@ g_socket_address_enumerator_real_next_finish (GSocketAddressEnumerator *enumera * g_socket_address_enumerator_next() for more information about * error handling. * - * Returns: (transfer full): a #GSocketAddress (owned by the caller), or %NULL on + * Returns: (transfer full) (nullable): a #GSocketAddress (owned by the caller), or %NULL on * error (in which case *@error will be set) or if there are no * more addresses. */ From f29beb246c78d80f98320806d957343e9ef0e556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 15 Jul 2022 16:05:23 +0200 Subject: [PATCH 19/38] gsignal: Perform signal unlocked handlers block, unblock and disconnect ops We used to perform unneeded lock/unlock dances to perform block, unblock and disconnect actions, and these were potentially unsafe because we might have looped in data that could be potentially be changed by other threads. We could have also done the same by saving the handlers ids in a temporary array and eventually remove them, but I don't see a reason for that since we can just keep all locked without the risk of creating deadlocks. Coverity CID: #1474757, #1474771, #1474429 (cherry-picked from commit ae14f3219a756fa99dbbbb54555f10dd48eb0fea) --- gobject/gsignal.c | 102 ++++++++++++++++++++++++++++++---------------- 1 file changed, 68 insertions(+), 34 deletions(-) diff --git a/gobject/gsignal.c b/gobject/gsignal.c index 1fafcae5d..aeaf24407 100644 --- a/gobject/gsignal.c +++ b/gobject/gsignal.c @@ -2616,6 +2616,10 @@ g_signal_connect_data (gpointer instance, return handler_seq_no; } +static void +signal_handler_block_unlocked (gpointer instance, + gulong handler_id); + /** * g_signal_handler_block: * @instance: (type GObject.Object): The instance to block the signal handler of. @@ -2634,12 +2638,20 @@ void g_signal_handler_block (gpointer instance, gulong handler_id) { - Handler *handler; - g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); g_return_if_fail (handler_id > 0); SIGNAL_LOCK (); + signal_handler_block_unlocked (instance, handler_id); + SIGNAL_UNLOCK (); +} + +static void +signal_handler_block_unlocked (gpointer instance, + gulong handler_id) +{ + Handler *handler; + handler = handler_lookup (instance, handler_id, NULL, NULL); if (handler) { @@ -2651,9 +2663,12 @@ g_signal_handler_block (gpointer instance, } else g_warning ("%s: instance '%p' has no handler with id '%lu'", G_STRLOC, instance, handler_id); - SIGNAL_UNLOCK (); } +static void +signal_handler_unblock_unlocked (gpointer instance, + gulong handler_id); + /** * g_signal_handler_unblock: * @instance: (type GObject.Object): The instance to unblock the signal handler of. @@ -2677,12 +2692,20 @@ void g_signal_handler_unblock (gpointer instance, gulong handler_id) { - Handler *handler; - g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); g_return_if_fail (handler_id > 0); SIGNAL_LOCK (); + signal_handler_unblock_unlocked (instance, handler_id); + SIGNAL_UNLOCK (); +} + +static void +signal_handler_unblock_unlocked (gpointer instance, + gulong handler_id) +{ + Handler *handler; + handler = handler_lookup (instance, handler_id, NULL, NULL); if (handler) { @@ -2693,9 +2716,12 @@ g_signal_handler_unblock (gpointer instance, } else g_warning ("%s: instance '%p' has no handler with id '%lu'", G_STRLOC, instance, handler_id); - SIGNAL_UNLOCK (); } +static void +signal_handler_disconnect_unlocked (gpointer instance, + gulong handler_id); + /** * g_signal_handler_disconnect: * @instance: (type GObject.Object): The instance to remove the signal handler from. @@ -2712,12 +2738,20 @@ void g_signal_handler_disconnect (gpointer instance, gulong handler_id) { - Handler *handler; - g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); g_return_if_fail (handler_id > 0); SIGNAL_LOCK (); + signal_handler_disconnect_unlocked (instance, handler_id); + SIGNAL_UNLOCK (); +} + +static void +signal_handler_disconnect_unlocked (gpointer instance, + gulong handler_id) +{ + Handler *handler; + handler = handler_lookup (instance, handler_id, 0, 0); if (handler) { @@ -2729,7 +2763,6 @@ g_signal_handler_disconnect (gpointer instance, } else g_warning ("%s: instance '%p' has no handler with id '%lu'", G_STRLOC, instance, handler_id); - SIGNAL_UNLOCK (); } /** @@ -2860,33 +2893,31 @@ g_signal_handler_find (gpointer instance, return handler_seq_no; } +typedef void (*CallbackHandlerFunc) (gpointer instance, gulong handler_seq_no); + static guint -signal_handlers_foreach_matched_R (gpointer instance, - GSignalMatchType mask, - guint signal_id, - GQuark detail, - GClosure *closure, - gpointer func, - gpointer data, - void (*callback) (gpointer instance, - gulong handler_seq_no)) +signal_handlers_foreach_matched_unlocked_R (gpointer instance, + GSignalMatchType mask, + guint signal_id, + GQuark detail, + GClosure *closure, + gpointer func, + gpointer data, + CallbackHandlerFunc callback) { HandlerMatch *mlist; guint n_handlers = 0; - + mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE); while (mlist) { n_handlers++; if (mlist->handler->sequential_number) - { - SIGNAL_UNLOCK (); - callback (instance, mlist->handler->sequential_number); - SIGNAL_LOCK (); - } + callback (instance, mlist->handler->sequential_number); + mlist = handler_match_free1_R (mlist, instance); } - + return n_handlers; } @@ -2928,9 +2959,10 @@ g_signal_handlers_block_matched (gpointer instance, if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) { SIGNAL_LOCK (); - n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, - closure, func, data, - g_signal_handler_block); + n_handlers = + signal_handlers_foreach_matched_unlocked_R (instance, mask, signal_id, detail, + closure, func, data, + signal_handler_block_unlocked); SIGNAL_UNLOCK (); } @@ -2976,9 +3008,10 @@ g_signal_handlers_unblock_matched (gpointer instance, if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) { SIGNAL_LOCK (); - n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, - closure, func, data, - g_signal_handler_unblock); + n_handlers = + signal_handlers_foreach_matched_unlocked_R (instance, mask, signal_id, detail, + closure, func, data, + signal_handler_unblock_unlocked); SIGNAL_UNLOCK (); } @@ -3024,9 +3057,10 @@ g_signal_handlers_disconnect_matched (gpointer instance, if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) { SIGNAL_LOCK (); - n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, - closure, func, data, - g_signal_handler_disconnect); + n_handlers = + signal_handlers_foreach_matched_unlocked_R (instance, mask, signal_id, detail, + closure, func, data, + signal_handler_disconnect_unlocked); SIGNAL_UNLOCK (); } From a6a725c27ac84633056cc47771eb4fd16f027dac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Tue, 14 Jun 2022 18:26:05 +0200 Subject: [PATCH 20/38] gioerror: Handle EMLINK error as too-many-links error This used to be a FreeBSD only error but it's actually defined also in linux. (cherry-picked from commit 9e09894414ca092a07cd094b4fad1fdab0906a9) --- gio/gioerror.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gio/gioerror.c b/gio/gioerror.c index 38fc3d83f..f52b95038 100644 --- a/gio/gioerror.c +++ b/gio/gioerror.c @@ -119,6 +119,12 @@ g_io_error_from_errno (gint err_no) break; #endif +#ifdef EMLINK + case EMLINK: + return G_IO_ERROR_TOO_MANY_LINKS; + break; +#endif + #ifdef ELOOP case ELOOP: return G_IO_ERROR_TOO_MANY_LINKS; From 28fe069024778998d64dbeaf06b742c64352a92a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Tue, 14 Jun 2022 18:41:33 +0200 Subject: [PATCH 21/38] gioerror: Map ETXTBSY to G_FILE_ERROR_BUSY It's a busy text file, but we don't care much about specifics so we can just return the generic busy error. (cherry-picked from commit 6bc6b7ef3012487966a99a5db06d27000205ab38) --- gio/gioerror.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gio/gioerror.c b/gio/gioerror.c index f52b95038..7566c49db 100644 --- a/gio/gioerror.c +++ b/gio/gioerror.c @@ -217,6 +217,12 @@ g_io_error_from_errno (gint err_no) break; #endif +#ifdef ETXTBSY + case ETXTBSY: + return G_IO_ERROR_BUSY; + break; +#endif + #ifdef EWOULDBLOCK case EWOULDBLOCK: return G_IO_ERROR_WOULD_BLOCK; From 938ea5141f47c69262b7370011955ba1bf1b9452 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Tue, 28 Jun 2022 10:51:42 +0100 Subject: [PATCH 22/38] gcontenttype: Fix a potential use-after-free of xdgmime data While `gio_xdgmime` is unlocked, the data which `type` points to in the xdgmime cache might get invalidated, leaving `type` as a dangling pointer. That would not bode well for the `g_strdup (type)` call to insert a new entry into the `type_comment_cache` once `gio_xdgmime` is re-acquired. This was spotted using static analysis, and the symptoms have not knowingly been seen in the wild. Signed-off-by: Philip Withnall Coverity CID: #1474702 (cherry-picked from commit 45d4c525) --- gio/gcontenttype.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/gio/gcontenttype.c b/gio/gcontenttype.c index 3c9522bc6..1e4f19b63 100644 --- a/gio/gcontenttype.c +++ b/gio/gcontenttype.c @@ -483,6 +483,7 @@ gchar * g_content_type_get_description (const gchar *type) { static GHashTable *type_comment_cache = NULL; + gchar *type_copy = NULL; gchar *comment; g_return_val_if_fail (type != NULL, NULL); @@ -497,16 +498,21 @@ g_content_type_get_description (const gchar *type) comment = g_hash_table_lookup (type_comment_cache, type); comment = g_strdup (comment); - G_UNLOCK (gio_xdgmime); if (comment != NULL) - return comment; + { + G_UNLOCK (gio_xdgmime); + return comment; + } - comment = load_comment_for_mime (type); + type_copy = g_strdup (type); + G_UNLOCK (gio_xdgmime); + comment = load_comment_for_mime (type_copy); G_LOCK (gio_xdgmime); + g_hash_table_insert (type_comment_cache, - g_strdup (type), + g_steal_pointer (&type_copy), g_strdup (comment)); G_UNLOCK (gio_xdgmime); From df1e7dc5db8d29bff4609005d7af9e994c90f626 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 2 Sep 2022 12:52:35 +0100 Subject: [PATCH 23/38] Fix check before a memcpy The search_total_results address is always going to be non-zero, so the check will always evaluate to true, and GCC is kind enough to point this out to us. The appropriate fix is checking if the size of the search results array is larger than zero, and if so, copy them into the total results array. (cherry-picked from commit e08c954693fdcfceda2de59cca93a76125f4fca6) --- gio/gdesktopappinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c index a35574516..7d9c3daf1 100644 --- a/gio/gdesktopappinfo.c +++ b/gio/gdesktopappinfo.c @@ -706,7 +706,7 @@ merge_directory_results (void) static_total_results = g_renew (struct search_result, static_total_results, static_total_results_allocated); } - if (static_total_results + static_total_results_size != 0) + if (static_search_results_size != 0) memcpy (static_total_results + static_total_results_size, static_search_results, static_search_results_size * sizeof (struct search_result)); From 8fb03af05d83481482b3610b8765c387248b5768 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 2 Sep 2022 12:46:57 +0100 Subject: [PATCH 24/38] Fix array-bounds compiler warnings with GCC 12 GCC isn't smart enough to recognise that the assertion on the size of N_PROPERTIES also affects the assertion on the GParamSpec array access, so we need to coalesce the two checks into one to avoid an array-bounds compiler warning. (cherry-picked from commit 903c004b37d723972b07ecbdd880ae0d2c8b767d) --- gobject/tests/properties.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/gobject/tests/properties.c b/gobject/tests/properties.c index 3695ee123..208d5f145 100644 --- a/gobject/tests/properties.c +++ b/gobject/tests/properties.c @@ -104,8 +104,7 @@ test_object_set_property (GObject *gobject, TestObject *tobj = (TestObject *) gobject; g_assert_cmpint (prop_id, !=, 0); - g_assert_cmpint (prop_id, !=, N_PROPERTIES); - g_assert (pspec == properties[prop_id]); + g_assert_true (prop_id < N_PROPERTIES && pspec == properties[prop_id]); switch (prop_id) { @@ -139,8 +138,7 @@ test_object_get_property (GObject *gobject, TestObject *tobj = (TestObject *) gobject; g_assert_cmpint (prop_id, !=, 0); - g_assert_cmpint (prop_id, !=, N_PROPERTIES); - g_assert (pspec == properties[prop_id]); + g_assert_true (prop_id < N_PROPERTIES && pspec == properties[prop_id]); switch (prop_id) { From ec0cdf638e8dbe82fc97702eb42586a2c86d48ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 11 Jul 2022 18:45:36 +0200 Subject: [PATCH 25/38] gthreadpool: Update unused_threads while we still own the pool lock As per the rationale explained in the previous commit, we could end up having the unused_threads value not to be conformant to what g_thread_pool_get_num_threads() returns, because an about-to-be-unused thread might not be counted yet as such, while the pool threads number has been already decreased. To avoid such scenario, and to make sure that when all the pool's threads are stopped, they're unmarked as unused, let's increase the unused_threads value earlier, while we still own the pool lock so that it will always include the pool that is not used anymore, but not yet queued. As per this we can update the test, not to repeat the stop-unused call as now we're sure that when the pool has no threads anymore, the unused threads value is also updated accordingly. Also adding a tests with multiple pools. (cherry-picked from commit a275ee66796ab0d6d95ed8647f2170be9b136951) --- glib/gthreadpool.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/glib/gthreadpool.c b/glib/gthreadpool.c index c7d587a56..ae0268443 100644 --- a/glib/gthreadpool.c +++ b/glib/gthreadpool.c @@ -165,8 +165,6 @@ g_thread_pool_wait_for_new_pool (void) local_max_idle_time = g_atomic_int_get (&max_idle_time); last_wakeup_thread_serial = g_atomic_int_get (&wakeup_thread_serial); - g_atomic_int_inc (&unused_threads); - do { if ((guint) g_atomic_int_get (&unused_threads) >= local_max_unused_threads) @@ -235,8 +233,6 @@ g_thread_pool_wait_for_new_pool (void) } while (pool == wakeup_thread_marker); - g_atomic_int_add (&unused_threads, -1); - return pool; } @@ -403,12 +399,16 @@ g_thread_pool_thread_proxy (gpointer data) } } + g_atomic_int_inc (&unused_threads); g_async_queue_unlock (pool->queue); if (free_pool) g_thread_pool_free_internal (pool); - if ((pool = g_thread_pool_wait_for_new_pool ()) == NULL) + pool = g_thread_pool_wait_for_new_pool (); + g_atomic_int_add (&unused_threads, -1); + + if (pool == NULL) break; g_async_queue_lock (pool->queue); From b54cce6cdd9a65a32cdf04ff89cac869eaf2d794 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 19 Aug 2022 08:29:36 -0400 Subject: [PATCH 26/38] mem: Document OOM behavior for allocations For all the memory allocator APIS, document that they terminate the program on failure. This was so far only mentioned in the long description, and in the docs for g_try_malloc(). And with gi-docgen style docs, the long description is going away. (cherry-picked from commit 1df83acb876c8325dfadf96bafc5751e1d9e5447) --- glib/gmem.c | 45 +++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/glib/gmem.c b/glib/gmem.c index 060e91af9..e604d1f71 100644 --- a/glib/gmem.c +++ b/glib/gmem.c @@ -109,10 +109,13 @@ static GMemVTable glib_mem_vtable = { /** * g_malloc: * @n_bytes: the number of bytes to allocate - * + * * Allocates @n_bytes bytes of memory. * If @n_bytes is 0 it returns %NULL. - * + * + * If the allocation fails (because the system is out of memory), + * the program is terminated. + * * Returns: a pointer to the allocated memory */ gpointer @@ -139,10 +142,13 @@ g_malloc (gsize n_bytes) /** * g_malloc0: * @n_bytes: the number of bytes to allocate - * + * * Allocates @n_bytes bytes of memory, initialized to 0's. * If @n_bytes is 0 it returns %NULL. - * + * + * If the allocation fails (because the system is out of memory), + * the program is terminated. + * * Returns: a pointer to the allocated memory */ gpointer @@ -170,13 +176,16 @@ g_malloc0 (gsize n_bytes) * g_realloc: * @mem: (nullable): the memory to reallocate * @n_bytes: new size of the memory in bytes - * + * * Reallocates the memory pointed to by @mem, so that it now has space for * @n_bytes bytes of memory. It returns the new address of the memory, which may * have been moved. @mem may be %NULL, in which case it's considered to * have zero-length. @n_bytes may be 0, in which case %NULL will be returned * and @mem will be freed unless it is %NULL. - * + * + * If the allocation fails (because the system is out of memory), + * the program is terminated. + * * Returns: the new address of the allocated memory */ gpointer @@ -343,10 +352,13 @@ g_try_realloc (gpointer mem, * g_malloc_n: * @n_blocks: the number of blocks to allocate * @n_block_bytes: the size of each block in bytes - * + * * This function is similar to g_malloc(), allocating (@n_blocks * @n_block_bytes) bytes, * but care is taken to detect possible overflow during multiplication. - * + * + * If the allocation fails (because the system is out of memory), + * the program is terminated. + * * Since: 2.24 * Returns: a pointer to the allocated memory */ @@ -367,10 +379,13 @@ g_malloc_n (gsize n_blocks, * g_malloc0_n: * @n_blocks: the number of blocks to allocate * @n_block_bytes: the size of each block in bytes - * + * * This function is similar to g_malloc0(), allocating (@n_blocks * @n_block_bytes) bytes, * but care is taken to detect possible overflow during multiplication. - * + * + * If the allocation fails (because the system is out of memory), + * the program is terminated. + * * Since: 2.24 * Returns: a pointer to the allocated memory */ @@ -392,10 +407,13 @@ g_malloc0_n (gsize n_blocks, * @mem: (nullable): the memory to reallocate * @n_blocks: the number of blocks to allocate * @n_block_bytes: the size of each block in bytes - * + * * This function is similar to g_realloc(), allocating (@n_blocks * @n_block_bytes) bytes, * but care is taken to detect possible overflow during multiplication. - * + * + * If the allocation fails (because the system is out of memory), + * the program is terminated. + * * Since: 2.24 * Returns: the new address of the allocated memory */ @@ -554,6 +572,9 @@ g_mem_profile (void) * alignment value. Additionally, it will detect possible overflow during * multiplication. * + * If the allocation fails (because the system is out of memory), + * the program is terminated. + * * Aligned memory allocations returned by this function can only be * freed using g_aligned_free(). * From 0dfffca862444cb4136bc3dbd6537f56a9c4274d Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Mon, 14 Sep 2020 16:28:10 +0200 Subject: [PATCH 27/38] gdbusauth: empty DATA does not need a trailing space This is an interoperability fix. If the line is exactly "DATA\r\n", the reference implementation of D-Bus treats this as equivalent to "DATA \r\n", meaning the data block consists of zero hex-encoded bytes. In practice, D-Bus clients send empty data blocks as "DATA\r\n", and in fact sd-bus only accepts that, rejecting "DATA \r\n". [Originally part of a larger commit; commit message added by smcv] Signed-off-by: Giuseppe Scrivano Co-authored-by: Simon McVittie Signed-off-by: Simon McVittie (cherry-picked from commit 764f071909df70622e79ee71323973c18c055c8c) --- gio/gdbusauth.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gio/gdbusauth.c b/gio/gdbusauth.c index 74c178dbf..595ab0559 100644 --- a/gio/gdbusauth.c +++ b/gio/gdbusauth.c @@ -784,13 +784,13 @@ _g_dbus_auth_run_client (GDBusAuth *auth, if (line == NULL) goto out; debug_print ("CLIENT: WaitingForData, read='%s'", line); - if (g_str_has_prefix (line, "DATA ")) + if (g_str_equal (line, "DATA") || g_str_has_prefix (line, "DATA ")) { gchar *encoded; gchar *decoded_data; gsize decoded_data_len = 0; - encoded = g_strdup (line + 5); + encoded = g_strdup (line + 4); g_free (line); g_strstrip (encoded); decoded_data = hexdecode (encoded, &decoded_data_len, error); @@ -1265,13 +1265,13 @@ _g_dbus_auth_run_server (GDBusAuth *auth, debug_print ("SERVER: WaitingForData, read '%s'", line); if (line == NULL) goto out; - if (g_str_has_prefix (line, "DATA ")) + if (g_str_equal (line, "DATA") || g_str_has_prefix (line, "DATA ")) { gchar *encoded; gchar *decoded_data; gsize decoded_data_len = 0; - encoded = g_strdup (line + 5); + encoded = g_strdup (line + 4); g_free (line); g_strstrip (encoded); decoded_data = hexdecode (encoded, &decoded_data_len, error); From d6d871208ca6a2f5c9391784eddd3d50782c4f60 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Mon, 14 Sep 2020 16:28:10 +0200 Subject: [PATCH 28/38] GDBusServer: If no initial response for EXTERNAL, send a challenge Sending an "initial response" along with the AUTH command is meant to be an optional optimization, and clients are allowed to omit it. We must reply with our initial challenge, which in the case of EXTERNAL is an empty string: the client responds to that with the authorization identity. If we do not reply to the AUTH command, then the client will wait forever for our reply, while we wait forever for the reply that we expect the client to send, resulting in deadlock. D-Bus does not have a way to distinguish between an empty initial response and the absence of an initial response, so clients that want to use an empty authorization identity, such as systed's sd-bus, cannot use the initial-response optimization and will fail to connect to a GDBusServer that does not have this change. [Originally part of a larger commit; commit message added by smcv.] Signed-off-by: Simon McVittie (cherry-picked from commit a7d2e727eefcf883bb463ad559f5632e8e448757) --- gio/gdbusauthmechanismexternal.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/gio/gdbusauthmechanismexternal.c b/gio/gdbusauthmechanismexternal.c index b3f21175b..ea8eb897d 100644 --- a/gio/gdbusauthmechanismexternal.c +++ b/gio/gdbusauthmechanismexternal.c @@ -38,6 +38,7 @@ struct _GDBusAuthMechanismExternalPrivate gboolean is_client; gboolean is_server; GDBusAuthMechanismState state; + gboolean empty_data_sent; }; static gint mechanism_get_priority (void); @@ -251,7 +252,9 @@ mechanism_server_initiate (GDBusAuthMechanism *mechanism, } else { - m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA; + /* The initial-response optimization was not used, so we need to + * send an empty challenge to prompt the client to respond. */ + m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND; } } @@ -286,12 +289,22 @@ mechanism_server_data_send (GDBusAuthMechanism *mechanism, g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL); g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL); - g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND, NULL); - /* can never end up here because we are never in the HAVE_DATA_TO_SEND state */ - g_assert_not_reached (); + if (out_data_len) + *out_data_len = 0; - return NULL; + if (m->priv->empty_data_sent) + { + /* We have already sent an empty data response. + Reject the connection. */ + m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED; + return NULL; + } + + m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA; + m->priv->empty_data_sent = TRUE; + + return g_strdup (""); } static gchar * From 48f1e15a67894c3c08eb4d52490ccd2da6eaf358 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Mon, 14 Sep 2020 16:28:10 +0200 Subject: [PATCH 29/38] GDBusServer: Accept empty authorization identity for EXTERNAL mechanism RFC 4422 appendix A defines the empty authorization identity to mean the identity that the server associated with its authentication credentials. In this case, this means whatever uid is in the GCredentials object. In particular, this means that clients in a different Linux user namespace can authenticate against our server and will be authorized as the version of their uid that is visible in the server's namespace, even if the corresponding numeric uid returned by geteuid() in the client's namespace was different. systemd's sd-bus has relied on this since commit https://github.com/systemd/systemd/commit/1ed4723d38cd0d1423c8fe650f90fa86007ddf55. [Originally part of a larger commit; commit message added by smcv] Signed-off-by: Simon McVittie (cherry-picked from commit b51e3ab09e39c590c65a7be6228ecfa48a6189f6) --- gio/gdbusauthmechanismexternal.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/gio/gdbusauthmechanismexternal.c b/gio/gdbusauthmechanismexternal.c index ea8eb897d..70aaddc74 100644 --- a/gio/gdbusauthmechanismexternal.c +++ b/gio/gdbusauthmechanismexternal.c @@ -199,14 +199,24 @@ data_matches_credentials (const gchar *data, if (credentials == NULL) goto out; - if (data == NULL || data_len == 0) - goto out; - #if defined(G_OS_UNIX) { gint64 alleged_uid; gchar *endp; + /* If we were unable to find out the uid, then nothing + * can possibly match it. */ + if (g_credentials_get_unix_user (credentials, NULL) == (uid_t) -1) + goto out; + + /* An empty authorization identity means we want to be + * whatever identity the out-of-band credentials say we have + * (RFC 4422 appendix A.1). This effectively matches any uid. */ + if (data == NULL || data_len == 0) + { + match = TRUE; + goto out; + } /* on UNIX, this is the uid as a string in base 10 */ alleged_uid = g_ascii_strtoll (data, &endp, 10); if (*endp == '\0') From d3f80507770f5194d99216b2b82ab98d1802d2fb Mon Sep 17 00:00:00 2001 From: Ryan Hope Date: Tue, 12 Jul 2022 21:38:54 +0000 Subject: [PATCH 30/38] Add missing extension point register for for GMemorySettingsBackend Using GMemorySettingsBackend before any other GSettingsBackend would cause the following error: "Tried to implement non-registered extension point gsettings-backend". This is due to a missing call to _g_io_modules_ensure_extension_points_registered() in the GMemorySettingsBackend type definition which registers the gsettings-backend extension point. (cherry-picked from commit 04255e45654bd49f1974a79baeafb33d228f6f71) --- gio/gmemorysettingsbackend.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gio/gmemorysettingsbackend.c b/gio/gmemorysettingsbackend.c index 5bb96bf29..8f8297aad 100644 --- a/gio/gmemorysettingsbackend.c +++ b/gio/gmemorysettingsbackend.c @@ -21,7 +21,7 @@ #include "gsimplepermission.h" #include "gsettingsbackendinternal.h" -#include "giomodule.h" +#include "giomodule-priv.h" #define G_TYPE_MEMORY_SETTINGS_BACKEND (g_memory_settings_backend_get_type()) @@ -39,6 +39,7 @@ typedef struct G_DEFINE_TYPE_WITH_CODE (GMemorySettingsBackend, g_memory_settings_backend, G_TYPE_SETTINGS_BACKEND, + _g_io_modules_ensure_extension_points_registered (); g_io_extension_point_implement (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME, g_define_type_id, "memory", 10)) From ee0a3a59c738f9a38f1e6425c84f405feb59580d Mon Sep 17 00:00:00 2001 From: Ryan Hope Date: Wed, 13 Jul 2022 10:58:51 +0100 Subject: [PATCH 31/38] gio: Ensure extension points are registered when creating Settings backends Add missing call to _g_io_modules_ensure_extension_points_registered() to GRegistryBackend, GNullSettingsBackend, and GNextstepSettingsBackend (cherry-picked from commit 924da751c2d3ed4636223343ebaa7364b97f8f93) --- gio/gnextstepsettingsbackend.m | 3 ++- gio/gnullsettingsbackend.c | 3 ++- gio/gregistrysettingsbackend.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/gio/gnextstepsettingsbackend.m b/gio/gnextstepsettingsbackend.m index c09d995b6..cde636cee 100644 --- a/gio/gnextstepsettingsbackend.m +++ b/gio/gnextstepsettingsbackend.m @@ -21,7 +21,7 @@ #include "gsettingsbackendinternal.h" #include "gsimplepermission.h" -#include "giomodule.h" +#include "giomodule-priv.h" #import @@ -44,6 +44,7 @@ struct _GNextstepSettingsBackend G_DEFINE_TYPE_WITH_CODE (GNextstepSettingsBackend, g_nextstep_settings_backend, G_TYPE_SETTINGS_BACKEND, + _g_io_modules_ensure_extension_points_registered (); g_io_extension_point_implement (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME, g_define_type_id, "nextstep", 90)); diff --git a/gio/gnullsettingsbackend.c b/gio/gnullsettingsbackend.c index 6b6f8cf75..48819962e 100644 --- a/gio/gnullsettingsbackend.c +++ b/gio/gnullsettingsbackend.c @@ -20,7 +20,7 @@ #include "config.h" #include "gsettingsbackendinternal.h" -#include "giomodule.h" +#include "giomodule-priv.h" #include "gsimplepermission.h" @@ -36,6 +36,7 @@ typedef GSettingsBackend GNullSettingsBackend; G_DEFINE_TYPE_WITH_CODE (GNullSettingsBackend, g_null_settings_backend, G_TYPE_SETTINGS_BACKEND, + _g_io_modules_ensure_extension_points_registered (); g_io_extension_point_implement (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME, g_define_type_id, "null", 10)) diff --git a/gio/gregistrysettingsbackend.c b/gio/gregistrysettingsbackend.c index a7171a21f..fd87cdba3 100644 --- a/gio/gregistrysettingsbackend.c +++ b/gio/gregistrysettingsbackend.c @@ -91,7 +91,7 @@ #include "gregistrysettingsbackend.h" #include "gsettingsbackend.h" -#include "giomodule.h" +#include "giomodule-priv.h" #include @@ -177,6 +177,7 @@ typedef struct { G_DEFINE_TYPE_WITH_CODE (GRegistryBackend, g_registry_backend, G_TYPE_SETTINGS_BACKEND, + _g_io_modules_ensure_extension_points_registered (); g_io_extension_point_implement (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME, g_define_type_id, "registry", 90)) From dda414454193ae3445ceeec0b7275a16f29d3727 Mon Sep 17 00:00:00 2001 From: Ryan Hope Date: Thu, 14 Jul 2022 23:07:38 +0100 Subject: [PATCH 32/38] Add tests for GMemorySettingsBackend and GNullSettingsBackend (cherry-picked from commit 7c4e6032c6e383db94d917e9af6836d938114241) --- gio/tests/memory-settings-backend.c | 57 +++++++++++++++++++++++++++++ gio/tests/meson.build | 2 + gio/tests/null-settings-backend.c | 54 +++++++++++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 gio/tests/memory-settings-backend.c create mode 100644 gio/tests/null-settings-backend.c diff --git a/gio/tests/memory-settings-backend.c b/gio/tests/memory-settings-backend.c new file mode 100644 index 000000000..80e9919bf --- /dev/null +++ b/gio/tests/memory-settings-backend.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2022 Ryan Hope + * + * 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 . + * + * Authors: Ryan Hope + */ + +#include +#include +#define G_SETTINGS_ENABLE_BACKEND +#include + +/* Test that the "gsettings-backend" extension point has been registered. + * Must be run first and separetly from other GSettingsBackend, + * as they will register the extension point making the test useless. + */ +static void +test_extension_point_registered (void) +{ + GSettingsBackend *backend; + GIOExtensionPoint *extension_point; + + backend = g_memory_settings_backend_new (); + g_assert_true (G_IS_SETTINGS_BACKEND (backend)); + + extension_point = g_io_extension_point_lookup (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME); + g_assert_nonnull (extension_point); + + g_object_unref (backend); +} + +int +main (int argc, char *argv[]) +{ + setlocale (LC_ALL, ""); + + g_test_init (&argc, &argv, NULL); + + /* Must be run first */ + g_test_add_func ("/memory-settings-backend/extension-point-registered", test_extension_point_registered); + + return g_test_run (); +} diff --git a/gio/tests/meson.build b/gio/tests/meson.build index 3ed23a5f2..eac412aa1 100644 --- a/gio/tests/meson.build +++ b/gio/tests/meson.build @@ -86,10 +86,12 @@ gio_tests = { 'memory-input-stream' : {}, 'memory-monitor' : {}, 'memory-output-stream' : {}, + 'memory-settings-backend' : {}, 'mount-operation' : {}, 'network-address' : {'extra_sources': ['mock-resolver.c']}, 'network-monitor' : {}, 'network-monitor-race' : {}, + 'null-settings-backend' : {}, 'permission' : {}, 'pollable' : {'dependencies' : [libdl_dep]}, 'power-profile-monitor' : {}, diff --git a/gio/tests/null-settings-backend.c b/gio/tests/null-settings-backend.c new file mode 100644 index 000000000..34dee56d2 --- /dev/null +++ b/gio/tests/null-settings-backend.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2022 Ryan Hope + * + * 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 . + * + * Authors: Ryan Hope + */ + +#include +#define G_SETTINGS_ENABLE_BACKEND +#include + +/* Test that the "gsettings-backend" extension point has been registered. + * Must be run first and separetly from other GSettingsBackend, + * as they will register the extension point making the test useless. + */ +static void +test_extension_point_registered (void) +{ + GSettingsBackend *backend; + GIOExtensionPoint *extension_point; + + backend = g_null_settings_backend_new (); + g_assert_true (G_IS_SETTINGS_BACKEND (backend)); + extension_point = g_io_extension_point_lookup (G_SETTINGS_BACKEND_EXTENSION_POINT_NAME); + + g_assert_nonnull (extension_point); + + g_object_unref (backend); +} + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + /* Must be run first */ + g_test_add_func ("/null-settings-backend/extension-point-registered", test_extension_point_registered); + + return g_test_run (); +} From fcf2aaa1eb0b75303426dc74d6c74cb2dd70ea89 Mon Sep 17 00:00:00 2001 From: James Hilliard Date: Fri, 15 Jul 2022 00:23:37 -0600 Subject: [PATCH 33/38] meson: fix build without cpp toolchain We don't need a cpp toolchain for building glib so lets just automatically disable tests requiring one when not available. Signed-off-by: James Hilliard (cherry-picked from commit d0b9ebbaacb5f69aaaad30829e04cd3a88f084cb) --- fuzzing/meson.build | 8 ++++++-- gio/tests/meson.build | 11 ++++++++--- glib/tests/meson.build | 11 ++++++++--- gmodule/tests/meson.build | 12 +++++++----- gobject/tests/meson.build | 11 ++++++++--- meson.build | 39 +++++++++++++++++++++++++-------------- 6 files changed, 62 insertions(+), 30 deletions(-) diff --git a/fuzzing/meson.build b/fuzzing/meson.build index 259c6d91d..49cfc3752 100644 --- a/fuzzing/meson.build +++ b/fuzzing/meson.build @@ -26,8 +26,12 @@ extra_c_args = cc.get_supported_arguments('-Werror=unused-function') # Links in a static library provided by oss-fuzz, else a standalone driver. # https://google.github.io/oss-fuzz/getting-started/new-project-guide/#buildsh-script-environment -fuzzing_engine = cxx.find_library('FuzzingEngine', required : get_option('oss_fuzz')) -if fuzzing_engine.found() +have_fuzzing_engine = false +if have_cxx + fuzzing_engine = cxx.find_library('FuzzingEngine', required : get_option('oss_fuzz')) + have_fuzzing_engine = fuzzing_engine.found() +endif +if have_fuzzing_engine deps += fuzzing_engine else extra_sources += 'driver.c' diff --git a/gio/tests/meson.build b/gio/tests/meson.build index eac412aa1..383d84319 100644 --- a/gio/tests/meson.build +++ b/gio/tests/meson.build @@ -58,9 +58,6 @@ gio_tests = { }, 'converter-stream' : {}, 'credentials' : {}, - 'cxx' : { - 'source' : ['cxx.cpp'], - }, 'data-input-stream' : {}, 'data-output-stream' : {}, 'fileattributematcher' : {}, @@ -124,6 +121,14 @@ gio_tests = { 'win32-appinfo' : {}, } +if have_cxx + gio_tests += { + 'cxx' : { + 'source' : ['cxx.cpp'], + }, + } +endif + test_extra_programs = { 'gdbus-connection-flush-helper' : {}, 'gdbus-testserver' : {}, diff --git a/glib/tests/meson.build b/glib/tests/meson.build index 301158e0f..48d12d749 100644 --- a/glib/tests/meson.build +++ b/glib/tests/meson.build @@ -15,9 +15,6 @@ glib_tests = { 'completion' : {}, 'cond' : {}, 'convert' : {}, - 'cxx' : { - 'source' : ['cxx.cpp'], - }, 'dataset' : {}, 'date' : { # FIXME: https://gitlab.gnome.org/GNOME/glib/-/issues/1392 @@ -142,6 +139,14 @@ glib_tests = { }, } +if have_cxx + glib_tests += { + 'cxx' : { + 'source' : ['cxx.cpp'], + } + } +endif + if cc.get_id() != 'msvc' glib_tests += {'autoptr' : {}} endif diff --git a/gmodule/tests/meson.build b/gmodule/tests/meson.build index 9b475a88e..b6f1ccaa6 100644 --- a/gmodule/tests/meson.build +++ b/gmodule/tests/meson.build @@ -1,8 +1,10 @@ -gmodule_tests = { - 'cxx' : { - 'source' : ['cxx.cpp'], - }, -} +if have_cxx + gmodule_tests = { + 'cxx' : { + 'source' : ['cxx.cpp'], + }, + } +endif test_env = environment() test_env.set('G_TEST_SRCDIR', meson.current_source_dir()) diff --git a/gobject/tests/meson.build b/gobject/tests/meson.build index 8d568f00e..eb6a04746 100644 --- a/gobject/tests/meson.build +++ b/gobject/tests/meson.build @@ -29,9 +29,6 @@ marshalers_c = custom_target('marshalers_c', gobject_tests = { 'qdata' : {}, 'boxed' : {}, - 'cxx' : { - 'source' : ['cxx.cpp'], - }, 'enums' : {}, 'param' : {}, 'threadtests' : {}, @@ -59,6 +56,14 @@ gobject_tests = { 'type-flags' : {}, } +if have_cxx + gobject_tests += { + 'cxx' : { + 'source' : ['cxx.cpp'], + }, + } +endif + if cc.get_id() != 'msvc' gobject_tests += {'autoptr' : {}} endif diff --git a/meson.build b/meson.build index 48fdfe864..04fce1d90 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -project('glib', 'c', 'cpp', +project('glib', 'c', version : '2.72.3', # NOTE: We keep this pinned at 0.52 because that's what Debian Stable ships meson_version : '>= 0.52.0', @@ -10,7 +10,14 @@ project('glib', 'c', 'cpp', ) cc = meson.get_compiler('c') -cxx = meson.get_compiler('cpp') +if meson.version().version_compare('>= 0.54.0') + have_cxx = add_languages('cpp', native: false, required: get_option('oss_fuzz').enabled()) +else + have_cxx = add_languages('cpp', required: get_option('oss_fuzz').enabled()) +endif +if have_cxx + cxx = meson.get_compiler('cpp') +endif cc_can_run = not meson.is_cross_build() or meson.has_exe_wrapper() @@ -495,7 +502,9 @@ else endif add_project_arguments(cc.get_supported_arguments(warning_c_args), language: 'c') -add_project_arguments(cxx.get_supported_arguments(warning_cxx_args), language: 'cpp') +if have_cxx + add_project_arguments(cxx.get_supported_arguments(warning_cxx_args), language: 'cpp') +endif # FIXME: We cannot build some of the GResource tests with -z nodelete, which # means we cannot use that flag in add_project_link_arguments(), and must add @@ -1734,18 +1743,20 @@ if g_have_iso_c_varargs #endif''') endif -g_have_iso_cxx_varargs = cxx.compiles(''' - void some_func (void) { - int a(int p1, int p2, int p3); - #define call_a(...) a(1,__VA_ARGS__) - call_a(2,3); - }''', name : 'ISO C99 varargs macros in C++') +if have_cxx + g_have_iso_cxx_varargs = cxx.compiles(''' + void some_func (void) { + int a(int p1, int p2, int p3); + #define call_a(...) a(1,__VA_ARGS__) + call_a(2,3); + }''', name : 'ISO C99 varargs macros in C++') -if g_have_iso_cxx_varargs - glibconfig_conf.set('g_have_iso_cxx_varargs', ''' -#ifdef __cplusplus -# define G_HAVE_ISO_VARARGS 1 -#endif''') + if g_have_iso_cxx_varargs + glibconfig_conf.set('g_have_iso_cxx_varargs', ''' + #ifdef __cplusplus + # define G_HAVE_ISO_VARARGS 1 + #endif''') + endif endif g_have_gnuc_varargs = cc.compiles(''' From ad7617a528dc93ec795cf2ccacbbb2336e6a4319 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Thu, 23 Dec 2021 17:43:02 +0000 Subject: [PATCH 34/38] gmain: Add a clarifying comment about exit statuses vs wait statuses Signed-off-by: Philip Withnall Helps: #2216 (cherry-picked from commit 7b93693ab3007670a3d95d6ac3cb9260c5643493) --- glib/gmain.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/glib/gmain.c b/glib/gmain.c index 94aa1152a..f33f55fd1 100644 --- a/glib/gmain.c +++ b/glib/gmain.c @@ -342,6 +342,8 @@ struct _GChildWatchSource { GSource source; GPid pid; + /* On Unix this is a wait status, which is the thing you pass to WEXITSTATUS() + * to get the status returned from the process’ main() or passed to exit(): */ gint child_status; #ifdef G_OS_WIN32 GPollFD poll; From 3be74cc6f627dfbd2af2ae24ee91c97a9accd8a8 Mon Sep 17 00:00:00 2001 From: Michael Catanzaro Date: Mon, 13 Jun 2022 12:58:46 -0500 Subject: [PATCH 35/38] gsimpleproxyresolver: default_proxy should be consistently nullable Currently it's nullable in g_simple_proxy_resolver_new(), but not in g_simple_proxy_resolver_set_default_proxy() nor the property. Fix these. (cherry-picked from commit 8a1f087a31c9fc0e50cd147d4ce11a4bfff647c0) --- gio/gsimpleproxyresolver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gio/gsimpleproxyresolver.c b/gio/gsimpleproxyresolver.c index f19d56743..6a97ba2c6 100644 --- a/gio/gsimpleproxyresolver.c +++ b/gio/gsimpleproxyresolver.c @@ -415,7 +415,7 @@ g_simple_proxy_resolver_class_init (GSimpleProxyResolverClass *resolver_class) object_class->finalize = g_simple_proxy_resolver_finalize; /** - * GSimpleProxyResolver:default-proxy: + * GSimpleProxyResolver:default-proxy: (nullable) * * The default proxy URI that will be used for any URI that doesn't * match #GSimpleProxyResolver:ignore-hosts, and doesn't match any @@ -518,7 +518,7 @@ g_simple_proxy_resolver_new (const gchar *default_proxy, /** * g_simple_proxy_resolver_set_default_proxy: * @resolver: a #GSimpleProxyResolver - * @default_proxy: the default proxy to use + * @default_proxy: (nullable): the default proxy to use * * Sets the default proxy on @resolver, to be used for any URIs that * don't match #GSimpleProxyResolver:ignore-hosts or a proxy set From b4dde579358ccddce10982222a1b35063a3c2dcb Mon Sep 17 00:00:00 2001 From: Michael Catanzaro Date: Mon, 13 Jun 2022 13:00:01 -0500 Subject: [PATCH 36/38] gsimpleproxyresolver: ensure default proxy is valid It should be either a valid URI, or NULL. Passing empty strings or other invalid URIs is no bueno. (cherry-picked from commit 6f83f45db4b859839b81f07cc942a49834663ffc) --- gio/gsimpleproxyresolver.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gio/gsimpleproxyresolver.c b/gio/gsimpleproxyresolver.c index 6a97ba2c6..4cd39604b 100644 --- a/gio/gsimpleproxyresolver.c +++ b/gio/gsimpleproxyresolver.c @@ -535,6 +535,7 @@ g_simple_proxy_resolver_set_default_proxy (GSimpleProxyResolver *resolver, const gchar *default_proxy) { g_return_if_fail (G_IS_SIMPLE_PROXY_RESOLVER (resolver)); + g_return_if_fail (default_proxy == NULL || g_uri_is_valid (default_proxy, G_URI_FLAGS_NONE, NULL)); g_free (resolver->priv->default_proxy); resolver->priv->default_proxy = g_strdup (default_proxy); From d1766e99e5e15649902a662e858fa521e9bdca22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Tue, 14 Jun 2022 23:10:16 +0200 Subject: [PATCH 37/38] GDesktopAppInfo: Ignore flushing the session bus when there's not In some cases (such as in our CI tests) we may not have any dbus session set after launching, but we always assumed so. In case we have not a session bus set, we only have to return early. (cherry-picked from commit eee15225c74559f1ba02c78175a25be186cf1cf7) --- gio/gdesktopappinfo.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c index 7d9c3daf1..994846e6c 100644 --- a/gio/gdesktopappinfo.c +++ b/gio/gdesktopappinfo.c @@ -3354,11 +3354,16 @@ launch_uris_bus_get_cb (GObject *object, g_task_return_error (task, g_steal_pointer (&error)); g_object_unref (task); } - else + else if (session_bus) g_dbus_connection_flush (session_bus, cancellable, launch_uris_flush_cb, g_steal_pointer (&task)); + else + { + g_task_return_boolean (task, TRUE); + g_clear_object (&task); + } } g_clear_object (&session_bus); From 07b062b4dc7a41774f7698976d3108d7322ae175 Mon Sep 17 00:00:00 2001 From: Rozhuk Ivan Date: Sat, 25 Jun 2022 18:46:08 +0300 Subject: [PATCH 38/38] [PATCH] Add lock in _g_get_unix_mount_points() around *fsent() functions (cherry-picked from commit f43cf341511dd684a58c09e104e28c11987cbff1) --- gio/gunixmounts.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c index 9c8ef5d66..26963d623 100644 --- a/gio/gunixmounts.c +++ b/gio/gunixmounts.c @@ -1408,17 +1408,13 @@ _g_get_unix_mount_points (void) { struct fstab *fstab = NULL; GUnixMountPoint *mount_point; - GList *return_list; + GList *return_list = NULL; + G_LOCK_DEFINE_STATIC (fsent); #ifdef HAVE_SYS_SYSCTL_H int usermnt = 0; struct stat sb; #endif - - if (!setfsent ()) - return NULL; - return_list = NULL; - #ifdef HAVE_SYS_SYSCTL_H #if defined(HAVE_SYSCTLBYNAME) { @@ -1446,7 +1442,14 @@ _g_get_unix_mount_points (void) } #endif #endif - + + G_LOCK (fsent); + if (!setfsent ()) + { + G_UNLOCK (fsent); + return NULL; + } + while ((fstab = getfsent ()) != NULL) { gboolean is_read_only = FALSE; @@ -1480,9 +1483,10 @@ _g_get_unix_mount_points (void) return_list = g_list_prepend (return_list, mount_point); } - + endfsent (); - + G_UNLOCK (fsent); + return g_list_reverse (return_list); } /* Interix {{{2 */