Skip to content

fix(scoring): keep the default blood bonus when a stored value is out of range - #599

Open
Wangxiaolu0716 wants to merge 1 commit into
GZTimeWalker:workfrom
Wangxiaolu0716:fix/blood-bonus-default-fallback
Open

Wangxiaolu0716 wants to merge 1 commit into
GZTimeWalker:workfrom
Wangxiaolu0716:fix/blood-bonus-default-fallback

Conversation

@Wangxiaolu0716

@Wangxiaolu0716 Wangxiaolu0716 commented Oct 15, 2026 •

Copy link
Copy Markdown

问题

BloodBonus 是一个带主构造函数的 struct(src/GZCTF/Utils/Shared.cs:231)。越界分支里写的是 new(),而 struct 的 new() 会零初始化,不会取 init = DefaultValue:

new BloodBonus().Val     = 0          // 不是 52459530
new BloodBonus().NoBonus = true
new BloodBonus(x).Val    = x          // 带参数的形式是正常的

所以只要存进去的值超出每档 0..1000 的范围,加成不是被夹紧、也不是保留默认值,而是被整段清零。之后 GameRepository.cs:450 会走 noBonus 分支,排行榜上所有血包加分都没了。

能触发的输入:

  • Games.BloodBonus 列在数据库里默认是 0(bigint NOT NULL,见 Migrations/20240202021414_Initialize.cs:153),存成 0 就会走 FromValue 的越界分支;
  • 管理员在 PUT /api/Edit/Games/{id} 里传一个超过 1000‰ 上限的 BloodBonusValue(Game.cs:203);
  • 任何负值。

前端没有这个问题:那边的 new BloodBonus() 依然返回 (50 << 20) + (30 << 10) + 10(ClientApp/src/utils/Shared.tsx:492)。

改动

  • BloodBonus.FromValue 越界时回退到 new(DefaultValue),一行。
  • 把 FlagChecker.GetWorkerCount() 里的内存/CPU 分档挪进 ResolveWorkerCount(memoryGiB, cpuCount),这样分档可以被单测覆盖。行为不变。
  • 新增 src/GZCTF.Test/UnitTests/Models/ScoringTests.cs:动态计分曲线、血包位打包、worker 分档。这三块之前只有 HTTP 集成测试的间接覆盖。

验证

dotnet test src/GZCTF.Test/GZCTF.Test.csproj -c Debug → 179 passed。

我把那一行改动还原回去跑过一次,确认测试真的能抓到这个 bug:

失败 BloodBonus_OutOfRangeSlot_FallsBackToDefault(invalid: 1049624576)
失败 BloodBonus_OutOfRangeSlot_FallsBackToDefault(invalid: -1001)
失败 BloodBonus_OutOfRangeSlot_FallsBackToDefault(invalid: 1025024)
失败 BloodBonus_OutOfRangeSlot_FallsBackToDefault(invalid: 1023)
失败! - 失败: 4,通过: 22,总计: 26

带上修复是 26/26 全过。没有 schema 变更。

关于 CI

Integration Tests 这次跑到 Build 就失败了,原因是 SixLabors.ImageSharp 找不到 license:

error : No Six Labors license found. Set $(SixLaborsLicenseKey) ...
Build FAILED.  1 Error(s)

SixLaborsLicenseKey 取的是 secrets.SIXLABORS_LICENSE,而 fork 发起的 PR 拿不到仓库 secret,所以这一步在 fork PR 上必然失败;后面两个 test report 步骤因为找不到 .trx 也跟着报错。和本次改动无关。

@hez2010
hez2010 changed the base branch from develop to work October 15, 2026 11:45

This branch has not been deployed

No deployments
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