diff --git a/cfg/gtk.cfg b/cfg/gtk.cfg
index 024f567c922..2c02c567f30 100644
--- a/cfg/gtk.cfg
+++ b/cfg/gtk.cfg
@@ -717,6 +717,12 @@
g_variant_type_dup_string
g_value_dup_string
+
+
+
+
+
+
g_free
@@ -4237,7 +4243,6 @@
-
false
@@ -4249,7 +4254,6 @@
-
false
@@ -5652,7 +5656,6 @@
-
false
@@ -5669,7 +5672,6 @@
-
false
diff --git a/test/cfg/gtk.c b/test/cfg/gtk.c
index 2612b572638..1a19e6c9929 100644
--- a/test/cfg/gtk.c
+++ b/test/cfg/gtk.c
@@ -730,3 +730,45 @@ int g_define_enum_and_flags_type_test(void) {
return e + f;
}
#endif
+
+static gboolean source_func_frees_data(gpointer data)
+{
+ g_free(data);
+ return FALSE;
+}
+
+static void destroy_notify_frees_data(gpointer data)
+{
+ g_free(data);
+}
+
+// The data passed to a GSource is owned by the callback or the destroy notify
+// from then on, so it does not leak.
+void g_idle_add_takes_data_test(void)
+{
+ // cppcheck-suppress constVariablePointer
+ gchar *data = g_strdup("data");
+ g_idle_add(source_func_frees_data, data);
+
+ gchar *data_full = g_strdup("data");
+ g_idle_add_full(200, source_func_frees_data, data_full, NULL);
+}
+
+void g_timeout_add_takes_data_test(void)
+{
+ // cppcheck-suppress constVariablePointer
+ gchar *data = g_strdup("data");
+ g_timeout_add(10, source_func_frees_data, data);
+
+ // cppcheck-suppress constVariablePointer
+ gchar *data_seconds = g_strdup("data");
+ g_timeout_add_seconds(1, source_func_frees_data, data_seconds);
+
+ // cppcheck-suppress constVariablePointer
+ gchar *data_full = g_strdup("data");
+ g_timeout_add_full(0, 10, source_func_frees_data, data_full, destroy_notify_frees_data);
+
+ // cppcheck-suppress constVariablePointer
+ gchar *data_seconds_full = g_strdup("data");
+ g_timeout_add_seconds_full(0, 1, source_func_frees_data, data_seconds_full, destroy_notify_frees_data);
+}