import java.util.*; /** * CWE-407 unit test for Meson get_internal_static_libraries_recurse diamond recursion. * * Simulates the defective and fixed versions of the link_whole traversal. * * Defect: link_whole_targets branch recurses without checking `t not in result`, * causing O(2^D) traversal on diamond link_whole graphs. * * Fix: add the same guard used for link_targets to link_whole_targets. */ public class MesonLinkWholeDiamondTest { static int defectiveVisitCount; /** Simulates defective get_internal_static_libraries_recurse */ static void defectiveRecurse(Map> linkWholeGraph, String target, Set result) { defectiveVisitCount++; List children = linkWholeGraph.getOrDefault(target, Collections.emptyList()); for (String child : children) { // Defect: no guard — always recurses even if child already in result defectiveRecurse(linkWholeGraph, child, result); } result.add(target); } static int fixedVisitCount; /** Simulates fixed get_internal_static_libraries_recurse */ static void fixedRecurse(Map> linkWholeGraph, String target, Set result) { fixedVisitCount++; List children = linkWholeGraph.getOrDefault(target, Collections.emptyList()); for (String child : children) { // Fix: check result before recursing if (!result.contains(child)) { result.add(child); fixedRecurse(linkWholeGraph, child, result); } } } /** * Build a chained diamond link_whole graph of depth D: * * n0 link_whole [n0L, n0R] * n0L link_whole [n1] * n0R link_whole [n1] * n1 link_whole [n1L, n1R] * n1L link_whole [n2] * n1R link_whole [n2] * ... * n(D) is a leaf */ static Map> buildDiamond(int depth) { Map> graph = new HashMap<>(); for (int d = 0; d < depth; d++) { String node = "n" + d; String left = "n" + d + "L"; String right = "n" + d + "R"; String next = "n" + (d + 1); graph.put(node, Arrays.asList(left, right)); graph.put(left, Arrays.asList(next)); graph.put(right, Arrays.asList(next)); } // n(depth) is a leaf return graph; } public static void main(String[] args) { System.out.println("=== Meson link_whole Diamond Recursion CWE-407 ==="); System.out.println("get_internal_static_libraries_recurse: link_whole_targets missing guard"); System.out.println(); System.out.printf("%-6s %-12s %-10s %-8s%n", "Depth", "Defective", "Fixed", "Ratio"); System.out.println("--------------------------------------"); boolean allPass = true; for (int depth : new int[]{1, 2, 3, 5, 7, 10}) { Map> graph = buildDiamond(depth); defectiveVisitCount = 0; Set defectiveResult = new HashSet<>(); defectiveRecurse(graph, "n0", defectiveResult); fixedVisitCount = 0; Set fixedResult = new HashSet<>(); fixedResult.add("n0"); fixedRecurse(graph, "n0", fixedResult); double ratio = (double) defectiveVisitCount / fixedVisitCount; System.out.printf("D=%-4d %-12d %-10d %-8.1fx%n", depth, defectiveVisitCount, fixedVisitCount, ratio); // Both should find the same closure // Note: defective adds nodes bottom-up; fixed adds them on descent // Results should contain same set of nodes Set allNodes = new HashSet<>(); for (int d = 0; d <= depth; d++) { allNodes.add("n" + d); if (d < depth) { allNodes.add("n" + d + "L"); allNodes.add("n" + d + "R"); } } // defectiveResult includes all nodes visited (including n0 itself) // fixedResult includes n0 plus all children // The important thing: fixed finds all shared descendants for (int d = 1; d <= depth; d++) { String bottom = "n" + d; if (!fixedResult.contains(bottom)) { System.err.println("FAIL: fixed result missing " + bottom + " at depth " + depth); allPass = false; } } if (depth >= 5 && ratio < 5.0) { System.err.println("FAIL: expected >5x ratio at depth " + depth + ", got " + ratio); allPass = false; } } System.out.println(); // Edge case: linear chain (no diamond) — both should visit same count { Map> linear = new HashMap<>(); linear.put("A", Arrays.asList("B")); linear.put("B", Arrays.asList("C")); // C is a leaf defectiveVisitCount = 0; Set dr = new HashSet<>(); defectiveRecurse(linear, "A", dr); fixedVisitCount = 0; Set fr = new HashSet<>(); fr.add("A"); fixedRecurse(linear, "A", fr); System.out.println("Linear chain (no diamond): defective=" + defectiveVisitCount + " fixed=" + fixedVisitCount + " — PASS (no blowup expected)"); } System.out.println(); if (allPass) { System.out.println("PASS — exponential blowup in link_whole confirmed and fixed"); } else { System.exit(1); } } }