プロジェクト

全般

プロフィール

バグ #475

完了

バグ #474: コードベース健全性: メモリリーク・重大バグの一括調査と修正

選曲ソートのクラッシュ修正(Comparator contract 違反 / sortid 未検証)

バグ #475: 選曲ソートのクラッシュ修正(Comparator contract 違反 / sortid 未検証)

エージェント ちゃん さんが7日前に追加. 6日前に更新.

ステータス:
完了
優先度:
高め
担当者:
対象バージョン:
開始日:
2026/06/29
期日:
進捗率:

100%

予定工数:

説明

現象

選曲画面のソートで IllegalArgumentException: Comparison method violates its general contract! または IllegalArgumentException(不正 sortid)が発生しクラッシュする。

原因と対象

1. long 差分の int キャスト(推移律違反・確定)

  • src/bms/player/beatoraja/select/BarSorter.java:201(DURATION): (int)(o1.getScore().getAvgjudge() - o2.getScore().getAvgjudge())
  • src/bms/player/beatoraja/select/BarSorter.java:219(LASTUPDATE): (int)(o1.getScore().getDate() - o2.getScore().getDate())
  • getAvgjudge()/getDate()long。差が int 範囲(±2.1e9)を超えると符号反転し、libgdx TimSort(BarManager.java:381Sort.instance().sort)が contract 違反を検出して例外を投げる。曲数の多いフォルダで DURATION/LASTUPDATE ソートを選ぶと再現。

2. BarSorter.valueOf 未検証 + デッドコード

  • src/bms/player/beatoraja/select/BarManager.java:380: BarSorter.valueOf(getPlayerConfig().getSortid()) を未検証で呼ぶ。PlayerConfigValidator.java:86 は null のときだけ補完し、列挙名妥当性は検証しない。空文字/旧バージョン/手編集値で IllegalArgumentException
  • BarManager.java:381sorter != null ? sorter.sorter : BarSorter.TITLE.sorterデッドコード(valueOf は null を返さず例外を投げる)。

修正方針

  • DURATION/LASTUPDATE を Long.compare(...) に置換。
  • BarManager.java:380 を try/catch で囲んで TITLE にフォールバック(または PlayerConfigValidator で列挙名 whitelist 検証を追加)し、デッドコードの三項演算子を整理。
  • (予防)BPM/LENGTH/CLEAR/MISSCOUNT/RIVALCOMPARE 等の int 同士減算も Integer.compare/Float.compare 系に統一すると安全(現状は非負・小値域で実害低)。

検証

  • 多数曲フォルダで DURATION/LASTUPDATE ソートしてもクラッシュしない。
  • 不正 sortid の config で起動 → TITLE にフォールバックしクラッシュしない。

エージェント ちゃん さんが6日前に更新 操作 #1

  • ステータス未着手 から 実装中 に変更
  • 進捗率0 から 10 に変更

実装に着手しました。

  • ブランチ: feature/475
  • 対応方針: DURATION/LASTUPDATE の long 差分 int キャストを Long.compare に置換し、BarSorter.valueOf を列挙名検証付きの安全解決(不正値は TITLE フォールバック)に統一、デッドコードを整理。予防として他ソートの int 減算も Integer.compare に統一。

エージェント ちゃん さんが6日前に更新 操作 #2

  • ステータス実装中 から 完了 に変更
  • 進捗率10 から 100 に変更

対応が完了しました。

概要

選曲画面のソートで発生する IllegalArgumentException(Comparator contract 違反 / 不正 sortid)によるクラッシュを修正。

変更点

  • 確定バグ: DURATION/LASTUPDATE ソートの (int)(long - long)Long.compare(...) に置換。差が int 範囲(±2.1e9)を超えると符号反転し、libgdx TimSort が推移律違反を検出して例外を投げていた。
  • 不正 sortid ガード: BarSorter.exists(String) を追加。BarManager の未検証 valueOf 呼び出しを exists ? valueOf : TITLE に整理し、到達不能な三項演算子(デッドコード)を除去。空文字/旧バージョン/手編集値でも TITLE にフォールバック。
  • 多層防御: PlayerConfigValidator で起動時に null だけでなく未知の列挙名 sortid も既定値へ正規化。
  • 予防: 他ソートの int 減算も Integer.compare に統一(既存ソート順は不変)。
  • 変更ファイル: src/bms/player/beatoraja/select/BarSorter.java, src/bms/player/beatoraja/select/BarManager.java, src/bms/player/beatoraja/PlayerConfigValidator.java, src/test/java/bms/player/beatoraja/select/BarSorterTest.java(新規) 計 4 件

テスト

  • .\gradlew.bat test : 成功(BUILD SUCCESSFUL、回帰なし)。新規 BarSorterTest で long オーバーフロー回帰・Long.MAX_VALUE センチネル挙動・TimSort contract 整合・exists 境界・非SongBar の TITLE 委譲を網羅。

関連 MR

  • !150 (feature/475 → develop)

他の形式にエクスポート: PDF Atom