操作
バグ #476
完了バグ #474: コードベース健全性: メモリリーク・重大バグの一括調査と修正
外部スキンでプレイ中クラッシュ(JudgeManager ゼロ除算 / 配列外)
バグ #476:
外部スキンでプレイ中クラッシュ(JudgeManager ゼロ除算 / 配列外)
説明
現象¶
不正/特殊なサードパーティスキンを使うと、最初の判定ノートで ArithmeticException: / by zero または ArrayIndexOutOfBoundsException が発生しプレイがクラッシュする。
原因と対象¶
src/bms/player/beatoraja/play/JudgeManager.java:667-668
final int judgeindex = state.lane / (lanelength / judgenow.length);
context.setTimerOn(JUDGE_TIMER[judgeindex]); // JUDGE_TIMER は要素数 3
-
judgenow = new int[judgeregion](:131、judgeregion はスキン由来PlaySkin.getJudgeregion())。 -
judgeregion > states.length(レーン数より判定領域数が多い)のときlanelength / judgenow.length == 0となりゼロ除算。 - 逆に
judgeindex >= 3になる構成でJUDGE_TIMER[judgeindex]が配列外(配列長 3、:635)。
修正方針¶
- 除数が 0 になるケースのガード(
lanelength/judgenow.lengthの関係チェック)。 -
judgeindexをJUDGE_TIMER.lengthでクランプ。 - 実装前に最新の
JudgeManagerを再確認(行番号がもとエージェント調査時点)。
検証¶
- judgeregion がレーン数と不一致な検証用スキンでプレイ開始してもクラッシュしない。
エージェント ちゃん さんが6日前に更新
- ステータス を 未着手 から 実装中 に変更
- 進捗率 を 0 から 10 に変更
実装に着手しました。
- ブランチ:
feature/476 - 対応方針:
JudgeManager.updateMicro()の judgeindex 算出で除数をMath.max(1, ...)でゼロ除算ガードし、judgeindex をmin(JUDGE_TIMER.length, judgenow.length)-1でクランプして配列外参照を防ぐ。
エージェント ちゃん さんが6日前に更新
- ステータス を 実装中 から 完了 に変更
- 進捗率 を 10 から 100 に変更
対応が完了しました。
概要¶
不正/特殊なサードパーティスキンでプレイ開始時、最初の判定ノートで ArithmeticException: / by zero または ArrayIndexOutOfBoundsException が発生しクラッシュする問題を修正。スキン由来の判定領域数 judgeregion がレーン数と不一致な場合に JudgeManager.updateMicro() の judgeindex 算出が破綻するのが原因。
変更点¶
-
judgeindex算出を堅牢化。除数をMath.max(1, lanelength / judgenow.length)でガード(ゼロ除算回避)し、judgeindexをMath.min(…, Math.min(JUDGE_TIMER.length, judgenow.length) - 1)でクランプ(固定長 3 のタイマー配列と judgeregion 長の judgenow 系配列の両方に安全)。 - 正常スキン(
judgeregion1〜3)では算出値が従来と完全一致し、挙動は不変。 - リグレッションテスト 2 件を追加(ゼロ除算パス / 配列外パス)。
- 変更ファイル:
src/bms/player/beatoraja/play/JudgeManager.java,src/test/java/bms/player/beatoraja/play/FakeJudgeContext.java,src/test/java/bms/player/beatoraja/play/JudgeManagerUpdateTest.java(3 件)
テスト¶
-
.\gradlew.bat test: 成功(フルスイート BUILD SUCCESSFUL)
関連 MR¶
- !151 (feature/476 → develop)
操作