From 8805e31d25f8aafd3a656f7a16d61fac46d74a76 Mon Sep 17 00:00:00 2001 From: Igor Bochkariov Date: Sun, 4 Jun 2023 14:49:25 +0400 Subject: [PATCH] libobs: Fix crash when plugins delete properties in callback If a plugin removes a property when processing 'modified' property callback, OBS WILL CRASH. Example of offending plugin: obs-source-record This commit moves callback processing to after iterating over properties, thus removing the chance to crash OBS. (cherry picked from commit b081adf72e3dddcaaa7b94e38a25eb274be3b44a) --- libobs/obs-properties.c | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/libobs/obs-properties.c b/libobs/obs-properties.c index 4e44ffc9b..9bb2fcb46 100644 --- a/libobs/obs-properties.c +++ b/libobs/obs-properties.c @@ -360,22 +360,21 @@ void obs_properties_remove_by_name(obs_properties_t *props, const char *name) } } -void obs_properties_apply_settings_internal(obs_properties_t *props, - obs_data_t *settings, - obs_properties_t *realprops) +typedef DARRAY(struct obs_property *) obs_property_da_t; + +void obs_properties_apply_settings_internal( + obs_properties_t *props, obs_property_da_t *properties_with_callback) { struct obs_property *p = props->properties; while (p) { if (p->type == OBS_PROPERTY_GROUP) { obs_properties_apply_settings_internal( - obs_property_group_content(p), settings, - realprops); + obs_property_group_content(p), + properties_with_callback); } - if (p->modified) - p->modified(realprops, p, settings); - else if (p->modified2) - p->modified2(p->priv, realprops, p, settings); + if (p->modified || p->modified2) + da_push_back((*properties_with_callback), &p); p = p->hh.next; } @@ -387,7 +386,23 @@ void obs_properties_apply_settings(obs_properties_t *props, if (!props) return; - obs_properties_apply_settings_internal(props, settings, props); + obs_property_da_t properties_with_callback; + da_init(properties_with_callback); + + obs_properties_apply_settings_internal(props, + &properties_with_callback); + + while (properties_with_callback.num > 0) { + struct obs_property *p = *(struct obs_property **)da_end( + properties_with_callback); + if (p->modified) + p->modified(props, p, settings); + else if (p->modified2) + p->modified2(p->priv, props, p, settings); + da_pop_back(properties_with_callback); + } + + da_free(properties_with_callback); } /* ------------------------------------------------------------------------- */