From 823d7065ffcaec57bdbef479dce49ae97ff08640 Mon Sep 17 00:00:00 2001 From: Matthias Klumpp Date: Tue, 30 Jul 2019 02:38:47 +0200 Subject: [PATCH 3/3] Fix infinite recursion if component has itself listed as an addon This particular case of a component being an addon to itself is nonsense, but people may make that mistake and we shouldn't crash in that case. With this patch the cache will be resilient against such cases and simply ignore components depending on themselves. We could still get nasty dependency loops though, with A depending on B depending on A. This is a bit more complicated to resolve and will be fixed in a future commit. Resolves: #243 --- src/as-cache.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/as-cache.c b/src/as-cache.c index 50b42193..3afabda7 100644 --- a/src/as-cache.c +++ b/src/as-cache.c @@ -1573,7 +1573,7 @@ as_cache_register_addons_for_component (AsCache *cache, MDB_txn *txn, AsComponen { AsCachePrivate *priv = GET_PRIVATE (cache); MDB_val dval; - g_autoptr(GPtrArray) addons = NULL; + g_autofree guint8 *cpt_checksum = NULL; GError *tmp_error = NULL; dval = as_cache_txn_get_value (cache, @@ -1588,14 +1588,29 @@ as_cache_register_addons_for_component (AsCache *cache, MDB_txn *txn, AsComponen if (dval.mv_size == 0) return TRUE; - addons = as_cache_components_by_hash_list (cache, txn, dval.mv_data, dval.mv_size, &tmp_error); - if (addons == NULL) { - g_propagate_error (error, tmp_error); - return FALSE; - } + /* retrieve cache checksum of this component */ + as_generate_cache_checksum (as_component_get_data_id (cpt), + -1, + &cpt_checksum, + NULL); + + g_assert_cmpint (dval.mv_size % AS_CACHE_CHECKSUM_LEN, ==, 0); + for (gsize i = 0; i < dval.mv_size; i += AS_CACHE_CHECKSUM_LEN) { + const guint8 *chash = dval.mv_data + i; + AsComponent *addon; + + /* ignore addon that extends itself to prevent infinite recursion */ + if (memcmp (chash, cpt_checksum, AS_CACHE_CHECKSUM_LEN) == 0) + continue; - for (guint i = 0; i < addons->len; i++) - as_component_add_addon (cpt, AS_COMPONENT (g_ptr_array_index (addons, i))); + addon = as_cache_component_by_hash (cache, txn, chash, &tmp_error); + if (tmp_error != NULL) { + g_propagate_prefixed_error (error, tmp_error, "Failed to retrieve addon component data: "); + return FALSE; + } + if (addon != NULL) + as_component_add_addon (cpt, addon); + } return TRUE; } -- 2.22.0