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/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 * 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); 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); diff --git a/gio/gdbusauthmechanismexternal.c b/gio/gdbusauthmechanismexternal.c index b3f21175b..70aaddc74 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); @@ -198,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') @@ -251,7 +262,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 +299,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 * diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c index 60d6debb2..994846e6c 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)); @@ -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); } @@ -3280,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); } @@ -3347,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); 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: diff --git a/gio/gioerror.c b/gio/gioerror.c index 38fc3d83f..7566c49db 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; @@ -211,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; 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)) 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)) diff --git a/gio/gsimpleproxyresolver.c b/gio/gsimpleproxyresolver.c index f19d56743..4cd39604b 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 @@ -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); 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. */ 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; } 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 */ 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 (); } 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..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' : {}, @@ -86,10 +83,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' : {}, @@ -122,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/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 (); +} 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) 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 */ diff --git a/glib/glib-unix.c b/glib/glib-unix.c index fd799eaf7..9a148cb8f 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 * @@ -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/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; 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(). * 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; } } diff --git a/glib/gthread-posix.c b/glib/gthread-posix.c index 8e2e66db5..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) @@ -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); 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); 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 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/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); 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/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); } 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 diff --git a/gobject/gsignal.c b/gobject/gsignal.c index fb85fd6ba..aeaf24407 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(). * @@ -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 (); } 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/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) { 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('''