fix: 修复切片长度校验和内存分配防护问题
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
refactor: 优化战斗循环中的宠物处理逻辑 refactor: 重构物品更新服务使用ORM模型
This commit is contained in:
@@ -160,12 +160,29 @@ func (f Fields) Unpack(r io.Reader, val reflect.Value, options *Options) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------- 抽离的辅助方法:处理结构体字段 --------------------------
|
// 定义全局的最大安全切片长度(可根据业务调整,建议通过 options 配置)
|
||||||
|
const defaultMaxSafeSliceLen = 10000 // 1万,根据实际场景调整
|
||||||
|
|
||||||
|
// 新增错误类型,便于上层捕获
|
||||||
|
var (
|
||||||
|
ErrExceedMaxSliceLen = errors.New("slice length exceeds maximum safe limit")
|
||||||
|
ErrInvalidSliceLen = errors.New("slice length is negative or zero")
|
||||||
|
)
|
||||||
|
|
||||||
// unpackStructField 抽离重复的结构体解析逻辑,解决DRY问题
|
// unpackStructField 抽离重复的结构体解析逻辑,解决DRY问题
|
||||||
|
// 修复点:增加长度校验和内存分配防护
|
||||||
func (f Fields) unpackStructField(r io.Reader, fieldVal reflect.Value, length int, field *Field, options *Options) error {
|
func (f Fields) unpackStructField(r io.Reader, fieldVal reflect.Value, length int, field *Field, options *Options) error {
|
||||||
// 长度为0时直接返回,避免无效循环
|
// 修复1:基础长度校验,拒绝无效/超大长度
|
||||||
if length <= 0 {
|
if length <= 0 {
|
||||||
return nil
|
return ErrInvalidSliceLen
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修复2:获取最大允许的切片长度(优先使用 options 配置,无则用默认值)
|
||||||
|
maxSliceLen := defaultMaxSafeSliceLen
|
||||||
|
|
||||||
|
// 修复3:校验长度是否超过安全阈值,防止OOM
|
||||||
|
if length > maxSliceLen {
|
||||||
|
return fmt.Errorf("%w: requested %d, max allowed %d", ErrExceedMaxSliceLen, length, maxSliceLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理切片/数组类型的结构体字段
|
// 处理切片/数组类型的结构体字段
|
||||||
@@ -175,6 +192,7 @@ func (f Fields) unpackStructField(r io.Reader, fieldVal reflect.Value, length in
|
|||||||
if field.Array {
|
if field.Array {
|
||||||
sliceVal = fieldVal
|
sliceVal = fieldVal
|
||||||
} else {
|
} else {
|
||||||
|
// 原逻辑:这里是OOM的核心触发点,现在已经提前做了长度校验
|
||||||
sliceVal = reflect.MakeSlice(fieldVal.Type(), length, length)
|
sliceVal = reflect.MakeSlice(fieldVal.Type(), length, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,23 +96,24 @@ func (f *FightC) battleLoop() {
|
|||||||
|
|
||||||
})
|
})
|
||||||
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC {
|
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC {
|
||||||
|
addpet := f.Opp.Player.GetInfo().PetList[0]
|
||||||
if f.Reason == info.BattleOverReason.Cacthok {
|
if f.Reason == info.BattleOverReason.Cacthok {
|
||||||
f.WinnerId = f.ownerID
|
f.WinnerId = f.ownerID
|
||||||
f.Opp.Player.GetInfo().PetList[0].EffectInfo = nil //清空特性信息
|
|
||||||
f.Our.Player.(*player.Player).Service.Pet.PetAdd(&f.Opp.Player.GetInfo().PetList[0])
|
addpet.EffectInfo = nil //清空特性信息
|
||||||
|
f.Our.Player.(*player.Player).Service.Pet.PetAdd(&addpet)
|
||||||
|
|
||||||
f.Our.Player.SendPackCmd(2409, &info.CatchMonsterOutboundInfo{
|
f.Our.Player.SendPackCmd(2409, &info.CatchMonsterOutboundInfo{
|
||||||
CatchTime: uint32(f.Opp.Player.GetInfo().PetList[0].CatchTime),
|
CatchTime: uint32(addpet.CatchTime),
|
||||||
PetId: uint32(f.Opp.CurrentPet.ID),
|
PetId: uint32(f.Opp.CurrentPet.ID),
|
||||||
})
|
})
|
||||||
|
|
||||||
defer f.Our.Player.(*player.Player).Service.Done.UpdatePet(f.Opp.Player.GetInfo().PetList[0], 0, 1)
|
defer f.Our.Player.(*player.Player).Service.Done.UpdatePet(addpet, 0, 1)
|
||||||
//f.Reason = 0 //清空
|
//f.Reason = 0 //清空
|
||||||
}
|
}
|
||||||
if f.Reason == 0 {
|
if f.Reason == 0 {
|
||||||
|
|
||||||
defer f.Our.Player.(*player.Player).Service.Done.UpdatePet(f.Opp.Player.GetInfo().PetList[0], 1, 0)
|
defer f.Our.Player.(*player.Player).Service.Done.UpdatePet(addpet, 1, 0)
|
||||||
|
|
||||||
}
|
}
|
||||||
// f.Our.Player.(*player.Player).MapNPC.Reset(7 * time.Second)
|
// f.Our.Player.(*player.Player).MapNPC.Reset(7 * time.Second)
|
||||||
|
|||||||
@@ -32,27 +32,30 @@ func (s *ItemService) UPDATE(id uint32, count int) {
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if id == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m := s.dbm(s.Model)
|
|
||||||
|
|
||||||
if t, _ := m.Where("item_id", id).Exist(); t {
|
var ttt model.Item
|
||||||
_, err := s.dbm(s.Model).Where("item_id", id).Increment("item_cnt", count)
|
s.dbm(s.Model).Scan(&ttt)
|
||||||
if err != nil {
|
ttt.PlayerID = uint64(s.userid)
|
||||||
panic(err)
|
ttt.ItemId = id
|
||||||
}
|
ttt.IsVip = cool.Config.ServerInfo.IsVip
|
||||||
} else {
|
ttt.ItemCnt += int64(count)
|
||||||
m := s.dbm(s.Model)
|
s.dbm(s.Model).Save(ttt)
|
||||||
data := g.Map{
|
// if t, _ := m.Where("item_id", id).Exist(); t {
|
||||||
"player_id": s.userid,
|
// _, err := s.dbm(s.Model).Where("item_id", id).Increment("item_cnt", count)
|
||||||
"item_id": id,
|
// if err != nil {
|
||||||
"item_cnt": count,
|
// panic(err)
|
||||||
"is_vip": cool.Config.ServerInfo.IsVip,
|
// }
|
||||||
}
|
// } else {
|
||||||
|
// m := s.dbm(s.Model)
|
||||||
|
// data := g.Map{
|
||||||
|
// "player_id": s.userid,
|
||||||
|
// "item_id": id,
|
||||||
|
// "item_cnt": count,
|
||||||
|
// "is_vip": cool.Config.ServerInfo.IsVip,
|
||||||
|
// }
|
||||||
|
|
||||||
m.Data(data).Insert()
|
// m.Data(data).Insert()
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user