mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 07:32:32 +01:00
fix: array bound crashes on clans.
This commit is contained in:
@@ -86,7 +86,18 @@ func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte {
|
||||
}
|
||||
}
|
||||
bf.WriteUint32(uint32(channelserver.TimeAdjusted().Unix()))
|
||||
bf.WriteUint32(uint32(s.erupeConfig.GameplayOptions.ClanMemberLimits[len(s.erupeConfig.GameplayOptions.ClanMemberLimits)-1][1]))
|
||||
|
||||
// ClanMemberLimits requires at least 1 element with 2 columns to avoid index out of range panics
|
||||
// Use default value (60) if array is empty or last row is too small
|
||||
var maxClanMembers uint8 = 60
|
||||
if len(s.erupeConfig.GameplayOptions.ClanMemberLimits) > 0 {
|
||||
lastRow := s.erupeConfig.GameplayOptions.ClanMemberLimits[len(s.erupeConfig.GameplayOptions.ClanMemberLimits)-1]
|
||||
if len(lastRow) > 1 {
|
||||
maxClanMembers = lastRow[1]
|
||||
}
|
||||
}
|
||||
bf.WriteUint32(uint32(maxClanMembers))
|
||||
|
||||
return bf.Data()
|
||||
}
|
||||
|
||||
|
||||
171
server/entranceserver/make_resp_test.go
Normal file
171
server/entranceserver/make_resp_test.go
Normal file
@@ -0,0 +1,171 @@
|
||||
package entranceserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
_config "erupe-ce/config"
|
||||
)
|
||||
|
||||
// TestEncodeServerInfo_EmptyClanMemberLimits verifies the crash is FIXED when ClanMemberLimits is empty
|
||||
// Previously panicked: runtime error: index out of range [-1]
|
||||
// From erupe.log.1:659922
|
||||
// After fix: Should handle empty array gracefully with default value (60)
|
||||
func TestEncodeServerInfo_EmptyClanMemberLimits(t *testing.T) {
|
||||
config := &_config.Config{
|
||||
RealClientMode: _config.Z1,
|
||||
Host: "127.0.0.1",
|
||||
Entrance: _config.Entrance{
|
||||
Enabled: true,
|
||||
Port: 53310,
|
||||
Entries: []_config.EntranceServerInfo{
|
||||
{
|
||||
Name: "TestServer",
|
||||
Description: "Test",
|
||||
IP: "127.0.0.1",
|
||||
Type: 0,
|
||||
Recommended: 0,
|
||||
AllowedClientFlags: 0xFFFFFFFF,
|
||||
Channels: []_config.EntranceChannelInfo{
|
||||
{
|
||||
Port: 54001,
|
||||
MaxPlayers: 100,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
GameplayOptions: _config.GameplayOptions{
|
||||
ClanMemberLimits: [][]uint8{}, // Empty array - should now use default (60) instead of panicking
|
||||
},
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
logger: zap.NewNop(),
|
||||
erupeConfig: config,
|
||||
}
|
||||
|
||||
// Set up defer to catch ANY panic - we should NOT get array bounds panic anymore
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
// If panic occurs, it should NOT be from array access
|
||||
panicStr := fmt.Sprintf("%v", r)
|
||||
if strings.Contains(panicStr, "index out of range") {
|
||||
t.Errorf("Array bounds panic NOT fixed! Still getting: %v", r)
|
||||
} else {
|
||||
// Other panic is acceptable (network, DB, etc) - we only care about array bounds
|
||||
t.Logf("Non-array-bounds panic (acceptable): %v", r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// This should NOT panic on array bounds anymore - should use default value 60
|
||||
result := encodeServerInfo(config, server, true)
|
||||
if len(result) > 0 {
|
||||
t.Log("✅ encodeServerInfo handled empty ClanMemberLimits without array bounds panic")
|
||||
}
|
||||
}
|
||||
|
||||
// TestClanMemberLimitsBoundsChecking verifies bounds checking logic for ClanMemberLimits
|
||||
// Tests the specific logic that was fixed without needing full database setup
|
||||
func TestClanMemberLimitsBoundsChecking(t *testing.T) {
|
||||
// Test the bounds checking logic directly
|
||||
testCases := []struct {
|
||||
name string
|
||||
clanMemberLimits [][]uint8
|
||||
expectedValue uint8
|
||||
expectDefault bool
|
||||
}{
|
||||
{"empty array", [][]uint8{}, 60, true},
|
||||
{"single row with 2 columns", [][]uint8{{1, 50}}, 50, false},
|
||||
{"single row with 1 column", [][]uint8{{1}}, 60, true},
|
||||
{"multiple rows, last has 2 columns", [][]uint8{{1, 10}, {2, 20}, {3, 60}}, 60, false},
|
||||
{"multiple rows, last has 1 column", [][]uint8{{1, 10}, {2, 20}, {3}}, 60, true},
|
||||
{"multiple rows with valid data", [][]uint8{{1, 10}, {2, 20}, {3, 30}, {4, 40}, {5, 50}}, 50, false},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Replicate the bounds checking logic from the fix
|
||||
var maxClanMembers uint8 = 60
|
||||
if len(tc.clanMemberLimits) > 0 {
|
||||
lastRow := tc.clanMemberLimits[len(tc.clanMemberLimits)-1]
|
||||
if len(lastRow) > 1 {
|
||||
maxClanMembers = lastRow[1]
|
||||
}
|
||||
}
|
||||
|
||||
// Verify correct behavior
|
||||
if maxClanMembers != tc.expectedValue {
|
||||
t.Errorf("Expected value %d, got %d", tc.expectedValue, maxClanMembers)
|
||||
}
|
||||
|
||||
if tc.expectDefault && maxClanMembers != 60 {
|
||||
t.Errorf("Expected default value 60, got %d", maxClanMembers)
|
||||
}
|
||||
|
||||
t.Logf("✅ %s: Safe bounds access, value = %d", tc.name, maxClanMembers)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TestEncodeServerInfo_MissingSecondColumnClanMemberLimits tests accessing [last][1] when [last] is too small
|
||||
// Previously panicked: runtime error: index out of range [1]
|
||||
// After fix: Should handle missing column gracefully with default value (60)
|
||||
func TestEncodeServerInfo_MissingSecondColumnClanMemberLimits(t *testing.T) {
|
||||
config := &_config.Config{
|
||||
RealClientMode: _config.Z1,
|
||||
Host: "127.0.0.1",
|
||||
Entrance: _config.Entrance{
|
||||
Enabled: true,
|
||||
Port: 53310,
|
||||
Entries: []_config.EntranceServerInfo{
|
||||
{
|
||||
Name: "TestServer",
|
||||
Description: "Test",
|
||||
IP: "127.0.0.1",
|
||||
Type: 0,
|
||||
Recommended: 0,
|
||||
AllowedClientFlags: 0xFFFFFFFF,
|
||||
Channels: []_config.EntranceChannelInfo{
|
||||
{
|
||||
Port: 54001,
|
||||
MaxPlayers: 100,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
GameplayOptions: _config.GameplayOptions{
|
||||
ClanMemberLimits: [][]uint8{
|
||||
{1}, // Only 1 element, code used to panic accessing [1]
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
logger: zap.NewNop(),
|
||||
erupeConfig: config,
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
panicStr := fmt.Sprintf("%v", r)
|
||||
if strings.Contains(panicStr, "index out of range") {
|
||||
t.Errorf("Array bounds panic NOT fixed! Still getting: %v", r)
|
||||
} else {
|
||||
t.Logf("Non-array-bounds panic (acceptable): %v", r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// This should NOT panic on array bounds anymore - should use default value 60
|
||||
result := encodeServerInfo(config, server, true)
|
||||
if len(result) > 0 {
|
||||
t.Log("✅ encodeServerInfo handled missing ClanMemberLimits column without array bounds panic")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user