From 2513235859fc50e8c28545977702b9b7b439f5f5 Mon Sep 17 00:00:00 2001 From: Joshua C. Colp Date: Wed, 24 Jun 2020 07:25:47 -0300 Subject: [PATCH] menuselect: Resolve infinite loop in dependency scenario. Given a scenario where a module has a dependency on both an external library and a module if the external library was available and the module was not an infinite loop would occur. This happened due to the code changing the dependecy status to no failure on each dependency checking loop iteration, resulting in the code thinking that it had gone from no failure to failure each time triggering another dependency check. This change makes it so that the old dependency status is preserved throughout the dependency checking allowing it to determine that after the first iteration the dependency status does not transition from no failure to failure. ASTERISK-28930 Change-Id: Iea06d45d9fd6d8bfd068882a0bb7e23a53ec3e84 --- diff --git a/menuselect/menuselect.c b/menuselect/menuselect.c index 83f6098..a595ce8 100644 --- a/menuselect/menuselect.c +++ b/menuselect/menuselect.c @@ -630,14 +630,14 @@ struct member *mem; struct reference *dep; struct dep_file *dep_file; - unsigned int changed, old_failure; + unsigned int changed; AST_LIST_TRAVERSE(&categories, cat, list) { AST_LIST_TRAVERSE(&cat->members, mem, list) { if (mem->is_separator) { continue; } - old_failure = mem->depsfailed; + mem->depsfailedold = mem->depsfailed; AST_LIST_TRAVERSE(&mem->deps, dep, list) { if (dep->member) continue; @@ -655,7 +655,7 @@ break; /* This dependency is not met, so we can stop now */ } } - if (old_failure == SOFT_FAILURE && mem->depsfailed != HARD_FAILURE) + if (mem->depsfailedold == SOFT_FAILURE && mem->depsfailed != HARD_FAILURE) mem->depsfailed = SOFT_FAILURE; } } @@ -673,8 +673,6 @@ continue; } - old_failure = mem->depsfailed; - if (mem->depsfailed == HARD_FAILURE) continue; @@ -693,7 +691,7 @@ } } - if (mem->depsfailed != old_failure) { + if (mem->depsfailed != mem->depsfailedold) { if ((mem->depsfailed == NO_FAILURE) && mem->was_defaulted) { mem->enabled = !strcasecmp(mem->defaultenabled, "yes"); print_debug("Just set %s enabled to %d\n", mem->name, mem->enabled); @@ -702,6 +700,8 @@ print_debug("Just set %s enabled to %d\n", mem->name, mem->enabled); } changed = 1; + /* We need to update the old failed deps for the next loop of this */ + mem->depsfailedold = mem->depsfailed; break; /* This dependency is not met, so we can stop now */ } } diff --git a/menuselect/menuselect.h b/menuselect/menuselect.h index 78ae8ef..d41859e 100644 --- a/menuselect/menuselect.h +++ b/menuselect/menuselect.h @@ -78,6 +78,8 @@ unsigned int was_enabled:1; /*! This module has failed dependencies */ unsigned int depsfailed:2; + /*! Previous failed dependencies when calculating */ + unsigned int depsfailedold:2; /*! This module has failed conflicts */ unsigned int conflictsfailed:2; /*! This module's 'enabled' flag was changed by a default only */