Description
A regression we noticed on attempting to update to v1.11.0 from v1.10.1, specifically in binding/form_mapping.go setByForm().
Previously the following code would execute in tests, now it panics:
// You can edit this code!
// Click here and start typing.
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"strconv"
"github.com/gin-gonic/gin"
)
type ReportCreateRequest struct {
AccountID string `form:"account_id" json:"account_id" xml:"account_id"`
StatusIDs []string `form:"status_ids[]" json:"status_ids" xml:"status_ids"`
Comment string `form:"comment" json:"comment" xml:"comment"`
Forward bool `form:"forward" json:"forward" xml:"forward"`
Category string `form:"category" json:"category" xml:"category"`
RuleIDs []string `form:"rule_ids[]" json:"rule_ids" xml:"rule_ids"`
}
func setForm(c *gin.Context, form *ReportCreateRequest) {
c.Request.Form = url.Values{
"account_id": {form.AccountID},
"status_ids[]": form.StatusIDs,
"comment": {form.Comment},
"forward": {strconv.FormatBool(form.Forward)},
"category": {form.Category},
"rule_ids[]": form.RuleIDs,
}
}
func main() {
for _, test := range []*ReportCreateRequest{
{
AccountID: "some account id",
StatusIDs: []string{},
Comment: "",
Forward: false,
},
} {
rw := httptest.NewRecorder()
c, _ := gin.CreateTestContext(rw)
c.Request = new(http.Request)
setForm(c, test)
var form ReportCreateRequest
err := c.ShouldBind(&form)
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("success: %+v\n", form)
}
}
}
which produces the following output if run:
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
panic: runtime error: index out of range [0] with length 0
goroutine 1 [running]:
github.com/gin-gonic/gin/binding.setByForm({0xdaff60?, 0xc0000f4da0?, 0xdc54cc?}, {{0xdc54bd, 0x9}, {0x0, 0x0}, {0x109f370, 0xdaff60}, {0xdc54c7, ...}, ...}, ...)
github.com/gin-gonic/gin@v1.11.0/binding/form_mapping.go:243 +0x792
github.com/gin-gonic/gin/binding.formSource.TrySet(0x41c4e6?, {0xdaff60?, 0xc0000f4da0?, 0xdc54cd?}, {{0xdc54bd, 0x9}, {0x0, 0x0}, {0x109f370, 0xdaff60}, ...}, ...)
github.com/gin-gonic/gin@v1.11.0/binding/form_mapping.go:74 +0x87
github.com/gin-gonic/gin/binding.tryToSetValue({0xdaff60?, 0xc0000f4da0?, 0x4c33cf?}, {{0xdc54bd, 0x9}, {0x0, 0x0}, {0x109f370, 0xdaff60}, {0xdc54c7, ...}, ...}, ...)
github.com/gin-gonic/gin@v1.11.0/binding/form_mapping.go:173 +0x391
github.com/gin-gonic/gin/binding.mapping({0xdaff60?, 0xc0000f4da0?, 0x3?}, {{0xdc54bd, 0x9}, {0x0, 0x0}, {0x109f370, 0xdaff60}, {0xdc54c7, ...}, ...}, ...)
github.com/gin-gonic/gin@v1.11.0/binding/form_mapping.go:107 +0x148
github.com/gin-gonic/gin/binding.mapping({0xe81900?, 0xc0000f4d90?, 0xc0000e7b70?}, {{0x0, 0x0}, {0x0, 0x0}, {0x0, 0x0}, {0x0, ...}, ...}, ...)
github.com/gin-gonic/gin@v1.11.0/binding/form_mapping.go:125 +0x498
github.com/gin-gonic/gin/binding.mapping({0xd9e040?, 0xc0000f4d90?, 0x4c4689?}, {{0x0, 0x0}, {0x0, 0x0}, {0x0, 0x0}, {0x0, ...}, ...}, ...)
github.com/gin-gonic/gin@v1.11.0/binding/form_mapping.go:96 +0x2e5
github.com/gin-gonic/gin/binding.mappingByPtr({0xd9e040?, 0xc0000f4d90?}, {0x108b820?, 0xc000238540?}, {0xed8b2d?, 0x16db080?})
github.com/gin-gonic/gin@v1.11.0/binding/form_mapping.go:78 +0xed
github.com/gin-gonic/gin/binding.mapFormByTag({0xd9e040, 0xc0000f4d90?}, 0xc000238540, {0xed8b2d, 0x4})
github.com/gin-gonic/gin@v1.11.0/binding/form_mapping.go:60 +0x1e8
github.com/gin-gonic/gin/binding.mapForm(...)
github.com/gin-gonic/gin@v1.11.0/binding/form_mapping.go:35
github.com/gin-gonic/gin/binding.formBinding.Bind({}, 0xc0001c6500, {0xd9e040, 0xc0000f4d90})
github.com/gin-gonic/gin@v1.11.0/binding/form.go:31 +0x90
github.com/gin-gonic/gin.(*Context).ShouldBindWith(...)
github.com/gin-gonic/gin@v1.11.0/context.go:870
github.com/gin-gonic/gin.(*Context).ShouldBind(0xc0001fc100, {0xd9e040, 0xc0000f4d90})
github.com/gin-gonic/gin@v1.11.0/context.go:820 +0x34c
main.main()
tmp/main.go:51 +0x539
exit status 2
Gin Version
v1.11.0
Can you reproduce the bug?
Yes
Source Code
No response
Go Version
go1.25
Operating System
No response