瀏覽代碼

Fix infinite loop in role hierarchy resolving

Issue: gh-7035
Karel Maxa 6 年之前
父節點
當前提交
d3eaef66fc

+ 6 - 20
core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyImpl.java

@@ -215,33 +215,19 @@ public class RoleHierarchyImpl implements RoleHierarchy {
 		// iterate over all higher roles from rolesReachableInOneStepMap
 
 		for (GrantedAuthority role : this.rolesReachableInOneStepMap.keySet()) {
-			Set<GrantedAuthority> rolesToVisitSet = new HashSet<>();
-
-			if (this.rolesReachableInOneStepMap.containsKey(role)) {
-				rolesToVisitSet.addAll(this.rolesReachableInOneStepMap.get(role));
-			}
-
+			Set<GrantedAuthority> rolesToVisitSet = new HashSet<>(this.rolesReachableInOneStepMap.get(role));
 			Set<GrantedAuthority> visitedRolesSet = new HashSet<>();
 
 			while (!rolesToVisitSet.isEmpty()) {
 				// take a role from the rolesToVisit set
 				GrantedAuthority aRole = rolesToVisitSet.iterator().next();
 				rolesToVisitSet.remove(aRole);
-				visitedRolesSet.add(aRole);
-				if (this.rolesReachableInOneStepMap.containsKey(aRole)) {
-					Set<GrantedAuthority> newReachableRoles = this.rolesReachableInOneStepMap
-							.get(aRole);
-
-					// definition of a cycle: you can reach the role you are starting from
-					if (rolesToVisitSet.contains(role)
-							|| visitedRolesSet.contains(role)) {
-						throw new CycleInRoleHierarchyException();
-					}
-					else {
-						// no cycle
-						rolesToVisitSet.addAll(newReachableRoles);
-					}
+				if (!visitedRolesSet.add(aRole) || !this.rolesReachableInOneStepMap.containsKey(aRole)) {
+					continue; // Already visited role or role with missing hierarchy
+				} else if (role.equals(aRole)) {
+					throw new CycleInRoleHierarchyException();
 				}
+				rolesToVisitSet.addAll(this.rolesReachableInOneStepMap.get(aRole));
 			}
 			this.rolesReachableInOneOrMoreStepsMap.put(role, visitedRolesSet);
 

+ 6 - 0
core/src/test/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyImplTests.java

@@ -168,6 +168,12 @@ public class RoleHierarchyImplTests {
 		}
 		catch (CycleInRoleHierarchyException e) {
 		}
+
+		try {
+			roleHierarchyImpl.setHierarchy("ROLE_C > ROLE_B\nROLE_B > ROLE_A\nROLE_A > ROLE_B");
+			fail("Cycle in role hierarchy was not detected!");
+		} catch (CycleInRoleHierarchyException e) {
+		}
 	}
 
 	@Test