Skip to content
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

panic with HandleMethodNotAllowed and route corner case #3459

Closed
kristiansvalland opened this issue Jan 3, 2023 · 0 comments · Fixed by #3460
Closed

panic with HandleMethodNotAllowed and route corner case #3459

kristiansvalland opened this issue Jan 3, 2023 · 0 comments · Fixed by #3460

Comments

@kristiansvalland
Copy link
Contributor

kristiansvalland commented Jan 3, 2023

Description

Setting HandleMethodNotAllowed on the engine and configuring the routes in a intricate way, gin panics when a certain request is sent. See details below on how to reproduce.

How to reproduce

package main

import (
	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()
	r.HandleMethodNotAllowed = true

	r.GET("/base/metrics", handler)
	r.GET("/base/v1/:id/devices", handler)
	r.GET("/base/v1/user/:id/groups", handler)
	r.GET("/base/v1/organizations/:id", handler)
	r.DELETE("/base/v1/organizations/:id", handler)
	r.Run() 
}

Now, make a GET on "localhost:8080/base/v1/user/groups", in which case gin panics.

I must admit that the above setup is a bit off, with how ".../:id/devices" and ".../user/:id/groups" is overlapping somewhat, but I still do not expect a panic. If the setup of the routes truly is wrong, then I would expect a panic to happen earlier, either at r.GET() or r.Run().

I've also tried to delete some of the routes to minimize the example, but it seems that all lines are needed for this to fail, which further emphasize that this is a corner case.

Expectations

$ curl http://localhost:8080/base/v1/user/groups
404 page not found

Actual result

$ curl -i http://localhost:8080/base/v1/user/groups
curl: (52) Empty reply from server

With the following log message from the gin app:

2023/01/03 10:16:50 http: panic serving 127.0.0.1:56181: runtime error: index out of range [0] with length 0
goroutine 34 [running]:
net/http.(*conn).serve.func1()
        /usr/local/go/src/net/http/server.go:1850 +0xb0
panic({0x1053aefe0, 0x140000260f0})
        /usr/local/go/src/runtime/panic.go:890 +0x258
github.com/gin-gonic/gin.(*node).getValue(0x1400012d938?, {0x14000520244?, 0x1400012d9d8?}, 0x0, 0x1400000e030, 0x0)
        /Users/kristiansvalland/go/pkg/mod/github.com/gin-gonic/gin@v1.8.2/tree.go:637 +0x378
github.com/gin-gonic/gin.(*Engine).handleHTTPRequest(0x1400054c4e0, 0x140000ae000)
        /Users/kristiansvalland/go/pkg/mod/github.com/gin-gonic/gin@v1.8.2/gin.go:637 +0x474
github.com/gin-gonic/gin.(*Engine).ServeHTTP(0x1400054c4e0, {0x1053d9df8?, 0x140000a8000}, 0x14000512100)
        /Users/kristiansvalland/go/pkg/mod/github.com/gin-gonic/gin@v1.8.2/gin.go:572 +0x1d4
net/http.serverHandler.ServeHTTP({0x14000502e70?}, {0x1053d9df8, 0x140000a8000}, 0x14000512100)
        /usr/local/go/src/net/http/server.go:2947 +0x2c4
net/http.(*conn).serve(0x1400051ab40, {0x1053da5e0, 0x14000502d80})
        /usr/local/go/src/net/http/server.go:1991 +0x560
created by net/http.(*Server).Serve
        /usr/local/go/src/net/http/server.go:3102 +0x444

Environment

  • go version: go1.19.4
  • gin version (or commit ref): v1.8.2 and master
  • operating system: MacOS

Suggested fix

As hinted by in the backtrace, the panic occurs in tree.go#L637, specifically here (with commentary and suggested fix commented):

if !value.tsr && path != "/" {
	for l := len(*skippedNodes); l > 0; {
		skippedNode := (*skippedNodes)[l-1] // <-- Panic occurs here in the second round of the for loop
		*skippedNodes = (*skippedNodes)[:l-1]
		l-- // suggested fix
		if strings.HasSuffix(skippedNode.path, path) {
			path = skippedNode.path
			n = skippedNode.node
			if value.params != nil {
				*value.params = (*value.params)[:skippedNode.paramsCount]
			}
			globalParamsCount = skippedNode.paramsCount
			continue walk
		}
	}
}

Note: The above logic happens three places in tree.go, so they should probably also be fixed at the same time.

Capacity for working on this

I have already created a test and fix for this issue, which I will create a PR for promptly.

kristiansvalland added a commit to kristiansvalland/gin that referenced this issue Jan 3, 2023
…te fix.

gin-gonic#3459

Signed-off-by: Kristian Svalland <kristian.svalland@gmail.com>
kristiansvalland added a commit to kristiansvalland/gin that referenced this issue Jan 3, 2023
Also add test to validate fix.

fixes gin-gonic#3459

Signed-off-by: Kristian Svalland <kristian.svalland@gmail.com>
kristiansvalland added a commit to kristiansvalland/gin that referenced this issue Jan 4, 2023
Also add test to validate fix.

fixes gin-gonic#3459

Signed-off-by: Kristian Svalland <kristian.svalland@gmail.com>
kristiansvalland added a commit to kristiansvalland/gin that referenced this issue Jan 4, 2023
Also add test to validate fix.

fixes gin-gonic#3459

Signed-off-by: Kristian Svalland <kristian.svalland@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant