mirror of
https://github.com/brl/mutter.git
synced 2025-02-17 05:44:08 +00:00
state: clutter_state_remove_key_internal fix memory corruption
When we free a state because there are no more keys with it as a target use a goto to re-initialize temporary variables that have become invalid. Fixing bug #2273
This commit is contained in:
parent
66018a7035
commit
04d55107f3
@ -269,6 +269,8 @@ clutter_state_remove_key_internal (ClutterState *this,
|
|||||||
if (source_state_name)
|
if (source_state_name)
|
||||||
source_state = clutter_state_fetch_state (this, source_state_name, FALSE);
|
source_state = clutter_state_fetch_state (this, source_state_name, FALSE);
|
||||||
|
|
||||||
|
again_from_start:
|
||||||
|
|
||||||
if (target_state_name != NULL)
|
if (target_state_name != NULL)
|
||||||
state_list = g_list_append (NULL, (gpointer) target_state_name);
|
state_list = g_list_append (NULL, (gpointer) target_state_name);
|
||||||
else
|
else
|
||||||
@ -278,31 +280,36 @@ clutter_state_remove_key_internal (ClutterState *this,
|
|||||||
{
|
{
|
||||||
State *target_state;
|
State *target_state;
|
||||||
target_state = clutter_state_fetch_state (this, s->data, FALSE);
|
target_state = clutter_state_fetch_state (this, s->data, FALSE);
|
||||||
|
/* Go through each TargetState */
|
||||||
if (target_state)
|
if (target_state)
|
||||||
{
|
{
|
||||||
GList *k;
|
GList *k;
|
||||||
again:
|
again_for_target_state:
|
||||||
for (k = target_state->keys; k != NULL; k = k->next)
|
for (k = target_state->keys; k != NULL; k = k->next)
|
||||||
{
|
{
|
||||||
ClutterStateKey *key = k->data;
|
ClutterStateKey *key = k->data;
|
||||||
|
|
||||||
|
/* Check if each key matches query */
|
||||||
if ( (object == NULL || (object == key->object))
|
if ( (object == NULL || (object == key->object))
|
||||||
&& (source_state == NULL || (source_state == key->source_state))
|
&& (source_state == NULL || (source_state == key->source_state))
|
||||||
&& (property_name == NULL || ((property_name == key->property_name))))
|
&& (property_name == NULL || ((property_name == key->property_name))))
|
||||||
{
|
{
|
||||||
|
/* Remove matching key */
|
||||||
target_state->keys = g_list_remove (target_state->keys, key);
|
target_state->keys = g_list_remove (target_state->keys, key);
|
||||||
|
|
||||||
if (target_state->keys == NULL)
|
|
||||||
{
|
|
||||||
/* no more keys, so remove this state */
|
|
||||||
clutter_state_remove_key (this, s->data, NULL, NULL, NULL);
|
|
||||||
g_hash_table_remove (this->priv->states, s->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
key->is_inert = is_inert;
|
key->is_inert = is_inert;
|
||||||
clutter_state_key_free (key);
|
clutter_state_key_free (key);
|
||||||
goto again;
|
|
||||||
|
/* no more keys with transitions to this target_state*/
|
||||||
|
if (target_state->keys == NULL)
|
||||||
|
{
|
||||||
|
/* remove any keys that exist that uses this state as a source */
|
||||||
|
clutter_state_remove_key (this, s->data, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
g_hash_table_remove (this->priv->states, s->data);
|
||||||
|
goto again_from_start; /* we have just freed State *target_state, so
|
||||||
|
need to restart removal */
|
||||||
|
}
|
||||||
|
goto again_for_target_state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user