[fix][evaluation] guard nil BaseInfo and nil correction to prevent panics in experiment result and record correction paths - #628
Open
xueyizheng wants to merge 1 commit into
Open
Conversation
线上两个独立 panic,同属判空缺失: 1. SG BatchGetExperimentResult → EvalTargetRecordDO2DTO: 构造 DTO 时在结构体字面量里直接取 src.BaseInfo.CreatedAt, 后面虽有 if src.BaseInfo != nil 保护,但发生在直接访问之后。 BaseInfo 为 nil 的 target record 会打挂整次请求,网关侧表现为 502。 改为先构造空 BaseInfo,判空后再赋值。 2. CN CorrectEvaluatorRecordOApi → CorrectEvaluatorRecord: 领域实现第一行即 correctionDO.UpdatedBy = ..., 请求未带 correction 时 correctionDO 为 nil,直接 panic。 在领域层加 record / correction 判空返回参数错误, 并在 OApi 层前置校验 correction,缺失时返回结构化 4xx 而非透传。 补回归单测:两处均验证 nil 入参不 panic;nil 参数校验先于任何 repo / publisher 调用生效。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
bitholic
self-requested a review
August 24, 2026 14:23
bitholic
approved these changes
Aug 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What type of PR is this?
fix
Check the PR title
[x] This PR title match the format: [][]
[x] The description of this PR title is user-oriented and clear enough for others to understand.
[ ] Add documentation if the current PR requires user awareness at the usage level.
[x] This PR is written in English. PRs not in English will not be reviewed.
(Optional) More detailed description for this PR
Fixes two independent nil pointer dereferences in the evaluation module. Both follow the same shape: a pointer field is dereferenced before it is checked, so a single record or request with a missing optional field takes down the whole call instead of degrading gracefully.
The DTO is built with CreatedAt: src.BaseInfo.CreatedAt inside the struct literal. The if src.BaseInfo != nil check below it is dead as a guard, because the dereference already happened while evaluating the literal.
BaseInfo is an optional field on EvalTargetRecord, so any record that has it unset panics the conversion. Since this convertor runs in the fan-out of BatchGetExperimentResult, one such record fails the entire batch rather than just its own row, and the caller sees a 5xx instead of partial results.
Fix: initialize an empty BaseInfo in the literal and populate the timestamps inside the existing nil check. The CreatedBy / UpdatedBy TODOs move with them, so they are guarded too when someone eventually fills them in.
EvaluatorRecordServiceImpl.CorrectEvaluatorRecord starts with correctionDO.UpdatedBy = userIDInContext, before any validation. The method already defensively initializes EvaluatorOutputData, EvaluatorResult and BaseInfo a few lines further down, so the intent is clearly to tolerate a sparsely populated record — the correction argument was simply missed.
Correction is optional in the request, and OpenAPICorrectionDTO2DO returns nil for a nil DTO by design. So a CorrectEvaluatorRecordOApi call that omits correction reaches the domain service with correctionDO == nil and panics on a caller mistake that should have been a 4xx.
Fix, at two levels:
domain service: reject nil evaluatorRecordDO / correctionDO with
CommonInvalidParamCode before touching either.
OpenAPI handler: validate req.Correction up front, so a malformed request
gets a structured invalid-param error and never reaches the domain layer.
Tests
Three regression tests, one per guarded entry point:
TestEvalTargetRecordDO2DTO_NilBaseInfo — a record with BaseInfo: nil
converts without panicking and yields a non-nil, empty BaseInfo.
TestEvaluatorRecordServiceImpl_CorrectEvaluatorRecord_NilParams — all three
nil combinations return an error, and the repo / publisher mocks assert
Times(0) so validation is proven to run before any side effect.
eval_openapi_app_test.go gains a nil correction case asserting
CommonInvalidParamCode with auth and the record service never invoked.
Each test was checked against the unpatched code and fails there with invalid memory address or nil pointer dereference, so they pin the actual defect rather than passing vacuously.
Two pre-existing cases in TestEvalOpenAPIApplication_CorrectEvaluatorRecordOApi (record not found, auth failed) omitted Correction and are now short-circuited by the new up-front check. They were given a valid correction so they still exercise their intended paths.
Note for reviewers: these packages need -gcflags="all=-N -l" (required by mockey); without it unrelated cases fail their own self-check.