swaggo / swag

Automatically generate RESTful API documentation with Swagger 2.0 for Go.
MIT License
10.66k stars 1.2k forks source link

Crash when generating doc for recursive structure #1016

Open arunpoudel opened 3 years ago

arunpoudel commented 3 years ago

Describe the bug swaggo crashes when generating doc for recursive structure

To Reproduce I have prepared a sample that causes it to crash. Can be found at https://github.com/medsensio/swag-go-crash-demo

Expected behavior swagger documentation should be updated

Screenshots N/A

Exception

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x7dc91f]

goroutine 1 [running]:
github.com/swaggo/swag.(*Parser).getRefTypeSchema(0xc0001e6000, 0xc00011c7a0, 0x0)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:798 +0x7f
github.com/swaggo/swag.(*Parser).getTypeSchema(0xc0001e6000, {0xc0001201f0, 0x9}, 0xc8b3a0, 0x1)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:748 +0x96d
github.com/swaggo/swag.(*Parser).parseTypeExpr(0xc0001e6000, 0x98f600, {0x998c28, 0xc00011c180}, 0xb0)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:907 +0xab
github.com/swaggo/swag.(*Parser).parseTypeExpr(0xc0001e6000, 0xc00011a0f0, {0x998778, 0xc00011a0f0}, 0x1)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:920 +0x3f1
github.com/swaggo/swag.(*Parser).parseStructField(0xc0001bec58, 0xc00011abd0, 0xc00012a180)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:1045 +0x405
github.com/swaggo/swag.(*Parser).parseStruct(0xc00011f2b0, 0xc00002abc0, 0xc00011a120)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:952 +0xf0
github.com/swaggo/swag.(*Parser).parseTypeExpr(0xc0001e6000, 0x8f7133, {0x998f58, 0xc0001180a8}, 0xf0)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:903 +0x3b3
github.com/swaggo/swag.(*Parser).ParseDefinition(0xc0001e6000, 0xc00011c7c0)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:864 +0x2d2
github.com/swaggo/swag.(*Parser).getTypeSchema(0xc0001e6000, {0xc000120216, 0x7}, 0x0, 0x0)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:744 +0x886
github.com/swaggo/swag.(*Parser).parseStructField(0x0, 0xc0001bfb18, 0xc00012a200)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:1010 +0x136
github.com/swaggo/swag.(*Parser).parseStruct(0xc00011f2b0, 0xc00002abc0, 0xc00011a1b0)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:952 +0xf0
github.com/swaggo/swag.(*Parser).parseTypeExpr(0xc0001e6000, 0x8f7133, {0x998f58, 0xc0001180c0}, 0x26)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:903 +0x3b3
github.com/swaggo/swag.(*Parser).ParseDefinition(0xc0001e6000, 0xc00011c7e0)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:864 +0x2d2
github.com/swaggo/swag.(*Parser).getTypeSchema(0xc0001e6000, {0xc000120250, 0xe}, 0xc00011a930, 0x0)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:744 +0x886
github.com/swaggo/swag.(*Parser).parseStructField(0x7f3a148415b8, 0x10, 0xc00012a300)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:1010 +0x136
github.com/swaggo/swag.(*Parser).parseStruct(0xc00011f2b0, 0xc00002abc0, 0xc00011a210)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:952 +0xf0
github.com/swaggo/swag.(*Parser).parseTypeExpr(0xc0001e6000, 0x8f7133, {0x998f58, 0xc0001180d8}, 0x8)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:903 +0x3b3
github.com/swaggo/swag.(*Parser).ParseDefinition(0xc0001e6000, 0xc00011c800)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:864 +0x2d2
github.com/swaggo/swag.(*Parser).getTypeSchema(0xc0001e6000, {0xc000130109, 0x8}, 0x0, 0x1)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:744 +0x886
github.com/swaggo/swag.(*Operation).parseObjectSchema(0xc000150000, {0xc000130109, 0x8}, 0xc0001288d0)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/operation.go:696 +0xfdf
github.com/swaggo/swag.(*Operation).parseAPIObjectSchema(0xc000130100, {0xc000130101, 0x6}, {0xc000130109, 0x8}, 0x203000)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/operation.go:766 +0x250
github.com/swaggo/swag.(*Operation).ParseResponseComment(0xc000150000, {0xc0001300fc, 0x15}, 0x902ce0)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/operation.go:796 +0x13c
github.com/swaggo/swag.(*Operation).ParseComment(0xc000150000, {0xc0001300f0, 0x1}, 0x1c)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/operation.go:119 +0x405
github.com/swaggo/swag.(*Parser).ParseRouterAPIInfo(0xc0001e6000, {0xc000138040, 0x35}, 0xc00012c280)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:637 +0x1d6
github.com/swaggo/swag.(*PackagesDefinitions).RangeFiles(0xc00000e8e8, 0xc0001c1940)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/packages.go:84 +0x1ff
github.com/swaggo/swag.(*Parser).ParseAPIMultiSearchDir(0xc0001e6000, {0xc0000fdbd0, 0x1, 0xc00006c100}, {0x8f3652, 0x7}, 0x64)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/parser.go:253 +0x325
github.com/swaggo/swag/gen.(*Gen).Build(0xc0000fdb10, 0xc0001c1c50)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/gen/gen.go:98 +0x270
main.initAction(0xc000190180)
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/cmd/swag/main.go:101 +0x367
github.com/urfave/cli/v2.(*Command).Run(0xc0000b38c0, 0xc0001a23c0)
        /home/fr3ak/go/pkg/mod/github.com/urfave/cli/v2@v2.3.0/command.go:163 +0x64a
github.com/urfave/cli/v2.(*App).RunContext(0xc000192340, {0x99b770, 0xc000024120}, {0xc000020040, 0x2, 0x2})
        /home/fr3ak/go/pkg/mod/github.com/urfave/cli/v2@v2.3.0/app.go:313 +0x81e
github.com/urfave/cli/v2.(*App).Run(...)
        /home/fr3ak/go/pkg/mod/github.com/urfave/cli/v2@v2.3.0/app.go:224
main.main()
        /home/fr3ak/go/pkg/mod/github.com/swaggo/swag@v1.7.3/cmd/swag/main.go:130 +0x205

Your swag version 1.7.3

Your go version go version go1.17.1 linux/amd64

Desktop (please complete the following information):

Additional context I did some digging around and looks like https://github.com/swaggo/swag/blob/master/parser.go#L771 is the culprit.

if err == ErrRecursiveParseStruct && ref {
    return parser.getRefTypeSchema(typeSpecDef, schema), nil
}

Is there a reason why ref has to be set inorder for recursive structure to be parsed as reference? If we remove the ref check, then the document seem to be generated.

ubogdan commented 3 years ago

@arunpoudel, thanks for letting us know. If you have a solution to this issue, please feel free to contribute with a PR, and I will be more than happy to assist you with a code review.

sdghchj commented 3 years ago

Is there a reason why ref has to be set inorder for recursive structure to be parsed as reference? If we remove the ref check, then the document seem to be generated.

For embedded struct, all its field schemas, not a reference, are required to expand.