diff --git a/gio/tests/gdbus-connection.c b/gio/tests/gdbus-connection.c index 8d37af83bf03ebcf57193e43a221d4dc77ba73c1..9f44a2e519e72f94b50c2e62b4332ed51312bd5e 100644 --- a/gio/tests/gdbus-connection.c +++ b/gio/tests/gdbus-connection.c @@ -539,7 +539,7 @@ test_connection_signal_handler (GDBusConnection *connection, /* We defer quitting to a G_PRIORITY_DEFAULT_IDLE function so other queued signal * callbacks have a chance to run first. They get dispatched with a higher priority - * of G_PIORITY_DEFAULT, so as long as the queue is non-empty g_main_loop_quit won't + * of G_PRIORITY_DEFAULT, so as long as the queue is non-empty g_main_loop_quit won't * run */ g_idle_add_once ((GSourceOnceFunc) g_main_loop_quit, loop); diff --git a/gio/tests/gdbus-export.c b/gio/tests/gdbus-export.c index 599df5bb56ec9923138915bcdc21e19e495cfdd0..6acfe504019ff5c3ce842ee667031dcad5488491 100644 --- a/gio/tests/gdbus-export.c +++ b/gio/tests/gdbus-export.c @@ -1928,6 +1928,17 @@ test_threaded_unregistration_iteration (gboolean subtree) g_clear_object (&call_result); g_clear_object (&data.connection); + /* We defer quitting to a G_PRIORITY_DEFAULT_IDLE function so other queued + * signal callbacks have a chance to run first. + * In particular we want to ensure that all calls to on_object_unregistered() + * are delivered here before we end this function, so that there won't be any + * invalid stack access. + * They get dispatched with a higher priority (G_PRIORITY_DEFAULT), so as + * long as the queue is non-empty g_main_loop_quit won't run + */ + g_idle_add_once ((GSourceOnceFunc) g_main_loop_quit, loop); + g_main_loop_run (loop); + return unregistration_was_first; } diff --git a/girepository/compiler/compiler.c b/girepository/compiler/compiler.c index e9b1b15631d2e1ab435e4e0dc793bddee9d47158..dcbbbe66f1019ece75e60530e4f2f000b1610660 100644 --- a/girepository/compiler/compiler.c +++ b/girepository/compiler/compiler.c @@ -219,6 +219,7 @@ main (int argc, char **argv) g_fprintf (stderr, "%s\n", message); g_free (message); gi_ir_parser_free (parser); + g_error_free (error); return 1; } @@ -229,6 +230,7 @@ main (int argc, char **argv) { GITypelib *typelib = NULL; + int write_successful; if (shlibs) { @@ -246,10 +248,14 @@ main (int argc, char **argv) g_error (_("Invalid typelib for module ā€˜%s’: %s"), module->name, error->message); - if (!write_out_typelib (NULL, typelib)) - return 1; - + write_successful = write_out_typelib (NULL, typelib); g_clear_pointer (&typelib, gi_typelib_unref); + + if (!write_successful) + { + gi_ir_parser_free (parser); + return 1; + } } g_debug ("[building] done"); diff --git a/girepository/girparser.c b/girepository/girparser.c index 0cf341533aca773bbc792d643858af2e70ae10bf..adb9db7f976369eed86a50113c5663315f8b1448 100644 --- a/girepository/girparser.c +++ b/girepository/girparser.c @@ -2309,7 +2309,7 @@ end_type_top (ParseContext *ctx) if (!ctx->type_parameters) goto out; - typenode = (GIIrNodeType*)ctx->type_parameters->data; + typenode = (GIIrNodeType *) g_steal_pointer (&ctx->type_parameters->data); /* Default to pointer for unspecified containers */ if (typenode->tag == GI_TYPE_TAG_ARRAY || @@ -2333,32 +2333,32 @@ end_type_top (ParseContext *ctx) case GI_IR_NODE_PARAM: { GIIrNodeParam *param = (GIIrNodeParam *)ctx->current_typed; - param->type = typenode; + param->type = g_steal_pointer (&typenode); } break; case GI_IR_NODE_FIELD: { GIIrNodeField *field = (GIIrNodeField *)ctx->current_typed; - field->type = typenode; + field->type = g_steal_pointer (&typenode); } break; case GI_IR_NODE_PROPERTY: { GIIrNodeProperty *property = (GIIrNodeProperty *) ctx->current_typed; - property->type = typenode; + property->type = g_steal_pointer (&typenode); } break; case GI_IR_NODE_CONSTANT: { GIIrNodeConstant *constant = (GIIrNodeConstant *)ctx->current_typed; - constant->type = typenode; + constant->type = g_steal_pointer (&typenode); } break; default: g_printerr("current node is %d\n", CURRENT_NODE (ctx)->type); g_assert_not_reached (); } - g_list_free (ctx->type_parameters); + g_list_free_full (ctx->type_parameters, (GDestroyNotify) gi_ir_node_free); out: ctx->type_depth = 0; @@ -2374,7 +2374,7 @@ end_type_recurse (ParseContext *ctx) parent = (GIIrNodeType *) ((GList*)ctx->type_stack->data)->data; if (ctx->type_parameters) - param = (GIIrNodeType *) ctx->type_parameters->data; + param = (GIIrNodeType *) g_steal_pointer (&ctx->type_parameters->data); if (parent->tag == GI_TYPE_TAG_ARRAY || parent->tag == GI_TYPE_TAG_GLIST || @@ -2383,7 +2383,7 @@ end_type_recurse (ParseContext *ctx) g_assert (param != NULL); if (parent->parameter_type1 == NULL) - parent->parameter_type1 = param; + parent->parameter_type1 = g_steal_pointer (¶m); else g_assert_not_reached (); } @@ -2392,13 +2392,14 @@ end_type_recurse (ParseContext *ctx) g_assert (param != NULL); if (parent->parameter_type1 == NULL) - parent->parameter_type1 = param; + parent->parameter_type1 = g_steal_pointer (¶m); else if (parent->parameter_type2 == NULL) - parent->parameter_type2 = param; + parent->parameter_type2 = g_steal_pointer (¶m); else g_assert_not_reached (); } - g_list_free (ctx->type_parameters); + g_clear_pointer ((GIIrNode **) ¶m, gi_ir_node_free); + g_list_free_full (ctx->type_parameters, (GDestroyNotify) gi_ir_node_free); ctx->type_parameters = (GList *)ctx->type_stack->data; ctx->type_stack = g_list_delete_link (ctx->type_stack, ctx->type_stack); } diff --git a/girepository/tests/callable-info.c b/girepository/tests/callable-info.c index ee23d2e62fb801b8f4c830b4034046e617f2361a..69fd5e940762517e6d9255414e4b505312774e03 100644 --- a/girepository/tests/callable-info.c +++ b/girepository/tests/callable-info.c @@ -199,6 +199,7 @@ test_callable_info_static_vfunc (RepositoryFixture *fx, if (!vfunc_info) { g_test_skip ("g-ir-scanner is not new enough"); + gi_base_info_unref (info); return; } g_assert_nonnull (vfunc_info); diff --git a/glib/gbytes.c b/glib/gbytes.c index 1fd3078d9b7bf9221e1f3902ce7b9571a50bb4da..35fc3829d04f909888c325d0a9dcac647404bfee 100644 --- a/glib/gbytes.c +++ b/glib/gbytes.c @@ -123,12 +123,19 @@ g_bytes_new (gconstpointer data, { g_return_val_if_fail (data != NULL || size == 0, NULL); + if (data == NULL || size == 0) + { + g_assert (data != NULL || size == 0); + + return g_bytes_new_with_free_func (NULL, size, NULL, NULL); + } + if (size <= G_BYTES_MAX_INLINE) { GBytesInline *bytes; bytes = g_malloc (sizeof *bytes + size); - bytes->bytes.data = (data != NULL && size > 0) ? bytes->inline_data : NULL; + bytes->bytes.data = bytes->inline_data; bytes->bytes.size = size; bytes->bytes.free_func = NULL; bytes->bytes.user_data = NULL; diff --git a/glib/gcharset.c b/glib/gcharset.c index b0a4b9cc019abe6c11b31034d2d9fc6479ea8ac2..939ff596de8257072512d7b488940fed47aef631 100644 --- a/glib/gcharset.c +++ b/glib/gcharset.c @@ -26,6 +26,7 @@ #include "garray.h" #include "genviron.h" #include "ghash.h" +#include "glib-private.h" #include "gmessages.h" #include "gstrfuncs.h" #include "gthread.h" @@ -807,6 +808,7 @@ g_get_language_names_with_category (const gchar *category_name) cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, language_names_cache_free); g_private_set (&cache_private, cache); + g_ignore_leak (cache); } languages = guess_category_value (category_name); @@ -835,6 +837,7 @@ g_get_language_names_with_category (const gchar *category_name) name_cache->languages = g_strdup (languages); name_cache->language_names = (gchar **) g_ptr_array_free (array, FALSE); g_hash_table_insert (cache, g_strdup (category_name), name_cache); + g_ignore_leak (name_cache); } return (const gchar * const *) name_cache->language_names; diff --git a/glib/glib-private.h b/glib/glib-private.h index 3417dfaf62a66cbbefa135a5e310a839de0f5b6d..4dd0c2020a7f8e00888a8e96a0ba00203cf47bee 100644 --- a/glib/glib-private.h +++ b/glib/glib-private.h @@ -100,7 +100,7 @@ g_leak_sanitizer_is_supported (void) #if defined (_GLIB_ADDRESS_SANITIZER) return TRUE; #elif defined (HAS_DYNAMIC_ASAN_LOADING) - return __lsan_enable != NULL && __lsan_ignore_object != NULL; + return G_UNLIKELY (__lsan_enable != NULL && __lsan_ignore_object != NULL); #else return FALSE; #endif @@ -122,7 +122,7 @@ g_ignore_leak (gconstpointer p) if (p != NULL) __lsan_ignore_object (p); #elif defined (HAS_DYNAMIC_ASAN_LOADING) - if (p != NULL && __lsan_ignore_object != NULL) + if (G_LIKELY (p != NULL) && G_UNLIKELY (__lsan_ignore_object != NULL)) __lsan_ignore_object (p); #endif } @@ -166,7 +166,7 @@ g_begin_ignore_leaks (void) #if defined (_GLIB_ADDRESS_SANITIZER) __lsan_disable (); #elif defined (HAS_DYNAMIC_ASAN_LOADING) - if (__lsan_disable != NULL) + if (G_UNLIKELY (__lsan_disable != NULL)) __lsan_disable (); #endif } @@ -183,7 +183,7 @@ g_end_ignore_leaks (void) #if defined (_GLIB_ADDRESS_SANITIZER) __lsan_enable (); #elif defined (HAS_DYNAMIC_ASAN_LOADING) - if (__lsan_enable != NULL) + if (G_UNLIKELY (__lsan_enable != NULL)) __lsan_enable (); #endif } diff --git a/glib/gmessages.c b/glib/gmessages.c index 8393617181f2057c2adde870edd609cdc0d8fcd1..cfea3d7843524322d25db22655f8f747fde09fb2 100644 --- a/glib/gmessages.c +++ b/glib/gmessages.c @@ -2778,6 +2778,8 @@ should_drop_message (GLogLevelFlags log_level, if (log_domain == NULL) { + log_domain_length = 0; + for (i = 0; i < n_fields; i++) { if (g_strcmp0 (fields[i].key, "GLIB_DOMAIN") == 0) diff --git a/glib/gthread.c b/glib/gthread.c index b587181325000a2e577b40add1427386d6338e25..8354c01e5d150f26423c2444f0f815b0c0944f55 100644 --- a/glib/gthread.c +++ b/glib/gthread.c @@ -40,6 +40,7 @@ #include "config.h" +#include "glib-private.h" #include "gthread.h" #include "gthreadprivate.h" @@ -505,10 +506,11 @@ static GPrivate g_thread_specific_private = G_PRIVATE_INIT (g_thread_cleanup * * Sets the thread local variable @key to have a newly-allocated and zero-filled * value of given @size, and returns a pointer to that memory. Allocations made - * using this API will be suppressed in valgrind: it is intended to be used for - * one-time allocations which are known to be leaked, such as those for - * per-thread initialisation data. Otherwise, this function behaves the same as - * g_private_set(). + * using this API will be suppressed in valgrind (when the GLib default + * suppression file, `glib.supp`, is used) and leak sanitizer: it is intended to + * be used for one-time allocations which are known to be leaked, such as those + * for per-thread initialisation data. Otherwise, this function behaves the same + * as g_private_set(). * * Returns: (transfer full): new thread-local heap allocation of size @size * Since: 2.60 @@ -520,6 +522,7 @@ g_private_set_alloc0 (GPrivate *key, { gpointer allocated = g_malloc0 (size); + g_ignore_leak (allocated); g_private_set (key, allocated); return g_steal_pointer (&allocated); diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c index 4ee62889b17a6c88c8a0f4688571305ac8aae07c..69680f45e9cab80908c5039d50e47de8fdeeaaa9 100644 --- a/glib/gvariant-core.c +++ b/glib/gvariant-core.c @@ -1415,6 +1415,8 @@ void g_variant_store (GVariant *value, gpointer data) { + g_return_if_fail (data != NULL); + g_variant_lock (value); if (value->state & STATE_SERIALISED) diff --git a/glib/gvariant.c b/glib/gvariant.c index bdcbe412b745e41e666e819621c1a0b4642098cc..c6970296544ee8c57508861948ef35dcf7a13e42 100644 --- a/glib/gvariant.c +++ b/glib/gvariant.c @@ -6187,12 +6187,16 @@ g_variant_byteswap (GVariant *value) GVariantTypeInfo *type_info; guint alignment; GVariant *new; + gsize size = 0; type_info = g_variant_get_type_info (value); g_variant_type_info_query (type_info, &alignment, NULL); - if (alignment && g_variant_is_normal_form (value)) + if (alignment) + size = g_variant_get_size (value); + + if (size > 0 && g_variant_is_normal_form (value)) { /* (potentially) contains multi-byte numeric data, but is also already in * normal form so we can use a faster byteswapping codepath on the @@ -6201,7 +6205,7 @@ g_variant_byteswap (GVariant *value) GBytes *bytes; serialised.type_info = g_variant_get_type_info (value); - serialised.size = g_variant_get_size (value); + serialised.size = size; serialised.data = g_malloc (serialised.size); serialised.depth = g_variant_get_depth (value); serialised.ordered_offsets_up_to = G_MAXSIZE; /* operating on the normal form */ diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c index 12a35dad95dbfb2dd7a52db651cad6b2fc7dffde..8e17130465f4fe8339a27b1fdc915533e273e3e0 100644 --- a/glib/tests/gvariant.c +++ b/glib/tests/gvariant.c @@ -2327,7 +2327,15 @@ test_byteswap (void) * often makes something non-normal but still readable. */ three_size_copy = three.size + 1; three_data_copy = g_malloc (three_size_copy); - memcpy (three_data_copy, three.data, three.size); + if (three.data) + { + g_assert_cmpuint (three.size, !=, 0); + memcpy (three_data_copy, three.data, three.size); + } + else + { + g_assert_cmpuint (three.size, ==, 0); + } three_data_copy[three.size] = '\0'; three_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (three.type_info)), @@ -2367,6 +2375,19 @@ test_byteswaps (void) g_variant_type_info_assert_no_infos (); } +static void +test_byteswap_zero_sized (void) +{ + GVariant *variant; + GVariant *swapped; + + variant = g_variant_new_from_data (G_VARIANT_TYPE_STRING, NULL, 0, TRUE, NULL, NULL); + swapped = g_variant_byteswap (variant); + + g_variant_unref (variant); + g_variant_unref (swapped); +} + static void test_serialiser_children (void) { @@ -5939,6 +5960,7 @@ main (int argc, char **argv) g_test_add_func ("/gvariant/serialiser/variant", test_variants); g_test_add_func ("/gvariant/serialiser/strings", test_strings); g_test_add_func ("/gvariant/serialiser/byteswap", test_byteswaps); + g_test_add_func ("/gvariant/serialiser/byteswap/zero-sized", test_byteswap_zero_sized); g_test_add_func ("/gvariant/serialiser/children", test_serialiser_children); for (i = 1; i <= 20; i += 4)