-
Notifications
You must be signed in to change notification settings - Fork 3.7k
fix: prevent DefaultConfig template values from leaking into user model_list entries #724
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -499,6 +499,20 @@ func LoadConfig(path string) (*Config, error) { | |||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Pre-scan the JSON to check how many model_list entries the user provided. | ||||||||||||||||||||||||||||
| // Go's JSON decoder reuses existing slice backing-array elements rather than | ||||||||||||||||||||||||||||
| // zero-initializing them, so fields absent from the user's JSON (e.g. api_base) | ||||||||||||||||||||||||||||
| // would silently inherit values from the DefaultConfig template at the same | ||||||||||||||||||||||||||||
| // index position. We only reset cfg.ModelList when the user actually provides | ||||||||||||||||||||||||||||
| // entries; when count is 0 we keep DefaultConfig's built-in list as fallback. | ||||||||||||||||||||||||||||
| var tmp Config | ||||||||||||||||||||||||||||
| if err := json.Unmarshal(data, &tmp); err != nil { | ||||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| if len(tmp.ModelList) > 0 { | ||||||||||||||||||||||||||||
|
Comment on lines
+508
to
+512
|
||||||||||||||||||||||||||||
| var tmp Config | |
| if err := json.Unmarshal(data, &tmp); err != nil { | |
| return nil, err | |
| } | |
| if len(tmp.ModelList) > 0 { | |
| type modelListEnvelope struct { | |
| ModelList *[]json.RawMessage `json:"model_list"` | |
| } | |
| var pre modelListEnvelope | |
| if err := json.Unmarshal(data, &pre); err != nil { | |
| return nil, err | |
| } | |
| if pre.ModelList != nil && len(*pre.ModelList) > 0 { |
Copilot
AI
Feb 24, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change fixes a subtle encoding/json slice-reuse bug but currently has no direct regression test. Please add a LoadConfig unit test that writes a config with model_list containing a single entry that omits api_base, calls LoadConfig, and asserts the resulting cfg.ModelList[0].APIBase is empty (and does not inherit the DefaultConfig template value). A second assertion for the “model_list omitted” case preserving DefaultConfig can help lock in the intended fallback behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic
len(tmp.ModelList) > 0can’t distinguish between (a)model_listmissing and (b)model_listpresent but empty ([]) ornull—all yield length 0 intmp. If the intended behavior is “missing/empty keeps DefaultConfig model list as fallback”, the subsequentjson.Unmarshal(data, cfg)will still clear the default slice whenmodel_list: []is explicitly present. Either adjust the comment/PR semantics to state the fallback only applies when the field is omitted, or change the pre-scan to detect field presence (e.g.,*[]json.RawMessageormap[string]json.RawMessage) and handle empty-vs-missing explicitly.