mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-07-03 13:16:04 +00:00
tracers: leaks: fix potentially invalid memory access when trying to detect object type
The is_gst_mini_object_check would sometimes detect a proper GObject as a mini object, and then bad things happen. We know whether a pointer is a proper GObject or a MiniObject here though, so just pass that information to the right code paths and avoid the heuristics altogether. Eliminates all remaining uses of object_is_gst_mini_object(). Fixes #1334 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2832>
This commit is contained in:
parent
5a055ae70a
commit
75bdd2b7eb
|
@ -131,7 +131,7 @@ typedef struct
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
gchar *creation_trace;
|
gchar *creation_trace;
|
||||||
|
ObjectKind kind;
|
||||||
GList *refing_infos;
|
GList *refing_infos;
|
||||||
} ObjectRefingInfos;
|
} ObjectRefingInfos;
|
||||||
|
|
||||||
|
@ -321,13 +321,6 @@ typedef struct
|
||||||
const gchar *type_name;
|
const gchar *type_name;
|
||||||
} ObjectLog;
|
} ObjectLog;
|
||||||
|
|
||||||
static inline gboolean
|
|
||||||
object_is_gst_mini_object (gpointer obj)
|
|
||||||
{
|
|
||||||
return (G_TYPE_IS_DERIVED (GST_MINI_OBJECT_TYPE (obj)) &&
|
|
||||||
G_TYPE_FUNDAMENTAL (GST_MINI_OBJECT_TYPE (obj)) == G_TYPE_BOXED);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ObjectLog *
|
static ObjectLog *
|
||||||
object_log_new (gpointer obj, ObjectKind kind)
|
object_log_new (gpointer obj, ObjectKind kind)
|
||||||
{
|
{
|
||||||
|
@ -393,20 +386,27 @@ mini_object_weak_cb (gpointer data, GstMiniObject * object)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_object_created (GstLeaksTracer * self, gpointer object, GType type,
|
handle_object_created (GstLeaksTracer * self, gpointer object, GType type,
|
||||||
gboolean gobject)
|
ObjectKind kind)
|
||||||
{
|
{
|
||||||
ObjectKind kind = gobject ? GOBJECT : MINI_OBJECT; // FIXME: change arg to pass directly
|
|
||||||
ObjectRefingInfos *infos;
|
ObjectRefingInfos *infos;
|
||||||
|
|
||||||
if (!should_handle_object_type (self, type))
|
if (!should_handle_object_type (self, type))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
infos = g_malloc0 (sizeof (ObjectRefingInfos));
|
infos = g_malloc0 (sizeof (ObjectRefingInfos));
|
||||||
if (gobject)
|
infos->kind = kind;
|
||||||
g_object_weak_ref ((GObject *) object, object_weak_cb, self);
|
switch (kind) {
|
||||||
else
|
case GOBJECT:
|
||||||
gst_mini_object_weak_ref (GST_MINI_OBJECT_CAST (object),
|
g_object_weak_ref ((GObject *) object, object_weak_cb, self);
|
||||||
mini_object_weak_cb, self);
|
break;
|
||||||
|
case MINI_OBJECT:
|
||||||
|
gst_mini_object_weak_ref (GST_MINI_OBJECT_CAST (object),
|
||||||
|
mini_object_weak_cb, self);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
GST_OBJECT_LOCK (self);
|
GST_OBJECT_LOCK (self);
|
||||||
if ((gint) self->trace_flags != -1)
|
if ((gint) self->trace_flags != -1)
|
||||||
|
@ -425,7 +425,8 @@ mini_object_created_cb (GstTracer * tracer, GstClockTime ts,
|
||||||
{
|
{
|
||||||
GstLeaksTracer *self = GST_LEAKS_TRACER_CAST (tracer);
|
GstLeaksTracer *self = GST_LEAKS_TRACER_CAST (tracer);
|
||||||
|
|
||||||
handle_object_created (self, object, GST_MINI_OBJECT_TYPE (object), FALSE);
|
handle_object_created (self, object, GST_MINI_OBJECT_TYPE (object),
|
||||||
|
MINI_OBJECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -438,7 +439,7 @@ object_created_cb (GstTracer * tracer, GstClockTime ts, GstObject * object)
|
||||||
if (g_type_is_a (object_type, GST_TYPE_TRACER))
|
if (g_type_is_a (object_type, GST_TYPE_TRACER))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
handle_object_created (self, object, object_type, TRUE);
|
handle_object_created (self, object, object_type, GOBJECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -615,18 +616,25 @@ create_leaks_list (GstLeaksTracer * self)
|
||||||
GType type;
|
GType type;
|
||||||
guint ref_count;
|
guint ref_count;
|
||||||
|
|
||||||
if (object_is_gst_mini_object (obj)) {
|
switch (((ObjectRefingInfos *) infos)->kind) {
|
||||||
if (GST_MINI_OBJECT_FLAG_IS_SET (obj, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED))
|
case GOBJECT:
|
||||||
continue;
|
if (GST_OBJECT_FLAG_IS_SET (obj, GST_OBJECT_FLAG_MAY_BE_LEAKED))
|
||||||
|
continue;
|
||||||
|
|
||||||
type = GST_MINI_OBJECT_TYPE (obj);
|
type = G_OBJECT_TYPE (obj);
|
||||||
ref_count = ((GstMiniObject *) obj)->refcount;
|
ref_count = ((GObject *) obj)->ref_count;
|
||||||
} else {
|
break;
|
||||||
if (GST_OBJECT_FLAG_IS_SET (obj, GST_OBJECT_FLAG_MAY_BE_LEAKED))
|
case MINI_OBJECT:
|
||||||
continue;
|
if (GST_MINI_OBJECT_FLAG_IS_SET (obj,
|
||||||
|
GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED))
|
||||||
|
continue;
|
||||||
|
|
||||||
type = G_OBJECT_TYPE (obj);
|
type = GST_MINI_OBJECT_TYPE (obj);
|
||||||
ref_count = ((GObject *) obj)->ref_count;
|
ref_count = ((GstMiniObject *) obj)->refcount;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
l = g_list_prepend (l, leak_new (obj, type, ref_count, infos));
|
l = g_list_prepend (l, leak_new (obj, type, ref_count, infos));
|
||||||
|
@ -660,10 +668,17 @@ process_leak (Leak * leak, GValue * ret_leaks)
|
||||||
/* for leaked objects, we take ownership of the object instead of
|
/* for leaked objects, we take ownership of the object instead of
|
||||||
* reffing ("collecting") it to avoid deadlocks */
|
* reffing ("collecting") it to avoid deadlocks */
|
||||||
g_value_init (&obj_value, leak->type);
|
g_value_init (&obj_value, leak->type);
|
||||||
if (object_is_gst_mini_object (leak->obj))
|
switch (leak->infos->kind) {
|
||||||
g_value_take_boxed (&obj_value, leak->obj);
|
case GOBJECT:
|
||||||
else
|
g_value_take_object (&obj_value, leak->obj);
|
||||||
g_value_take_object (&obj_value, leak->obj);
|
break;
|
||||||
|
case MINI_OBJECT:
|
||||||
|
g_value_take_boxed (&obj_value, leak->obj);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
s = gst_structure_new_empty ("object-alive");
|
s = gst_structure_new_empty ("object-alive");
|
||||||
gst_structure_take_value (s, "object", &obj_value);
|
gst_structure_take_value (s, "object", &obj_value);
|
||||||
gst_structure_set (s, "ref-count", G_TYPE_UINT, leak->ref_count,
|
gst_structure_set (s, "ref-count", G_TYPE_UINT, leak->ref_count,
|
||||||
|
@ -745,7 +760,7 @@ gst_leaks_tracer_finalize (GObject * object)
|
||||||
GstLeaksTracer *self = GST_LEAKS_TRACER (object);
|
GstLeaksTracer *self = GST_LEAKS_TRACER (object);
|
||||||
gboolean leaks = FALSE;
|
gboolean leaks = FALSE;
|
||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
gpointer obj;
|
gpointer obj, infos;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self, "destroying tracer, checking for leaks");
|
GST_DEBUG_OBJECT (self, "destroying tracer, checking for leaks");
|
||||||
|
|
||||||
|
@ -758,12 +773,19 @@ gst_leaks_tracer_finalize (GObject * object)
|
||||||
|
|
||||||
/* Remove weak references */
|
/* Remove weak references */
|
||||||
g_hash_table_iter_init (&iter, self->objects);
|
g_hash_table_iter_init (&iter, self->objects);
|
||||||
while (g_hash_table_iter_next (&iter, &obj, NULL)) {
|
while (g_hash_table_iter_next (&iter, &obj, &infos)) {
|
||||||
if (object_is_gst_mini_object (obj))
|
switch (((ObjectRefingInfos *) infos)->kind) {
|
||||||
gst_mini_object_weak_unref (GST_MINI_OBJECT_CAST (obj),
|
case GOBJECT:
|
||||||
mini_object_weak_cb, self);
|
g_object_weak_unref (obj, object_weak_cb, self);
|
||||||
else
|
break;
|
||||||
g_object_weak_unref (obj, object_weak_cb, self);
|
case MINI_OBJECT:
|
||||||
|
gst_mini_object_weak_unref (GST_MINI_OBJECT_CAST (obj),
|
||||||
|
mini_object_weak_cb, self);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_clear_pointer (&self->objects, g_hash_table_unref);
|
g_clear_pointer (&self->objects, g_hash_table_unref);
|
||||||
|
|
Loading…
Reference in a new issue