Skip to content

Fix nil pointer panics and bugs in lobby/room/battle code#359

Merged
inada-s merged 1 commit into
masterfrom
fix/lobby-nil-checks-and-slice-bugs
Mar 2, 2026
Merged

Fix nil pointer panics and bugs in lobby/room/battle code#359
inada-s merged 1 commit into
masterfrom
fix/lobby-nil-checks-and-slice-bugs

Conversation

@inada-s

@inada-s inada-s commented Mar 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • Fix nil pointer dereference panics in sendLobbyChat, NotifyLobbyEvent, NotifyRoomEvent when FindPeer returns nil for a disconnected user still in the Users map
  • Add nil lobby guard in BroadcastLobbyMatchEntryUserCount (unlike BroadcastLobbyUserCount which already had one)
  • Add break after slice removal in Exit, EntryCancel, EntryPicked to prevent incorrect iteration after modifying the slice
  • Remove dead code p.udpAddr.IP.IsLoopback() in makeP2PMatchingMsg that was a no-op and potential nil panic
  • Fix nil-before-append order in checkRoomBattleStart renpo room scan to match the zeon side pattern
  • Fix off-by-one boundary check (<<=) in GetUserByPos, GetGameParamByPos, GetUserRankByPos

Test plan

  • Added TestLbsLobby_sendLobbyChat_NilPeer - verifies no panic with nil peer
  • Added TestLbsLobby_NotifyLobbyEvent_NilPeer - verifies no panic with nil peer
  • Added TestLbsRoom_NotifyRoomEvent_NilPeer - verifies no panic with nil peer
  • Added TestBroadcastLobbyMatchEntryUserCount_NilLobby - verifies no panic with nil lobby
  • Added TestLbsLobby_Exit_RemovesEntryUser / TestLbsLobby_Exit_NonEntryUser - verifies correct slice removal
  • Added TestLbsLobby_EntryCancel / TestLbsLobby_EntryPicked - verifies correct entry removal
  • Added TestLbsRoom_Enter / TestLbsRoom_Exit / TestLbsRoom_Remove - verifies room state transitions
  • Updated TestLbsBattle_GetUserByPos / GetGameParamByPos / GetUserRankByPos - boundary returns nil/0 instead of panic
  • All existing tests pass (make test)
  • Lint clean (make lint)

- Add nil checks for FindPeer in sendLobbyChat, NotifyLobbyEvent, NotifyRoomEvent
- Add nil lobby guard in BroadcastLobbyMatchEntryUserCount
- Add break after slice removal in Exit, EntryCancel, EntryPicked
- Remove dead code (IsLoopback no-op) in makeP2PMatchingMsg
- Fix nil-before-append order in checkRoomBattleStart renpo scan
- Fix off-by-one boundary check in GetUserByPos, GetGameParamByPos, GetUserRankByPos
- Add tests for all fixed issues

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@inada-s inada-s requested a review from Copilot March 2, 2026 10:15
@inada-s inada-s merged commit 154a2a9 into master Mar 2, 2026
4 checks passed
@inada-s inada-s deleted the fix/lobby-nil-checks-and-slice-bugs branch March 2, 2026 10:17

Copilot 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.

Pull request overview

This PR hardens the lobby/room/battle flows against nil pointer panics and a few boundary/iteration bugs, with accompanying regression tests to ensure the server no longer panics in common disconnect/stale-user scenarios.

Changes:

  • Add nil guards around FindPeer() results (lobby chat/events, room events) and around BroadcastLobbyMatchEntryUserCount(nil).
  • Fix off-by-one bounds checks in LbsBattle getters and adjust tests to assert safe returns rather than panics.
  • Fix slice-modification iteration issues in lobby entry removal paths (Exit/EntryCancel/EntryPicked) and adjust room battle peer collection to avoid nil-before-append.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
gdxsv/lbs_lobby.go Adds nil checks for peers, fixes iteration after slice removal, removes dead code, and fixes peer collection ordering.
gdxsv/lbs_room.go Prevents nil deref in NotifyRoomEvent when FindPeer returns nil.
gdxsv/lbs_battle.go Fixes off-by-one bounds checks to avoid out-of-range panics.
gdxsv/lbs.go Adds nil guard to BroadcastLobbyMatchEntryUserCount.
gdxsv/lbs_lobby_test.go Adds regression tests for nil-peer handling and entry removal behaviors.
gdxsv/lbs_room_test.go Adds new room behavior/state transition and nil-peer tests.
gdxsv/lbs_battle_test.go Updates tests to validate safe out-of-bounds behavior instead of expecting panics.
gdxsv/lbs_test.go Adds regression test for nil lobby in BroadcastLobbyMatchEntryUserCount.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread gdxsv/lbs_lobby.go
Comment on lines 395 to 401
delete(l.Users, userID)
for i, id := range l.EntryUsers {
if id == userID {
l.EntryUsers = append(l.EntryUsers[:i], l.EntryUsers[i+1:]...)
l.CancelForceStart()
break
}

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

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

The new break means only the first matching occurrence is removed from EntryUsers. Since Entry() appends p.UserID without checking for duplicates, EntryUsers can contain the same user multiple times (e.g., repeated lbsLobbyMatchingEntry enable=1), leaving stale extra entries after Exit and causing incorrect counts/force-start logic. Consider enforcing uniqueness on insert, or removing all occurrences safely when deleting.

Copilot uses AI. Check for mistakes.
Comment thread gdxsv/lbs_lobby.go
Comment on lines 421 to 426
l.CancelForceStart()
for i, id := range l.EntryUsers {
if id == p.UserID {
l.EntryUsers = append(l.EntryUsers[:i], l.EntryUsers[i+1:]...)
break
}

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

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

EntryCancel now breaks after removing the first matching element. If EntryUsers contains duplicates (possible because Entry() appends without deduping), this will leave additional occurrences behind and can inflate GetLobbyMatchEntryUserCount() / allow a user to be picked multiple times. Consider deduping on Entry() or removing all occurrences here.

Copilot uses AI. Check for mistakes.
Comment thread gdxsv/lbs_lobby.go
Comment on lines 440 to 444
for i, id := range l.EntryUsers {
if id == p.UserID {
l.EntryUsers = append(l.EntryUsers[:i], l.EntryUsers[i+1:]...)
break
}

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

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

EntryPicked now removes only the first occurrence due to the added break. If duplicates can be present in EntryUsers (since Entry() unconditionally appends), one user may remain "entered" after being picked, affecting later counts and selection. Consider ensuring EntryUsers is unique or removing all matches.

Copilot uses AI. Check for mistakes.
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