Skip to content

Fix FlowRuleComparator violating the Comparator contract - #3629

Open
vasiliy-mikhailov wants to merge 1 commit into
alibaba:1.8from
vasiliy-mikhailov:fix/flowrulecomparator-contract
Open

Fix FlowRuleComparator violating the Comparator contract#3629
vasiliy-mikhailov wants to merge 1 commit into
alibaba:1.8from
vasiliy-mikhailov:fix/flowrulecomparator-contract

Conversation

@vasiliy-mikhailov

@vasiliy-mikhailov vasiliy-mikhailov commented Jun 24, 2026

Copy link
Copy Markdown

Problem

FlowRuleComparator.compare returns 0 (equal) for rules that are not actually equal:

if (o1.getLimitApp() == null) {
    return 0;                       // returns 0 even when o2.getLimitApp() is non-null
}
...
} else {
    return 0;                       // two different non-default limitApps compare as equal
}

So a rule whose limitApp is null compares equal to any other rule, and two rules with different non-default limitApp values (e.g. originA vs originB) compare equal. Returning 0 for unequal elements violates the Comparator contract and can cause rules to be dropped when stored in a sorted structure.

Fix

  • Return 0 only when both limitApps are null; otherwise order a null consistently against a non-null value.
  • Compare two different non-default limitApps with String.compareTo instead of returning 0.

Test

Adds testNullVsNonNullLimitApp and testDifferentNonDefaultLimitApps to FlowRuleComparatorTest, each also checking antisymmetry. Both fail on 1.8 (compare returns 0 for unequal rules) and pass with this change.

AI assistance disclosure

This contribution was produced with the help of an AI pipeline. The pipeline processed a large amount of source code to surface suspected bugs, reproduced a subset of them with failing unit tests and generated candidate fixes, and prepared pull requests from the ones that held up. Each PR was then reviewed and verified by a human before being opened: the fix and test were checked by hand and the test was confirmed to fail before the change and pass after.

FlowRuleComparator.compare returned 0 (equal) for rules that are not equal:

- when one limitApp is null and the other is not (the early
  o1.getLimitApp() == null check returned 0 regardless of o2), and
- when both limitApps are non-null, non-default and different (the final
  else returned 0).

Returning 0 for unequal elements breaks the Comparator contract and can drop
rules when they are stored in a sorted structure. Handle the null cases
explicitly and compare two different non-default limitApps with
String.compareTo.

@oss-sentinel-ai oss-sentinel-ai left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Fixes two Comparator contract violations in FlowRuleComparator: (1) a null limitApp on one side was compared as equal to anything (breaking antisymmetry), and (2) two different non-default limitApp values compared as 0, making the ordering nondeterministic. Both could trigger IllegalArgumentException: Comparison method violates its general contract! from TimSort during rule reloads. Verified against FlowRuleUtil.buildFlowRuleMap (the only consumer): origin-specific rules still sort before default, cluster-mode rules still sort last, and blank limitApp is normalized to default before sorting — so matching semantics are preserved while the ordering becomes deterministic. Tests cover both the null-vs-non-null and different-app cases with antisymmetry assertions. LGTM.


Automated review by github-manager-bot

return -1;
} else {
return 0;
return o1.getLimitApp().compareTo(o2.getLimitApp());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified the surrounding semantics: FlowRuleUtil.buildFlowRuleMap sorts per-resource rule lists with this comparator. Origin-specific rules still sort before LIMIT_APP_DEFAULT and cluster-mode rules still sort last, so rule matching order is preserved; the new lexicographic tie-break between two different non-default limitApp values only makes the ordering deterministic. Combined with FlowRuleUtil normalizing blank limitApp to default before sorting, this safely fixes the Comparator contract violations (antisymmetry) that could trigger IllegalArgumentException from TimSort on rule updates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants