diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2021-10-29 10:28:40 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2021-10-29 10:28:40 +0900 |
commit | 01661d9c1888e4230ae0ea499265e70b9b436d63 (patch) | |
tree | dea19695c780ea54389db567b74727a3e3719f0e /gio | |
parent | 5457625a8c549d3f02daaa7398ebe9bca159e4fa (diff) | |
download | glib-01661d9c1888e4230ae0ea499265e70b9b436d63.tar.gz glib-01661d9c1888e4230ae0ea499265e70b9b436d63.tar.bz2 glib-01661d9c1888e4230ae0ea499265e70b9b436d63.zip |
Imported Upstream version 2.66.7upstream/2.66.7
Diffstat (limited to 'gio')
-rw-r--r-- | gio/gdbusconnection.c | 11 | ||||
-rw-r--r-- | gio/gdbusserver.c | 5 | ||||
-rw-r--r-- | gio/gkeyfilesettingsbackend.c | 14 | ||||
-rw-r--r-- | gio/gtlspassword.c | 2 | ||||
-rw-r--r-- | gio/tests/gdbus-peer.c | 187 | ||||
-rw-r--r-- | gio/tests/gsettings.c | 170 | ||||
-rw-r--r-- | gio/tests/tls-interaction.c | 55 |
7 files changed, 441 insertions, 3 deletions
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c index 633198b02..75b818069 100644 --- a/gio/gdbusconnection.c +++ b/gio/gdbusconnection.c @@ -121,6 +121,13 @@ #include "glibintl.h" +#define G_DBUS_CONNECTION_FLAGS_ALL \ + (G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | \ + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER | \ + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS | \ + G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION | \ + G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING) + /** * SECTION:gdbusconnection * @short_description: D-Bus Connections @@ -2706,6 +2713,7 @@ g_dbus_connection_new (GIOStream *stream, _g_dbus_initialize (); g_return_if_fail (G_IS_IO_STREAM (stream)); + g_return_if_fail ((flags & ~G_DBUS_CONNECTION_FLAGS_ALL) == 0); g_async_initable_new_async (G_TYPE_DBUS_CONNECTION, G_PRIORITY_DEFAULT, @@ -2793,6 +2801,7 @@ g_dbus_connection_new_sync (GIOStream *stream, { _g_dbus_initialize (); g_return_val_if_fail (G_IS_IO_STREAM (stream), NULL); + g_return_val_if_fail ((flags & ~G_DBUS_CONNECTION_FLAGS_ALL) == 0, NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); return g_initable_new (G_TYPE_DBUS_CONNECTION, cancellable, @@ -2850,6 +2859,7 @@ g_dbus_connection_new_for_address (const gchar *address, _g_dbus_initialize (); g_return_if_fail (address != NULL); + g_return_if_fail ((flags & ~G_DBUS_CONNECTION_FLAGS_ALL) == 0); g_async_initable_new_async (G_TYPE_DBUS_CONNECTION, G_PRIORITY_DEFAULT, @@ -2937,6 +2947,7 @@ g_dbus_connection_new_for_address_sync (const gchar *address, _g_dbus_initialize (); g_return_val_if_fail (address != NULL, NULL); + g_return_val_if_fail ((flags & ~G_DBUS_CONNECTION_FLAGS_ALL) == 0, NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); return g_initable_new (G_TYPE_DBUS_CONNECTION, cancellable, diff --git a/gio/gdbusserver.c b/gio/gdbusserver.c index 4a8dab0ea..64bac73ae 100644 --- a/gio/gdbusserver.c +++ b/gio/gdbusserver.c @@ -57,6 +57,10 @@ #include "glibintl.h" +#define G_DBUS_SERVER_FLAGS_ALL \ + (G_DBUS_SERVER_FLAGS_RUN_IN_THREAD | \ + G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS) + /** * SECTION:gdbusserver * @short_description: Helper for accepting connections @@ -512,6 +516,7 @@ g_dbus_server_new_sync (const gchar *address, g_return_val_if_fail (address != NULL, NULL); g_return_val_if_fail (g_dbus_is_guid (guid), NULL); + g_return_val_if_fail ((flags & ~G_DBUS_SERVER_FLAGS_ALL) == 0, NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); server = g_initable_new (G_TYPE_DBUS_SERVER, diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c index 25b057672..de216e615 100644 --- a/gio/gkeyfilesettingsbackend.c +++ b/gio/gkeyfilesettingsbackend.c @@ -158,6 +158,13 @@ convert_path (GKeyfileSettingsBackend *kfsb, last_slash = strrchr (key, '/'); + /* Disallow empty group names or key names */ + if (key_len == 0 || + (last_slash != NULL && + (*(last_slash + 1) == '\0' || + last_slash == key))) + return FALSE; + if (kfsb->root_group) { /* if a root_group was specified, make sure the user hasn't given @@ -185,7 +192,12 @@ convert_path (GKeyfileSettingsBackend *kfsb, } if (basename) - *basename = g_memdup2 (last_slash + 1, key_len - (last_slash - key)); + { + if (last_slash != NULL) + *basename = g_memdup2 (last_slash + 1, key_len - (last_slash - key)); + else + *basename = g_strdup (key); + } return TRUE; } diff --git a/gio/gtlspassword.c b/gio/gtlspassword.c index dbcec41a8..bd86a6dfe 100644 --- a/gio/gtlspassword.c +++ b/gio/gtlspassword.c @@ -291,7 +291,7 @@ g_tls_password_set_value (GTlsPassword *password, { /* FIXME: g_tls_password_set_value_full() doesn’t support unsigned gsize */ gsize length_unsigned = strlen ((gchar *) value); - g_return_if_fail (length_unsigned > G_MAXSSIZE); + g_return_if_fail (length_unsigned <= G_MAXSSIZE); length = (gssize) length_unsigned; } diff --git a/gio/tests/gdbus-peer.c b/gio/tests/gdbus-peer.c index 8450a3be7..a03ebbbbe 100644 --- a/gio/tests/gdbus-peer.c +++ b/gio/tests/gdbus-peer.c @@ -1139,6 +1139,183 @@ test_peer (void) /* ---------------------------------------------------------------------------------------------------- */ +#define VALID_GUID "0123456789abcdef0123456789abcdef" + +static void +test_peer_invalid_server (void) +{ + GDBusServer *server; + + if (!g_test_undefined ()) + { + g_test_skip ("Not exercising programming errors"); + return; + } + + if (g_test_subprocess ()) + { + /* This assumes we are not going to run out of GDBusServerFlags + * any time soon */ + server = g_dbus_server_new_sync ("tcp:", (GDBusServerFlags) (1 << 30), + VALID_GUID, + NULL, NULL, NULL); + g_assert_null (server); + } + else + { + g_test_trap_subprocess (NULL, 0, 0); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_SERVER_FLAGS_ALL*"); + } +} + +static void +test_peer_invalid_conn_stream_sync (void) +{ + GSocket *sock; + GSocketConnection *socket_conn; + GIOStream *iostream; + GDBusConnection *conn; + + if (!g_test_undefined ()) + { + g_test_skip ("Not exercising programming errors"); + return; + } + + sock = g_socket_new (G_SOCKET_FAMILY_IPV4, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_TCP, + NULL); + + if (sock == NULL) + { + g_test_skip ("TCP not available?"); + return; + } + + socket_conn = g_socket_connection_factory_create_connection (sock); + g_assert_nonnull (socket_conn); + iostream = G_IO_STREAM (socket_conn); + g_assert_nonnull (iostream); + + if (g_test_subprocess ()) + { + /* This assumes we are not going to run out of GDBusConnectionFlags + * any time soon */ + conn = g_dbus_connection_new_sync (iostream, VALID_GUID, + (GDBusConnectionFlags) (1 << 30), + NULL, NULL, NULL); + g_assert_null (conn); + } + else + { + g_test_trap_subprocess (NULL, 0, 0); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_CONNECTION_FLAGS_ALL*"); + } + + g_clear_object (&sock); + g_clear_object (&socket_conn); +} + +static void +test_peer_invalid_conn_stream_async (void) +{ + GSocket *sock; + GSocketConnection *socket_conn; + GIOStream *iostream; + + if (!g_test_undefined ()) + { + g_test_skip ("Not exercising programming errors"); + return; + } + + sock = g_socket_new (G_SOCKET_FAMILY_IPV4, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_TCP, + NULL); + + if (sock == NULL) + { + g_test_skip ("TCP not available?"); + return; + } + + socket_conn = g_socket_connection_factory_create_connection (sock); + g_assert_nonnull (socket_conn); + iostream = G_IO_STREAM (socket_conn); + g_assert_nonnull (iostream); + + if (g_test_subprocess ()) + { + g_dbus_connection_new (iostream, VALID_GUID, + (GDBusConnectionFlags) (1 << 30), + NULL, NULL, NULL, NULL); + } + else + { + g_test_trap_subprocess (NULL, 0, 0); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_CONNECTION_FLAGS_ALL*"); + } + + g_clear_object (&sock); + g_clear_object (&socket_conn); +} + +static void +test_peer_invalid_conn_addr_sync (void) +{ + GDBusConnection *conn; + + if (!g_test_undefined ()) + { + g_test_skip ("Not exercising programming errors"); + return; + } + + if (g_test_subprocess ()) + { + conn = g_dbus_connection_new_for_address_sync ("tcp:", + (GDBusConnectionFlags) (1 << 30), + NULL, NULL, NULL); + g_assert_null (conn); + } + else + { + g_test_trap_subprocess (NULL, 0, 0); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_CONNECTION_FLAGS_ALL*"); + } +} + +static void +test_peer_invalid_conn_addr_async (void) +{ + if (!g_test_undefined ()) + { + g_test_skip ("Not exercising programming errors"); + return; + } + + if (g_test_subprocess ()) + { + g_dbus_connection_new_for_address ("tcp:", + (GDBusConnectionFlags) (1 << 30), + NULL, NULL, NULL, NULL); + } + else + { + g_test_trap_subprocess (NULL, 0, 0); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_CONNECTION_FLAGS_ALL*"); + } +} + +/* ---------------------------------------------------------------------------------------------------- */ + static void test_peer_signals (void) { @@ -2010,6 +2187,16 @@ main (int argc, test_interface_introspection_data = introspection_data->interfaces[0]; g_test_add_func ("/gdbus/peer-to-peer", test_peer); + g_test_add_func ("/gdbus/peer-to-peer/invalid/server", + test_peer_invalid_server); + g_test_add_func ("/gdbus/peer-to-peer/invalid/conn/stream/async", + test_peer_invalid_conn_stream_async); + g_test_add_func ("/gdbus/peer-to-peer/invalid/conn/stream/sync", + test_peer_invalid_conn_stream_sync); + g_test_add_func ("/gdbus/peer-to-peer/invalid/conn/addr/async", + test_peer_invalid_conn_addr_async); + g_test_add_func ("/gdbus/peer-to-peer/invalid/conn/addr/sync", + test_peer_invalid_conn_addr_sync); g_test_add_func ("/gdbus/peer-to-peer/signals", test_peer_signals); g_test_add_func ("/gdbus/delayed-message-processing", delayed_message_processing); g_test_add_func ("/gdbus/nonce-tcp", test_nonce_tcp); diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c index baadca8f5..6e5a6d367 100644 --- a/gio/tests/gsettings.c +++ b/gio/tests/gsettings.c @@ -1740,6 +1740,14 @@ key_changed_cb (GSettings *settings, const gchar *key, gpointer data) (*b) = TRUE; } +typedef struct +{ + const gchar *path; + const gchar *root_group; + const gchar *keyfile_group; + const gchar *root_path; +} KeyfileTestData; + /* * Test that using a keyfile works */ @@ -1834,7 +1842,11 @@ test_keyfile (Fixture *fixture, g_free (str); g_settings_set (settings, "farewell", "s", "cheerio"); - + + /* Check that empty keys/groups are not allowed. */ + g_assert_false (g_settings_is_writable (settings, "")); + g_assert_false (g_settings_is_writable (settings, "/")); + /* When executing as root, changing the mode of the keyfile will have * no effect on the writability of the settings. */ @@ -1866,6 +1878,149 @@ test_keyfile (Fixture *fixture, g_free (keyfile_path); } +/* + * Test that using a keyfile works with a schema with no path set. + */ +static void +test_keyfile_no_path (Fixture *fixture, + gconstpointer user_data) +{ + const KeyfileTestData *test_data = user_data; + GSettingsBackend *kf_backend; + GSettings *settings; + GKeyFile *keyfile; + gboolean writable; + gchar *key = NULL; + GError *error = NULL; + gchar *keyfile_path = NULL, *store_path = NULL; + + keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL); + store_path = g_build_filename (keyfile_path, "gsettings.store", NULL); + kf_backend = g_keyfile_settings_backend_new (store_path, test_data->root_path, test_data->root_group); + settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, test_data->path); + g_object_unref (kf_backend); + + g_settings_reset (settings, "test-boolean"); + g_assert_true (g_settings_get_boolean (settings, "test-boolean")); + + writable = g_settings_is_writable (settings, "test-boolean"); + g_assert_true (writable); + g_settings_set (settings, "test-boolean", "b", FALSE); + + g_assert_false (g_settings_get_boolean (settings, "test-boolean")); + + g_settings_delay (settings); + g_settings_set (settings, "test-boolean", "b", TRUE); + g_settings_apply (settings); + + keyfile = g_key_file_new (); + g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL)); + + g_assert_true (g_key_file_get_boolean (keyfile, test_data->keyfile_group, "test-boolean", NULL)); + + g_key_file_free (keyfile); + + g_settings_reset (settings, "test-boolean"); + g_settings_apply (settings); + keyfile = g_key_file_new (); + g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL)); + + g_assert_false (g_key_file_get_string (keyfile, test_data->keyfile_group, "test-boolean", &error)); + g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND); + g_clear_error (&error); + + /* Check that empty keys/groups are not allowed. */ + g_assert_false (g_settings_is_writable (settings, "")); + g_assert_false (g_settings_is_writable (settings, "/")); + + /* Keys which ghost the root group name are not allowed. This can only be + * tested when the path is `/` as otherwise it acts as a prefix and prevents + * any ghosting. */ + if (g_str_equal (test_data->path, "/")) + { + key = g_strdup_printf ("%s/%s", test_data->root_group, ""); + g_assert_false (g_settings_is_writable (settings, key)); + g_free (key); + + key = g_strdup_printf ("%s/%s", test_data->root_group, "/"); + g_assert_false (g_settings_is_writable (settings, key)); + g_free (key); + + key = g_strdup_printf ("%s/%s", test_data->root_group, "test-boolean"); + g_assert_false (g_settings_is_writable (settings, key)); + g_free (key); + } + + g_key_file_free (keyfile); + g_object_unref (settings); + + /* Clean up the temporary directory. */ + g_assert_no_errno (g_chmod (keyfile_path, 0777)); + g_assert_no_errno (g_remove (store_path)); + g_assert_no_errno (g_rmdir (keyfile_path)); + g_free (store_path); + g_free (keyfile_path); +} + +/* + * Test that a keyfile rejects writes to keys outside its root path. + */ +static void +test_keyfile_outside_root_path (Fixture *fixture, + gconstpointer user_data) +{ + GSettingsBackend *kf_backend; + GSettings *settings; + gchar *keyfile_path = NULL, *store_path = NULL; + + keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL); + store_path = g_build_filename (keyfile_path, "gsettings.store", NULL); + kf_backend = g_keyfile_settings_backend_new (store_path, "/tests/basic-types/", "root"); + settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, "/tests/"); + g_object_unref (kf_backend); + + g_assert_false (g_settings_is_writable (settings, "test-boolean")); + + g_object_unref (settings); + + /* Clean up the temporary directory. The keyfile probably doesn’t exist, so + * don’t error on failure. */ + g_remove (store_path); + g_assert_no_errno (g_rmdir (keyfile_path)); + g_free (store_path); + g_free (keyfile_path); +} + +/* + * Test that a keyfile rejects writes to keys in the root if no root group is set. + */ +static void +test_keyfile_no_root_group (Fixture *fixture, + gconstpointer user_data) +{ + GSettingsBackend *kf_backend; + GSettings *settings; + gchar *keyfile_path = NULL, *store_path = NULL; + + keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL); + store_path = g_build_filename (keyfile_path, "gsettings.store", NULL); + kf_backend = g_keyfile_settings_backend_new (store_path, "/", NULL); + settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, "/"); + g_object_unref (kf_backend); + + g_assert_false (g_settings_is_writable (settings, "test-boolean")); + g_assert_true (g_settings_is_writable (settings, "child/test-boolean")); + + g_object_unref (settings); + + /* Clean up the temporary directory. The keyfile probably doesn’t exist, so + * don’t error on failure. */ + g_remove (store_path); + g_assert_no_errno (g_rmdir (keyfile_path)); + g_free (store_path); + g_free (keyfile_path); +} + /* Test that getting child schemas works */ static void @@ -2844,6 +2999,14 @@ main (int argc, char *argv[]) gchar *override_text; gchar *enums; gint result; + const KeyfileTestData keyfile_test_data_explicit_path = { "/tests/", "root", "tests", "/" }; + const KeyfileTestData keyfile_test_data_empty_path = { "/", "root", "root", "/" }; + const KeyfileTestData keyfile_test_data_long_path = { + "/tests/path/is/very/long/and/this/makes/some/comparisons/take/a/different/branch/", + "root", + "tests/path/is/very/long/and/this/makes/some/comparisons/take/a/different/branch", + "/" + }; /* Meson build sets this */ #ifdef TEST_LOCALE_PATH @@ -2967,6 +3130,11 @@ main (int argc, char *argv[]) } g_test_add ("/gsettings/keyfile", Fixture, NULL, setup, test_keyfile, teardown); + g_test_add ("/gsettings/keyfile/explicit-path", Fixture, &keyfile_test_data_explicit_path, setup, test_keyfile_no_path, teardown); + g_test_add ("/gsettings/keyfile/empty-path", Fixture, &keyfile_test_data_empty_path, setup, test_keyfile_no_path, teardown); + g_test_add ("/gsettings/keyfile/long-path", Fixture, &keyfile_test_data_long_path, setup, test_keyfile_no_path, teardown); + g_test_add ("/gsettings/keyfile/outside-root-path", Fixture, NULL, setup, test_keyfile_outside_root_path, teardown); + g_test_add ("/gsettings/keyfile/no-root-group", Fixture, NULL, setup, test_keyfile_no_root_group, teardown); g_test_add_func ("/gsettings/child-schema", test_child_schema); g_test_add_func ("/gsettings/strinfo", test_strinfo); g_test_add_func ("/gsettings/enums", test_enums); diff --git a/gio/tests/tls-interaction.c b/gio/tests/tls-interaction.c index 4f0737d7e..5661e8e0d 100644 --- a/gio/tests/tls-interaction.c +++ b/gio/tests/tls-interaction.c @@ -174,6 +174,38 @@ test_interaction_ask_password_finish_failure (GTlsInteraction *interaction, } +/* Return a copy of @str that is allocated in a silly way, to exercise + * custom free-functions. The returned pointer points to a copy of @str + * in a buffer of the form "BEFORE \0 str \0 AFTER". */ +static guchar * +special_dup (const char *str) +{ + GString *buf = g_string_new ("BEFORE"); + guchar *ret; + + g_string_append_c (buf, '\0'); + g_string_append (buf, str); + g_string_append_c (buf, '\0'); + g_string_append (buf, "AFTER"); + ret = (guchar *) g_string_free (buf, FALSE); + return ret + strlen ("BEFORE") + 1; +} + + +/* Free a copy of @str that was made with special_dup(), after asserting + * that it has not been corrupted. */ +static void +special_free (gpointer p) +{ + gchar *s = p; + gchar *buf = s - strlen ("BEFORE") - 1; + + g_assert_cmpstr (buf, ==, "BEFORE"); + g_assert_cmpstr (s + strlen (s) + 1, ==, "AFTER"); + g_free (buf); +} + + static GTlsInteractionResult test_interaction_ask_password_sync_success (GTlsInteraction *interaction, GTlsPassword *password, @@ -181,6 +213,8 @@ test_interaction_ask_password_sync_success (GTlsInteraction *interaction, GError **error) { TestInteraction *self; + const guchar *value; + gsize len; g_assert (TEST_IS_INTERACTION (interaction)); self = TEST_INTERACTION (interaction); @@ -192,6 +226,27 @@ test_interaction_ask_password_sync_success (GTlsInteraction *interaction, g_assert (error != NULL); g_assert (*error == NULL); + /* Exercise different ways to set the value */ + g_tls_password_set_value (password, (const guchar *) "foo", 4); + len = 0; + value = g_tls_password_get_value (password, &len); + g_assert_cmpmem (value, len, "foo", 4); + + g_tls_password_set_value (password, (const guchar *) "bar", -1); + len = 0; + value = g_tls_password_get_value (password, &len); + g_assert_cmpmem (value, len, "bar", 3); + + g_tls_password_set_value_full (password, special_dup ("baa"), 4, special_free); + len = 0; + value = g_tls_password_get_value (password, &len); + g_assert_cmpmem (value, len, "baa", 4); + + g_tls_password_set_value_full (password, special_dup ("baz"), -1, special_free); + len = 0; + value = g_tls_password_get_value (password, &len); + g_assert_cmpmem (value, len, "baz", 3); + /* Don't do this in real life. Include a null terminator for testing */ g_tls_password_set_value (password, (const guchar *)"the password", 13); return G_TLS_INTERACTION_HANDLED; |