diff options
author | Øyvind Kolås <pippin@linux.intel.com> | 2010-08-17 13:22:08 +0100 |
---|---|---|
committer | Øyvind Kolås <pippin@linux.intel.com> | 2010-08-23 14:01:08 +0100 |
commit | 04d55107f380340ce22fbb56a3c87cf7576524db (patch) | |
tree | f7e19b25ea090676672ff99c919f422c8d890ebd /clutter/clutter-state.c | |
parent | 66018a7035ccdc2422f8eef9a9523339fd6309be (diff) | |
download | clutter-04d55107f380340ce22fbb56a3c87cf7576524db.tar.gz |
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
Diffstat (limited to 'clutter/clutter-state.c')
-rw-r--r-- | clutter/clutter-state.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/clutter/clutter-state.c b/clutter/clutter-state.c index 12cde6fba..b05338af4 100644 --- a/clutter/clutter-state.c +++ b/clutter/clutter-state.c @@ -269,6 +269,8 @@ clutter_state_remove_key_internal (ClutterState *this, if (source_state_name) source_state = clutter_state_fetch_state (this, source_state_name, FALSE); +again_from_start: + if (target_state_name != NULL) state_list = g_list_append (NULL, (gpointer) target_state_name); else @@ -278,31 +280,36 @@ clutter_state_remove_key_internal (ClutterState *this, { State *target_state; target_state = clutter_state_fetch_state (this, s->data, FALSE); - + /* Go through each TargetState */ if (target_state) { GList *k; -again: +again_for_target_state: for (k = target_state->keys; k != NULL; k = k->next) { ClutterStateKey *key = k->data; + /* Check if each key matches query */ if ( (object == NULL || (object == key->object)) && (source_state == NULL || (source_state == key->source_state)) && (property_name == NULL || ((property_name == key->property_name)))) { + /* Remove matching key */ target_state->keys = g_list_remove (target_state->keys, key); + key->is_inert = is_inert; + clutter_state_key_free (key); + /* no more keys with transitions to this target_state*/ if (target_state->keys == NULL) { - /* no more keys, so remove this state */ + /* 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 */ } - - key->is_inert = is_inert; - clutter_state_key_free (key); - goto again; + goto again_for_target_state; } } } |