Skip to content

[Bug] rocketmq-tools comparators truncate long differences to int #11306

Description

@Metastarx

Three comparators in rocketmq-tools subtract two long values and cast the difference to int:

  • GroupConsumeInfo.compareTo (tools/src/main/java/org/apache/rocketmq/tools/command/consumer/ConsumerProgressSubCommand.java:352): (int) (o.diffTotal - diffTotal), while diffTotal is a long (field at line 283, assigned from consumeStats.computeTotalDiff()).
  • TagCountBean.compareTo (tools/src/main/java/org/apache/rocketmq/tools/command/message/PrintMessageByQueueCommand.java:253): (int) (o.getCount().get() - this.count.get()).
  • QueryMsgByUniqueKeySubCommand.queryById (tools/src/main/java/org/apache/rocketmq/tools/command/message/QueryMsgByUniqueKeySubCommand.java:76): list.sort((o1, o2) -> (int) (o1.getStoreTimestamp() - o2.getStoreTimestamp())).

When the real difference is larger than Integer.MAX_VALUE the cast wraps: a positive difference becomes negative and vice versa. The printout order is then wrong, and the comparator contract is broken (sign(compare(a, b)) != -sign(compare(b, a))), which the JDK TimSort used by Collections.sort/List.sort can detect and fail with Comparison method violates its general contract!.

The values are reachable in practice: a group's total consume lag can exceed 2^31 messages, a queryMsgByUniqueKey -s/-e window can span more than about 24.8 days, and a printMsgByQueue tag count can exceed 2^31.

How to reproduce

Build two GroupConsumeInfo with setCount(1) and diffTotal of 0 and (long) Integer.MAX_VALUE + 1. Both left.compareTo(right) and right.compareTo(left) return a negative value, so the comparator is not antisymmetric; sorting a list that contains those entries prints them in the wrong order.

Expected

Comparisons should use Long.compare(...) / Comparator.comparingLong(...) instead of subtracting.

No activity

Activity on this issue will appear here.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions