Skip to content

Commit d3eaef6

Browse files
committed
Fix infinite loop in role hierarchy resolving
Issue: gh-7035
1 parent 2d36062 commit d3eaef6

File tree

2 files changed

+12
-20
lines changed

2 files changed

+12
-20
lines changed

core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyImpl.java

+6-20
Original file line numberDiff line numberDiff line change
@@ -215,33 +215,19 @@ private void buildRolesReachableInOneOrMoreStepsMap() {
215215
// iterate over all higher roles from rolesReachableInOneStepMap
216216

217217
for (GrantedAuthority role : this.rolesReachableInOneStepMap.keySet()) {
218-
Set<GrantedAuthority> rolesToVisitSet = new HashSet<>();
219-
220-
if (this.rolesReachableInOneStepMap.containsKey(role)) {
221-
rolesToVisitSet.addAll(this.rolesReachableInOneStepMap.get(role));
222-
}
223-
218+
Set<GrantedAuthority> rolesToVisitSet = new HashSet<>(this.rolesReachableInOneStepMap.get(role));
224219
Set<GrantedAuthority> visitedRolesSet = new HashSet<>();
225220

226221
while (!rolesToVisitSet.isEmpty()) {
227222
// take a role from the rolesToVisit set
228223
GrantedAuthority aRole = rolesToVisitSet.iterator().next();
229224
rolesToVisitSet.remove(aRole);
230-
visitedRolesSet.add(aRole);
231-
if (this.rolesReachableInOneStepMap.containsKey(aRole)) {
232-
Set<GrantedAuthority> newReachableRoles = this.rolesReachableInOneStepMap
233-
.get(aRole);
234-
235-
// definition of a cycle: you can reach the role you are starting from
236-
if (rolesToVisitSet.contains(role)
237-
|| visitedRolesSet.contains(role)) {
238-
throw new CycleInRoleHierarchyException();
239-
}
240-
else {
241-
// no cycle
242-
rolesToVisitSet.addAll(newReachableRoles);
243-
}
225+
if (!visitedRolesSet.add(aRole) || !this.rolesReachableInOneStepMap.containsKey(aRole)) {
226+
continue; // Already visited role or role with missing hierarchy
227+
} else if (role.equals(aRole)) {
228+
throw new CycleInRoleHierarchyException();
244229
}
230+
rolesToVisitSet.addAll(this.rolesReachableInOneStepMap.get(aRole));
245231
}
246232
this.rolesReachableInOneOrMoreStepsMap.put(role, visitedRolesSet);
247233

core/src/test/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyImplTests.java

+6
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,12 @@ public void testCyclesInRoleHierarchy() {
168168
}
169169
catch (CycleInRoleHierarchyException e) {
170170
}
171+
172+
try {
173+
roleHierarchyImpl.setHierarchy("ROLE_C > ROLE_B\nROLE_B > ROLE_A\nROLE_A > ROLE_B");
174+
fail("Cycle in role hierarchy was not detected!");
175+
} catch (CycleInRoleHierarchyException e) {
176+
}
171177
}
172178

173179
@Test

0 commit comments

Comments
 (0)