+Overview of changes in GLib 2.66.7
+==================================
+
+* Fix various regressions caused by rushed security fixes in 2.66.6
+ (work by Simon McVittie and Jan Alexander Steffens) (!1933, !1943)
+
+* Fix a silent integer truncation when calling `g_byte_array_new_take()` for
+ byte arrays bigger than `G_MAXUINT` (work by Krzesimir Nowak) (!1944)
+
+* Disallow using currently-undefined D-Bus connection or server flags to prevent
+ forward-compatibility problems with new security-sensitive flags likely to be
+ released in GLib 2.68 (work by Simon McVittie) (!1945)
+
+* Bugs fixed:
+ - !1933 [2.66] Fix regressions in 2.66.6 where negative gssize indicates strlen()
+ - !1943 Backport !1941 “gkeyfilesettingsbackend: Fix basename handling when group is unset” to glib-2-66
+ - !1944 Backport !1942 “gbytearray: Do not accept too large byte arrays” to glib-2-66
+ - !1945 Backport !1934 “gdbus: Reject attempts to set future connection or server flags” to glib-2-66
+
+
Overview of changes in GLib 2.66.6
==================================
#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
_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,
{
_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,
_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,
_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,
#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
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,
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
}
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;
}
{
/* 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;
}
/* ---------------------------------------------------------------------------------------------------- */
+#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)
{
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);
(*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
*/
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.
*/
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
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
}
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);
}
+/* 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,
GError **error)
{
TestInteraction *self;
+ const guchar *value;
+ gsize len;
g_assert (TEST_IS_INTERACTION (interaction));
self = TEST_INTERACTION (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;
* Create byte array containing the data. The data will be owned by the array
* and will be freed with g_free(), i.e. it could be allocated using g_strdup().
*
+ * Do not use it if @len is greater than %G_MAXUINT. #GByteArray
+ * stores the length of its data in #guint, which may be shorter than
+ * #gsize.
+ *
* Since: 2.32
*
* Returns: (transfer full): a new #GByteArray
GByteArray *array;
GRealArray *real;
+ g_return_val_if_fail (len <= G_MAXUINT, NULL);
+
array = g_byte_array_new ();
real = (GRealArray *)array;
g_assert (real->data == NULL);
* g_bytes_new(), g_bytes_new_take() or g_byte_array_free_to_bytes(). In all
* other cases the data is copied.
*
+ * Do not use it if @bytes contains more than %G_MAXUINT
+ * bytes. #GByteArray stores the length of its data in #guint, which
+ * may be shorter than #gsize, that @bytes is using.
+ *
* Returns: (transfer full): a new mutable #GByteArray containing the same byte data
*
* Since: 2.32
{
/* FIXME: We’re constrained by line_term_len being a guint here */
gsize length_size = strlen (line_term);
- g_return_if_fail (length_size > G_MAXUINT);
+ g_return_if_fail (length_size <= G_MAXUINT);
length_unsigned = (guint) length_size;
}
g_free (channel->line_term);
channel->line_term = line_term ? g_memdup2 (line_term, length_unsigned) : NULL;
- channel->line_term_len = length;
+ channel->line_term_len = length_unsigned;
}
/**
*/
#undef G_DISABLE_ASSERT
-#undef G_LOG_DOMAIN
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "glib.h"
+#include "glib/gstrfuncsprivate.h"
/* Keep in sync with glib/gbytes.c */
struct _GBytes
}
static void
+test_to_array_transferred_oversize (void)
+{
+ g_test_message ("g_bytes_unref_to_array() can only take GBytes up to "
+ "G_MAXUINT in length; test that longer ones are rejected");
+
+ if (sizeof (guint) >= sizeof (gsize))
+ {
+ g_test_skip ("Skipping test as guint is not smaller than gsize");
+ }
+ else if (g_test_undefined ())
+ {
+ GByteArray *array = NULL;
+ GBytes *bytes = NULL;
+ gpointer data = g_memdup2 (NYAN, N_NYAN);
+ gsize len = ((gsize) G_MAXUINT) + 1;
+
+ bytes = g_bytes_new_take (data, len);
+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
+ "g_byte_array_new_take: assertion 'len <= G_MAXUINT' failed");
+ array = g_bytes_unref_to_array (g_steal_pointer (&bytes));
+ g_test_assert_expected_messages ();
+ g_assert_null (array);
+
+ g_free (data);
+ }
+ else
+ {
+ g_test_skip ("Skipping test as testing undefined behaviour is disabled");
+ }
+}
+
+static void
test_to_array_two_refs (void)
{
gconstpointer memory;
g_test_add_func ("/bytes/to-data/two-refs", test_to_data_two_refs);
g_test_add_func ("/bytes/to-data/non-malloc", test_to_data_non_malloc);
g_test_add_func ("/bytes/to-array/transferred", test_to_array_transferred);
+ g_test_add_func ("/bytes/to-array/transferred/oversize", test_to_array_transferred_oversize);
g_test_add_func ("/bytes/to-array/two-refs", test_to_array_two_refs);
g_test_add_func ("/bytes/to-array/non-malloc", test_to_array_non_malloc);
g_test_add_func ("/bytes/null", test_null);
channel = g_io_channel_new_file (filename, "r", &local_error);
g_assert_no_error (local_error);
- /* Only break on newline characters, not nuls. */
- g_io_channel_set_line_term (channel, "\n", 1);
+ /* Only break on newline characters, not nuls.
+ * Use length -1 here to exercise glib#2323; the case where length > 0
+ * is covered in glib/tests/protocol.c. */
+ g_io_channel_set_line_term (channel, "\n", -1);
g_io_channel_set_encoding (channel, NULL, &local_error);
g_assert_no_error (local_error);
project('glib', 'c', 'cpp',
- version : '2.66.6',
+ version : '2.66.7',
# NOTE: We keep this pinned at 0.49 because that's what Debian 10 ships
meson_version : '>= 0.49.2',
default_options : [