Prevent dice overflow
rand.Int() would panic when the max value is <= 0, which happens when big.NewInt() was fed with a too large number. Avoid this by validating the big.NewInt() return beforehand. Add error handling to all callers to both gracefully return to IRC and to log an error message. Signed-off-by: Georg Pfuetzenreuter <mail@georg-pfuetzenreuter.net>
This commit is contained in:
parent
e300f71370
commit
94d31e829e
110
wat/game.go
110
wat/game.go
@ -2,6 +2,7 @@ package wat
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -121,9 +122,17 @@ func (g *WatGame) help() string {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *WatGame) RandInt(max int64) uint64 {
|
func (g *WatGame) RandInt(max int64) (uint64, error) {
|
||||||
i, _ := rand.Int(rand.Reader, big.NewInt(max))
|
bi := big.NewInt(max)
|
||||||
return i.Uint64()
|
// prevent panic of rand.Int on big numbers
|
||||||
|
if bi.BitLen() < 2 {
|
||||||
|
return 0, errors.New("overflow")
|
||||||
|
}
|
||||||
|
i, err := rand.Int(rand.Reader, bi)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return i.Uint64(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *WatGame) Heal(player *Player, fields []string) string {
|
func (g *WatGame) Heal(player *Player, fields []string) string {
|
||||||
@ -166,8 +175,11 @@ func (g *WatGame) Dice(player *Player, fields []string) string {
|
|||||||
roll = i
|
roll = i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
answer := g.RandInt(int64(roll)) + 1
|
answer, err := g.RandInt(int64(roll))
|
||||||
return fmt.Sprintf("1d%d - %d", roll, answer)
|
if e := handleError(err); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("1d%d - %d", roll + 1, answer)
|
||||||
}
|
}
|
||||||
|
|
||||||
type PositiveError struct{}
|
type PositiveError struct{}
|
||||||
@ -206,12 +218,20 @@ func (g *WatGame) Roll(player *Player, fields []string) string {
|
|||||||
}
|
}
|
||||||
lotteryNum := int64(-1)
|
lotteryNum := int64(-1)
|
||||||
if dieSize > 100 {
|
if dieSize > 100 {
|
||||||
lotteryNum = int64(g.RandInt(dieSize)) + 1
|
lotteryNumRand, randErr := g.RandInt(dieSize)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
lotteryNum = int64(lotteryNumRand) + 1
|
||||||
}
|
}
|
||||||
if amount > player.Coins {
|
if amount > player.Coins {
|
||||||
return "wat? brokeass"
|
return "wat? brokeass"
|
||||||
}
|
}
|
||||||
n := int64(g.RandInt(dieSize)) + 1
|
nRand, randErr := g.RandInt(dieSize)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
n := int64(nRand) + 1
|
||||||
ret := fmt.Sprintf("%s rolls the %d sided die... %d! ", player.Nick, dieSize, n)
|
ret := fmt.Sprintf("%s rolls the %d sided die... %d! ", player.Nick, dieSize, n)
|
||||||
if n == lotteryNum {
|
if n == lotteryNum {
|
||||||
player.Coins += player.Coins
|
player.Coins += player.Coins
|
||||||
@ -255,11 +275,18 @@ func (g *WatGame) Punch(player *Player, fields []string) string {
|
|||||||
if !target.Conscious() {
|
if !target.Conscious() {
|
||||||
return "wat? you're punching someone who is already unconscious. u crazy?"
|
return "wat? you're punching someone who is already unconscious. u crazy?"
|
||||||
}
|
}
|
||||||
chance := g.RandInt(6) + 1
|
chance, randErr := g.RandInt(6)
|
||||||
dmg := g.RandInt(6) + 1
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
dmg, randErr := g.RandInt(6)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
dmg = dmg + 1
|
||||||
ret := fmt.Sprintf("%s rolls a d6... %s ", player.Nick, player.Nick)
|
ret := fmt.Sprintf("%s rolls a d6... %s ", player.Nick, player.Nick)
|
||||||
dmg += uint64(player.Level(player.Anarchy))
|
dmg += uint64(player.Level(player.Anarchy))
|
||||||
if chance > 3 {
|
if chance + 1 > 3 {
|
||||||
ret += fmt.Sprintf("hits %s for %d points of damage! ", target.Nick, dmg)
|
ret += fmt.Sprintf("hits %s for %d points of damage! ", target.Nick, dmg)
|
||||||
target.Health -= int64(dmg)
|
target.Health -= int64(dmg)
|
||||||
g.db.Update(target)
|
g.db.Update(target)
|
||||||
@ -300,7 +327,11 @@ func (g *WatGame) Frame(player *Player, fields []string) string {
|
|||||||
if target.Coins < amount {
|
if target.Coins < amount {
|
||||||
return fmt.Sprintf("wat? %s is too poor for this.", target.Nick)
|
return fmt.Sprintf("wat? %s is too poor for this.", target.Nick)
|
||||||
}
|
}
|
||||||
n := g.RandInt(6) + 1
|
n, randErr := g.RandInt(6)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
n = n + 1
|
||||||
ret := fmt.Sprintf("%s rolls a d6 to frame %s with %d %s: It's a %d! (<3 wins). ", player.Nick, target.Nick, amount, currency, n)
|
ret := fmt.Sprintf("%s rolls a d6 to frame %s with %d %s: It's a %d! (<3 wins). ", player.Nick, target.Nick, amount, currency, n)
|
||||||
if n < 3 {
|
if n < 3 {
|
||||||
ret += fmt.Sprintf("You frame %s for a minor crime. They pay me %d.", target.Nick, amount)
|
ret += fmt.Sprintf("You frame %s for a minor crime. They pay me %d.", target.Nick, amount)
|
||||||
@ -335,7 +366,11 @@ func (g *WatGame) Steal(player *Player, fields []string) string {
|
|||||||
if target.Coins < amount {
|
if target.Coins < amount {
|
||||||
return fmt.Sprintf("wat? %s is poor and doesn't have that much to steal. (%d %s)", target.Nick, target.Coins, currency)
|
return fmt.Sprintf("wat? %s is poor and doesn't have that much to steal. (%d %s)", target.Nick, target.Coins, currency)
|
||||||
}
|
}
|
||||||
n := g.RandInt(6) + 1
|
n, randErr := g.RandInt(6)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
n = n + 1
|
||||||
ret := fmt.Sprintf("%s is trying to steal %d %s from %s... ", player.Nick, amount, currency, target.Nick)
|
ret := fmt.Sprintf("%s is trying to steal %d %s from %s... ", player.Nick, amount, currency, target.Nick)
|
||||||
if n < 3 {
|
if n < 3 {
|
||||||
ret += "You did it! Sneaky bastard!"
|
ret += "You did it! Sneaky bastard!"
|
||||||
@ -380,7 +415,11 @@ func (g *WatGame) Leech(player *Player, fields []string) string {
|
|||||||
if err != "" {
|
if err != "" {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r := g.RandInt(10) + 1
|
r, randErr := g.RandInt(10)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
r = r + 1
|
||||||
reply := fmt.Sprintf("You muster your wealth and feed it to %s. ", g.bot.Nick)
|
reply := fmt.Sprintf("You muster your wealth and feed it to %s. ", g.bot.Nick)
|
||||||
hpDown := amount / divisor
|
hpDown := amount / divisor
|
||||||
player.Coins -= amount
|
player.Coins -= amount
|
||||||
@ -408,7 +447,11 @@ func (g *WatGame) Rest(player *Player, fields []string) string {
|
|||||||
} else if delta < minRest {
|
} else if delta < minRest {
|
||||||
ret = fmt.Sprintf("wat were you thinking, sleeping at a time like this (%d until next rest)", minRest-delta)
|
ret = fmt.Sprintf("wat were you thinking, sleeping at a time like this (%d until next rest)", minRest-delta)
|
||||||
} else {
|
} else {
|
||||||
value := g.RandInt(10) + 1
|
value, randErr := g.RandInt(10)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
value = value + 1
|
||||||
if player.Health < -5 {
|
if player.Health < -5 {
|
||||||
player.Health = 1
|
player.Health = 1
|
||||||
ret = fmt.Sprintf("wow ur beat up. i pity u, ur health is now 1.")
|
ret = fmt.Sprintf("wow ur beat up. i pity u, ur health is now 1.")
|
||||||
@ -435,8 +478,15 @@ func (g *WatGame) Bench(player *Player, fields []string) string {
|
|||||||
if !g.CanAct(player, Action_Lift, minTime) {
|
if !g.CanAct(player, Action_Lift, minTime) {
|
||||||
return "you're tired. no more lifting for now."
|
return "you're tired. no more lifting for now."
|
||||||
}
|
}
|
||||||
weight := g.RandInt(370) + 50
|
weight, randErr := g.RandInt(370)
|
||||||
reps := g.RandInt(10)
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
weight = weight + 50
|
||||||
|
reps, randErr := g.RandInt(10)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
value := int64(0)
|
value := int64(0)
|
||||||
reply := fmt.Sprintf("%s benches %dwatts for %d reps, ", player.Nick, weight, reps)
|
reply := fmt.Sprintf("%s benches %dwatts for %d reps, ", player.Nick, weight, reps)
|
||||||
if weight < 150 {
|
if weight < 150 {
|
||||||
@ -452,7 +502,10 @@ func (g *WatGame) Bench(player *Player, fields []string) string {
|
|||||||
}
|
}
|
||||||
if g.roid[player.Nick] != 0 {
|
if g.roid[player.Nick] != 0 {
|
||||||
delete(g.roid, player.Nick)
|
delete(g.roid, player.Nick)
|
||||||
success := g.RandInt(2)
|
success, randErr := g.RandInt(2)
|
||||||
|
if randErr != nil {
|
||||||
|
return "woops"
|
||||||
|
}
|
||||||
if success != 0 {
|
if success != 0 {
|
||||||
player.Health = 0
|
player.Health = 0
|
||||||
player.Anarchy -= 10
|
player.Anarchy -= 10
|
||||||
@ -475,7 +528,10 @@ func (g *WatGame) Riot(player *Player, fields []string) string {
|
|||||||
if !g.CanAct(player, Action_Riot, int64((48 * time.Hour).Seconds())) {
|
if !g.CanAct(player, Action_Riot, int64((48 * time.Hour).Seconds())) {
|
||||||
return "Planning a riot takes time and the right circumstances. Be prepared. (nothing happens)"
|
return "Planning a riot takes time and the right circumstances. Be prepared. (nothing happens)"
|
||||||
}
|
}
|
||||||
r := g.RandInt(100)
|
r, randErr := g.RandInt(100)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
reply := ""
|
reply := ""
|
||||||
if r > 40 {
|
if r > 40 {
|
||||||
player.Anarchy += 3
|
player.Anarchy += 3
|
||||||
@ -621,9 +677,21 @@ func PrintTwo(nick string, value uint64) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *WatGame) megaWat(player *Player, _ []string) string {
|
func (g *WatGame) megaWat(player *Player, _ []string) string {
|
||||||
mega := g.RandInt(1000000) + 1
|
mega, randErr := g.RandInt(1000000)
|
||||||
kilo := g.RandInt(1000) + 1
|
if e := handleError(randErr); e != "" {
|
||||||
ten := g.RandInt(100) + 1
|
return e + " mega fail"
|
||||||
|
}
|
||||||
|
mega = mega + 1
|
||||||
|
kilo, randErr := g.RandInt(1000)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e + " kilo fail"
|
||||||
|
}
|
||||||
|
kilo = kilo + 1
|
||||||
|
ten, randErr := g.RandInt(100)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e + " ten fail"
|
||||||
|
}
|
||||||
|
ten = ten + 1
|
||||||
reply := ""
|
reply := ""
|
||||||
if mega == 23 {
|
if mega == 23 {
|
||||||
player.Coins += 1000000
|
player.Coins += 1000000
|
||||||
|
22
wat/utils.go
Normal file
22
wat/utils.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package wat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func handleError(err error) string {
|
||||||
|
if err != nil {
|
||||||
|
pc, _, _, ok := runtime.Caller(1)
|
||||||
|
details := runtime.FuncForPC(pc)
|
||||||
|
var cFun string
|
||||||
|
if ok && details != nil {
|
||||||
|
cFun = details.Name()
|
||||||
|
} else {
|
||||||
|
cFun = "???"
|
||||||
|
}
|
||||||
|
fmt.Printf("caught error in %s: %v\n", cFun, err)
|
||||||
|
return "u wat"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user