From ea25ad3a34947c8fda96e8373709eff81db63842 Mon Sep 17 00:00:00 2001 From: andreas hilti <69210561+andreas-hilti@users.noreply.github.com> Date: Sat, 7 Mar 2026 23:40:12 +0100 Subject: [PATCH] check also nested components in multiple component versions check Signed-off-by: andreas hilti <69210561+andreas-hilti@users.noreply.github.com> --- .../MultipleComponentVersions.cs | 15 +++++++- .../MultipleComponentVersionsTests.cs | 38 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/CycloneDX.Utils/MultipleComponentVersions.cs b/src/CycloneDX.Utils/MultipleComponentVersions.cs index dabbad34..32a9baf5 100644 --- a/src/CycloneDX.Utils/MultipleComponentVersions.cs +++ b/src/CycloneDX.Utils/MultipleComponentVersions.cs @@ -36,8 +36,20 @@ public static Dictionary> MultipleComponentVersions(Bom var componentCache = new Dictionary>(); - foreach (var component in bom.Components) + var toVisit = new List(bom.Components.Reverse()); + + while (toVisit.Count > 0) { + var component = toVisit.Last(); + toVisit.RemoveAt(toVisit.Count - 1); + if (component.Components != null) + { + foreach (var subComponent in component.Components.Reverse()) + { + toVisit.Add(subComponent); + } + } + var componentIdentifier = ComponentAnalysisIdentifier(component); if (!componentCache.ContainsKey(componentIdentifier)) { @@ -46,6 +58,7 @@ public static Dictionary> MultipleComponentVersions(Bom componentCache[componentIdentifier].Add(component); } + foreach (var componentEntry in componentCache) { if (componentEntry.Value.Count > 1) diff --git a/tests/CycloneDX.Utils.Tests/MultipleComponentVersionsTests.cs b/tests/CycloneDX.Utils.Tests/MultipleComponentVersionsTests.cs index 28bf8173..7bafcf35 100644 --- a/tests/CycloneDX.Utils.Tests/MultipleComponentVersionsTests.cs +++ b/tests/CycloneDX.Utils.Tests/MultipleComponentVersionsTests.cs @@ -35,5 +35,43 @@ public void MultipleComponentVersionTest() Assert.Equal(2, result["component"].Count); } + + [Fact] + public void MultipleNestedComponentVersionTest() + { + var bom = new Bom + { + Components = new List + { + new Component + { + Name = "ComponentA", + Version = "1", + BomRef = "ComponentA@1" + }, + new Component + { + Name = "ComponentB", + Version = "1", + BomRef = "ComponentB@1", + Components = new List + { + new Component + { + Name = "ComponentA", + Version = "2", + BomRef = "ComponentA@2" + } + } + } + }, + }; + + var result = CycloneDXUtils.MultipleComponentVersions(bom); + + Assert.Equal(2, result["ComponentA"].Count); + Assert.Equal("1", result["ComponentA"][0].Version); + Assert.Equal("2", result["ComponentA"][1].Version); + } } }