#4818·gin

Panic: slice bounds out of range in getValue with HandleMethodNotAllowed enabled

Author: rashmi-tondareCreated Aug 27, 2026Updated Aug 27, 2026
Labelstype/bug

Description

With HandleMethodNotAllowed = true, gin can panic during route matching:

runtime error: slice bounds out of range [:x+1] with capacity x

c.skippedNodes is allocated once per pooled Context with capacity engine.maxSections (gin.go:254). getValue pushes onto it with a raw reslice i.e. (*skippedNodes)[:index+1] (tree.go:435), so it cannot grow. Context.reset() clears it once per request (context.go:117), but handleHTTPRequest calls getValue once per method tree in the HandleMethodNotAllowed loop (gin.go:746) reusing the same stack, and getValue neither resets it on entry nor drains it before returning. Residue accumulates per tree until the reslice exceeds capacity:

getValue call #1: len=0 cap=6   push -> 1, push -> 2
getValue call #2: len=2 cap=6   <-- residue
getValue call #3: len=4 cap=6   <-- residue
getValue call #4: len=6 cap=6   push -> 7  => panic

Because the panic happens during route matching, before the handler chain, gin.Recovery() cannot catch it, net/http recovers per connection, logs http: panic serving ..., and closes the connection with no response, so clients see an empty reply/reset rather than a 5xx.

Gin Version

v1.12.0

Can you reproduce the bug?

Yes

Source Code

gin v1.12.0, go 1.26.4

package main                                                                                                                                
                                                                                                                                            
import (                                                                                                                                    
      "net/http"                                                                                                                            
      "net/http/httptest"                                                                                                                   
      "testing"                                                                                                                             
                                                                                                                                            
      "github.com/gin-gonic/gin"                                                                                                            
)                                                                                                                                           
                                                                                                                                            
func TestPanic(t *testing.T) {                                                                                                              
      gin.SetMode(gin.ReleaseMode)                                                                                                          
      router := gin.New()                                                                                                                   
      router.HandleMethodNotAllowed = true                                                                                                  
                                                                                                                                            
      h := func(c *gin.Context) {}                                                                                                          
      router.OPTIONS("/:p0/:p1/a/:p2", h)                                                                                                   
      router.GET("/:p0/:p1/a/:p2", h)                                                                                                       
      router.PATCH("/b/:p0/:p1/c", h)                                                                                                       
      router.DELETE("/b/:p0/:p1/d/:p3", h)                                                                                                  
      router.GET("/b/:p0/:p1/e/f", h)                                                                                                       
      router.POST("/b/:p0/:p1/g/:p4/h", h)                                                                                                  
      router.OPTIONS("/b/:p0/:p1/g/:p4/h", h)                                                                                               
      router.DELETE("/b/cache", h)                                                                                                          
      router.GET("/b/clients/:p1/g", h)                                                                                                     
      router.POST("/b/clients/:p1/g", h)                                                                                                    
      router.PATCH("/b/clients/:p1/g/:p4", h)                                                                                               
      router.OPTIONS("/b/clients/:p1/g/:p4", h)
                                                                                                                                            
      req := httptest.NewRequest(http.MethodPost, "/b/clients/42", nil)                                                                     
      router.ServeHTTP(httptest.NewRecorder(), req)                                                                                         
}                                                                                                                                           

Expectations

405 Method Not Allowed.

Actual result

panic: runtime error: slice bounds out of range [:7] with capacity 6                                                                        
github.com/gin-gonic/gin.(*node).getValue(...)                                                                                              
      [email protected]/tree.go:435                                                                                                               
github.com/gin-gonic/gin.(*Engine).handleHTTPRequest(...)                                                                                   
      [email protected]/gin.go:746                                                                                                                
github.com/gin-gonic/gin.(*Engine).ServeHTTP(...)                                                                                           
      [email protected]/gin.go:672                                                                                                                

Go Version

go 1.26.4

Operating System

No response