You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
VU#903934 (Hash table implementations vulnerable to algorithmic complexity attacks)
Fix with JEP180 in Java8: if too many hash codes map to the same bucket in the map, the list of entries can be changed into a balanced binary tree, sorted first by hash code and then by each key’s compareTo method, as long as the keys are Comparable.
IMHO it makes sense to provide such a rule in the standard ruleset so that others can benefit from it easily.
@ArchTag("DoS-Protection")
@ArchTeststaticfinalArchRulefields_of_type_HashMap_should_have_Comparable_key = fields().that()
.haveRawType(Map.class)
.should(haveComparableFirstTypeParameter());
@ArchTag("DoS-Protection")
@ArchTeststaticfinalArchRulecode_units_should_have_parameters_of_type_Map_with_Comparable_key = codeUnits()
.should(newArchCondition<JavaCodeUnit>("have parameters of type Map with `Comparable` key") {
@Overridepublicvoidcheck(finalJavaCodeUnitjavaCodeUnit, finalConditionEventsevents) {
javaCodeUnit.getParameters().forEach(parameter -> {
if (parameter.getRawType().isEquivalentTo(Map.class)) {
haveComparableFirstTypeParameter().check(parameter, events);
}
});
}
});
@ArchTag("DoS-Protection")
@ArchTeststaticfinalArchRulemethods_with_return_type_Map_should_have_return_types_with_Comparable_key = methods().that()
.haveRawReturnType(Map.class)
.should(newArchCondition<JavaMethod>("have return type with `Comparable` key") {
@Overridepublicvoidcheck(finalJavaMethodmethod, finalConditionEventsevents) {
classReturnTypeimplementsHasType, HasDescription {
@OverridepublicJavaTypegetType() {
returnmethod.getReturnType();
}
@OverridepublicJavaClassgetRawType() {
returnmethod.getRawReturnType();
}
@OverridepublicStringgetDescription() {
return"Return type <" + this.getType().getName() + "> of " + method.getDescription();
}
}
haveComparableFirstTypeParameter().check(newReturnType(), events);
}
});
privatestatic <TextendsHasType & HasDescription> ArchCondition<T> haveComparableFirstTypeParameter() {
returnnewArchCondition<>("have `Comparable` first type parameter") {
@Overridepublicvoidcheck(finalTtyped, finalConditionEventsevents) {
finalJavaTypefieldType = typed.getType();
if (fieldTypeinstanceofJavaParameterizedType) {
finalJavaTypekeyType = ((JavaParameterizedType) fieldType).getActualTypeArguments().get(0);
if (keyTypeinstanceofJavaTypeVariable) {
finalbooleanisGenericType = true;
finalStringmessage = String.format(
"%s has a generic first type parameter %s. Comparable check skipped.",
typed.getDescription(), keyType.getName());
events.add(newSimpleConditionEvent(typed, isGenericType, message));
} else {
finalJavaClasserasedType = keyType.toErasure();
finalbooleanisComparable = erasedType.getAllRawInterfaces()
.stream()
.anyMatch(rawInterface -> rawInterface.isEquivalentTo(Comparable.class));
finalStringmessage = String.format("%s has a first type parameter %s that %s Comparable",
typed.getDescription(), keyType.getName(), isComparable ? "is" : "is not");
events.add(newSimpleConditionEvent(typed, isComparable, message));
}
} else {
events.add(SimpleConditionEvent.violated(typed, typed.getDescription() + " is not parameterized"));
}
}
};
}
However, for a complete check, this #768 feature needs to be implemented first.
The text was updated successfully, but these errors were encountered:
Thanks a lot for sharing this 😃 Yes, we could definitely add this to the predefined rules, I just wonder if we should already do this without #768? Or do you think it doesn't provide enough value then?
I kind of think most such relevant errors would be caught by the rule though, because the only maps left are then in a narrow local scope which probably reduces the risk of a targeted attack a lot, don't you think?
If we put it to the library I would make it one rule though and explain the issue behind the rule.
I kind of think most such relevant errors would be caught by the rule though, because the only maps left are then in a narrow local scope which probably reduces the risk of a targeted attack a lot, don't you think?
Yes, agree.
If we put it to the library I would make it one rule though and explain the issue behind the rule.
Reference: https://stackoverflow.com/questions/70507647/how-to-assert-hashmap-keys-to-be-comparable-with-archunit/70509141
VU#903934 (Hash table implementations vulnerable to algorithmic complexity attacks)
Fix with JEP180 in Java8: if too many hash codes map to the same bucket in the map, the list of entries can be changed into a balanced binary tree, sorted first by hash code and then by each key’s compareTo method, as long as the keys are Comparable.
IMHO it makes sense to provide such a rule in the standard ruleset so that others can benefit from it easily.
However, for a complete check, this #768 feature needs to be implemented first.
The text was updated successfully, but these errors were encountered: