From 58f62bff4807dc650f1309165aebbbbcfef65c28 Mon Sep 17 00:00:00 2001 From: Trevor Slocum Date: Tue, 30 Jul 2024 14:41:41 -0700 Subject: [PATCH] Fix int8 overflow when operating on match and player point values --- pkg/server/game.go | 4 ++-- pkg/server/server.go | 25 +++++++++++++++++++++++++ pkg/server/server_command.go | 8 +++++--- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/pkg/server/game.go b/pkg/server/game.go index da42e15..cc29c74 100644 --- a/pkg/server/game.go +++ b/pkg/server/game.go @@ -666,7 +666,7 @@ func (g *serverGame) handleWin() bool { var reset bool if g.Winner == 1 { winEvent.Player = g.Player1.Name - g.Player1.Points = g.Player1.Points + winPoints*g.DoubleValue + g.Player1.Points = add8(g.Player1.Points, mul8(winPoints, g.DoubleValue)) if g.Player1.Points < g.Points { reset = true } else { @@ -674,7 +674,7 @@ func (g *serverGame) handleWin() bool { } } else { winEvent.Player = g.Player2.Name - g.Player2.Points = g.Player2.Points + winPoints*g.DoubleValue + g.Player2.Points = add8(g.Player2.Points, mul8(winPoints, g.DoubleValue)) if g.Player2.Points < g.Points { reset = true } else { diff --git a/pkg/server/server.go b/pkg/server/server.go index d86992e..86e1042 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -556,6 +556,31 @@ func RandInt(max int) int { return int(i.Int64()) } +// add8 adds two int8 values without overflowing. +func add8(a int8, b int8) int8 { + v := a + for i := int8(0); i < b; i++ { + a++ + if a < 0 { + return 127 + } + v++ + } + return v +} + +// mul8 multiplies two int8 values without overflowing. +func mul8(a int8, b int8) int8 { + var v int8 + for i := int8(0); i < b; i++ { + v = add8(v, a) + if v == 127 { + return v + } + } + return v +} + func gnubgPosition(g *bgammon.Game) string { var opponent int8 = 2 start := 0 diff --git a/pkg/server/server_command.go b/pkg/server/server_command.go index 4e24b2e..8207a28 100644 --- a/pkg/server/server_command.go +++ b/pkg/server/server_command.go @@ -395,9 +395,11 @@ COMMANDS: } points, err := strconv.Atoi(string(gamePoints)) - if err != nil || points < 1 || points > 99 { + if err != nil || points < 1 { sendUsage() continue + } else if points > 127 { + points = 127 } // Set default game name. @@ -614,10 +616,10 @@ COMMANDS: var reset bool if clientGame.Winner == 1 { - clientGame.Player1.Points = clientGame.Player1.Points + clientGame.DoubleValue + clientGame.Player1.Points = add8(clientGame.Player1.Points, clientGame.DoubleValue) reset = clientGame.Player1.Points < clientGame.Points } else { - clientGame.Player2.Points = clientGame.Player2.Points + clientGame.DoubleValue + clientGame.Player2.Points = add8(clientGame.Player2.Points, clientGame.DoubleValue) reset = clientGame.Player2.Points < clientGame.Points } clientGame.addReplayHeader()