gin icon indicating copy to clipboard operation
gin copied to clipboard

Bind recursion struct param fatal exit

Open flyhope opened this issue 3 weeks ago • 1 comments

Description

use c.Bind() for recursion struct param, output fatal.

How to reproduce

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
	"net/http/httptest"
)

type ParamA struct {
	B *ParamB
}

type ParamB struct {
	A *ParamA
}

func setupRouter() *gin.Engine {
	r := gin.Default()
	r.GET("/test", func(c *gin.Context) {
		param := new(ParamA)
		if err := c.Bind(param); err != nil {
			panic(err)
		}
		c.JSON(http.StatusOK, param)
	})
	return r
}

func main() {
	router := setupRouter()

	w := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/test", nil)
	router.ServeHTTP(w, req)
}

output:

gc 1 @0.021s 2%: 0+4.7+0 ms clock, 0+0/5.3/2.3+0 ms cpu, 3->3->1 MB, 4 MB goal, 8 MB stacks, 0 MB globals, 8 P
gc 2 @0.689s 3%: 0+209+0 ms clock, 0+0/218/21+0 ms cpu, 11->11->6 MB, 12 MB goal, 465 MB stacks, 0 MB globals, 8 P
runtime: goroutine stack exceeds 1000000000-byte limit
runtime: sp=0xc0203c1418 stack=[0xc0203c0000, 0xc0403c0000]
fatal error: stack overflow

runtime stack:
runtime.throw({0x1384d2a?, 0x17d69ff7f0?})
	C:/Program Files/Go/src/runtime/panic.go:1023 +0x65 fp=0x17d69ff7b0 sp=0x17d69ff780 pc=0xfdc025
runtime.newstack()
	C:/Program Files/Go/src/runtime/stack.go:1103 +0x5cc fp=0x17d69ff960 sp=0x17d69ff7b0 pc=0xff5e2c
runtime.morestack()
	C:/Program Files/Go/src/runtime/asm_amd64.s:616 +0x79 fp=0x17d69ff968 sp=0x17d69ff960 pc=0x10131b9

goroutine 1 gp=0xc00004e000 m=3 mp=0xc00005b008 [running]:
github.com/gin-gonic/gin/binding.setByForm({0x131d7e0?, 0xc000e7bb08?, 0x199?}, {{0x12cf007, 0x1}, {0x0, 0x0}, {0x142f9c0, 0x12ec700}, {0x0, ...}, ...}, ...)
	D:/var/GOPATH/pkg/mod/github.com/gin-gonic/[email protected]/binding/form_mapping.go:167 +0x47b fp=0xc0203c1428 sp=0xc0203c1420 pc=0x12b4cbb
github.com/gin-gonic/gin/binding.formSource.TrySet(0x0?, {0x131d7e0?, 0xc000e7bb08?, 0x0?}, {{0x12cf007, 0x1}, {0x0, 0x0}, {0x142f9c0, 0x12ec700}, ...}, ...)
	D:/var/GOPATH/pkg/mod/github.com/gin-gonic/[email protected]/binding/form_mapping.go:73 +0x87 fp=0xc0203c14e8 sp=0xc0203c1428 pc=0x12b3e27
github.com/gin-gonic/gin/binding.tryToSetValue({0x131d7e0?, 0xc000e7bb08?, 0x0?}, {{0x12cf007, 0x1}, {0x0, 0x0}, {0x142f9c0, 0x12ec700}, {0x0, ...}, ...}, ...)
	D:/var/GOPATH/pkg/mod/github.com/gin-gonic/[email protected]/binding/form_mapping.go:164 +0x265 fp=0xc0203c15f8 sp=0xc0203c14e8 pc=0x12b47c5
github.com/gin-gonic/gin/binding.mapping({0x131d7e0?, 0xc000e7bb08?, 0x103b14f?}, {{0x12cf007, 0x1}, {0x0, 0x0}, {0x142f9c0, 0x12ec700}, {0x0, ...}, ...}, ...)
	D:/var/GOPATH/pkg/mod/github.com/gin-gonic/[email protected]/binding/form_mapping.go:106 +0x148 fp=0xc0203c1768 sp=0xc0203c15f8 pc=0x12b4168
github.com/gin-gonic/gin/binding.mapping({0x12ec700?, 0xc000e7bb00?, 0x0?}, {{0x12cf007, 0x1}, {0x0, 0x0}, {0x142f9c0, 0x12ec700}, {0x0, ...}, ...}, ...)
	D:/var/GOPATH/pkg/mod/github.com/gin-gonic/[email protected]/binding/form_mapping.go:95 +0x2e5 fp=0xc0203c18d8 sp=0xc0203c1768 pc=0x12b4305
github.com/gin-gonic/gin/binding.mapping({0x131d860?, 0xc000e7bb00?, 0x103b14f?}, {{0x12cf004, 0x1}, {0x0, 0x0}, {0x142f9c0, 0x12ec6c0}, {0x0, ...}, ...}, ...)
	D:/var/GOPATH/pkg/mod/github.com/gin-gonic/[email protected]/binding/form_mapping.go:124 +0x498 fp=0xc0203c1a48 sp=0xc0203c18d8 pc=0x12b44b8
github.com/gin-gonic/gin/binding.mapping({0x12ec6c0?, 0xc000e7baf8?, 0x0?}, {{0x12cf004, 0x1}, {0x0, 0x0}, {0x142f9c0, 0x12ec6c0}, {0x0, ...}, ...}, ...)
	D:/var/GOPATH/pkg/mod/github.com/gin-gonic/[email protected]/binding/form_mapping.go:95 +0x2e5 fp=0xc0203c1bb8 sp=0xc0203c1a48 pc=0x12b4305
github.com/gin-gonic/gin/binding.mapping({0x131d7e0?, 0xc000e7baf8?, 0x103b14f?}, {{0x12cf007, 0x1}, {0x0, 0x0}, {0x142f9c0, 0x12ec700}, {0x0, ...}, ...}, ...)
	D:/var/GOPATH/pkg/mod/github.com/gin-gonic/[email protected]/binding/form_mapping.go:124 +0x498 fp=0xc0203c1d28 sp=0xc0203c1bb8 pc=0x12b44b8
github.com/gin-gonic/gin/binding.mapping({0x12ec700?, 0xc000e7baf0?, 0x0?}, {{0x12cf007, 0x1}, {0x0, 0x0}, {0x142f9c0, 0x12ec700}, {0x0, ...}, ...}, ...)
	D:/var/GOPATH/pkg/mod/github.com/gin-gonic/[email protected]/binding/form_mapping.go:95 +0x2e5 fp=0xc0203c1e98 sp=0xc0203c1d28 pc=0x12b4305
github.com/gin-gonic/gin/binding.mapping({0x131d860?, 0xc000e7baf0?, 0x103b14f?}, {{0x12cf004, 0x1}, {0x0, 0x0}, {0x142f9c0, 0x12ec6c0}, {0x0, ...}, ...}, ...)
	D:/var/GOPATH/pkg/mod/github.com/gin-gonic/[email protected]/binding/form_mapping.go:124 +0x498 fp=0xc0203c2008 sp=0xc0203c1e98 pc=0x12b44b8

...

Expectations

Don't fatal exit, limit recursion deep number.

Environment

  • go version: 1.22.1
  • gin version (or commit ref): v1.9.1
  • operating system: Windows/Linux

flyhope avatar Apr 28 '24 12:04 flyhope

You should not have structs with circular dependencies. You don't conform to the Single Responsibility Principle.

RedCrazyGhost avatar May 01 '24 16:05 RedCrazyGhost