mirror of
https://github.com/gin-gonic/gin.git
synced 2025-12-03 13:39:34 +08:00
ci(sec): improve type safety and server organization in HTTP middleware (#4437)
- Update linting configuration to exclude G115 gosec check instead of including specific checks - Add the safeInt8 helper for safer type conversions and use it to prevent int8 overflow in middleware handler execution - Group related constants and variables together for better organization in gin.go - Refactor HTTP server instantiation to use a dedicated http.Server object for all Run methods - Add the safeUint16 helper and use it to safely handle conversions in tree node functions to prevent uint16 overflow Signed-off-by: appleboy <appleboy.tw@gmail.com>
This commit is contained in:
parent
58135f06cf
commit
93ff771e6d
@ -18,15 +18,8 @@ linters:
|
|||||||
- wastedassign
|
- wastedassign
|
||||||
settings:
|
settings:
|
||||||
gosec:
|
gosec:
|
||||||
includes:
|
excludes:
|
||||||
- G102
|
- G115
|
||||||
- G106
|
|
||||||
- G108
|
|
||||||
- G109
|
|
||||||
- G111
|
|
||||||
- G112
|
|
||||||
- G201
|
|
||||||
- G203
|
|
||||||
perfsprint:
|
perfsprint:
|
||||||
int-conversion: true
|
int-conversion: true
|
||||||
err-error: true
|
err-error: true
|
||||||
|
|||||||
10
context.go
10
context.go
@ -55,6 +55,14 @@ const ContextRequestKey ContextKeyType = 0
|
|||||||
// abortIndex represents a typical value used in abort functions.
|
// abortIndex represents a typical value used in abort functions.
|
||||||
const abortIndex int8 = math.MaxInt8 >> 1
|
const abortIndex int8 = math.MaxInt8 >> 1
|
||||||
|
|
||||||
|
// safeInt8 converts int to int8 safely, capping at math.MaxInt8
|
||||||
|
func safeInt8(n int) int8 {
|
||||||
|
if n > math.MaxInt8 {
|
||||||
|
return math.MaxInt8
|
||||||
|
}
|
||||||
|
return int8(n)
|
||||||
|
}
|
||||||
|
|
||||||
// Context is the most important part of gin. It allows us to pass variables between middleware,
|
// Context is the most important part of gin. It allows us to pass variables between middleware,
|
||||||
// manage the flow, validate the JSON of a request and render a JSON response for example.
|
// manage the flow, validate the JSON of a request and render a JSON response for example.
|
||||||
type Context struct {
|
type Context struct {
|
||||||
@ -186,7 +194,7 @@ func (c *Context) FullPath() string {
|
|||||||
// See example in GitHub.
|
// See example in GitHub.
|
||||||
func (c *Context) Next() {
|
func (c *Context) Next() {
|
||||||
c.index++
|
c.index++
|
||||||
for c.index < int8(len(c.handlers)) {
|
for c.index < safeInt8(len(c.handlers)) {
|
||||||
if c.handlers[c.index] != nil {
|
if c.handlers[c.index] != nil {
|
||||||
c.handlers[c.index](c)
|
c.handlers[c.index](c)
|
||||||
}
|
}
|
||||||
|
|||||||
38
gin.go
38
gin.go
@ -23,10 +23,12 @@ import (
|
|||||||
"golang.org/x/net/http2/h2c"
|
"golang.org/x/net/http2/h2c"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultMultipartMemory = 32 << 20 // 32 MB
|
const (
|
||||||
const escapedColon = "\\:"
|
defaultMultipartMemory = 32 << 20 // 32 MB
|
||||||
const colon = ":"
|
escapedColon = "\\:"
|
||||||
const backslash = "\\"
|
colon = ":"
|
||||||
|
backslash = "\\"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
default404Body = []byte("404 page not found")
|
default404Body = []byte("404 page not found")
|
||||||
@ -46,8 +48,10 @@ var defaultTrustedCIDRs = []*net.IPNet{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var regSafePrefix = regexp.MustCompile("[^a-zA-Z0-9/-]+")
|
var (
|
||||||
var regRemoveRepeatedChar = regexp.MustCompile("/{2,}")
|
regSafePrefix = regexp.MustCompile("[^a-zA-Z0-9/-]+")
|
||||||
|
regRemoveRepeatedChar = regexp.MustCompile("/{2,}")
|
||||||
|
)
|
||||||
|
|
||||||
// HandlerFunc defines the handler used by gin middleware as return value.
|
// HandlerFunc defines the handler used by gin middleware as return value.
|
||||||
type HandlerFunc func(*Context)
|
type HandlerFunc func(*Context)
|
||||||
@ -537,7 +541,11 @@ func (engine *Engine) Run(addr ...string) (err error) {
|
|||||||
engine.updateRouteTrees()
|
engine.updateRouteTrees()
|
||||||
address := resolveAddress(addr)
|
address := resolveAddress(addr)
|
||||||
debugPrint("Listening and serving HTTP on %s\n", address)
|
debugPrint("Listening and serving HTTP on %s\n", address)
|
||||||
err = http.ListenAndServe(address, engine.Handler())
|
server := &http.Server{ // #nosec G112
|
||||||
|
Addr: address,
|
||||||
|
Handler: engine.Handler(),
|
||||||
|
}
|
||||||
|
err = server.ListenAndServe()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,7 +561,11 @@ func (engine *Engine) RunTLS(addr, certFile, keyFile string) (err error) {
|
|||||||
"Please check https://github.com/gin-gonic/gin/blob/master/docs/doc.md#dont-trust-all-proxies for details.")
|
"Please check https://github.com/gin-gonic/gin/blob/master/docs/doc.md#dont-trust-all-proxies for details.")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = http.ListenAndServeTLS(addr, certFile, keyFile, engine.Handler())
|
server := &http.Server{ // #nosec G112
|
||||||
|
Addr: addr,
|
||||||
|
Handler: engine.Handler(),
|
||||||
|
}
|
||||||
|
err = server.ListenAndServeTLS(certFile, keyFile)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -576,7 +588,10 @@ func (engine *Engine) RunUnix(file string) (err error) {
|
|||||||
defer listener.Close()
|
defer listener.Close()
|
||||||
defer os.Remove(file)
|
defer os.Remove(file)
|
||||||
|
|
||||||
err = http.Serve(listener, engine.Handler())
|
server := &http.Server{ // #nosec G112
|
||||||
|
Handler: engine.Handler(),
|
||||||
|
}
|
||||||
|
err = server.Serve(listener)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -630,7 +645,10 @@ func (engine *Engine) RunListener(listener net.Listener) (err error) {
|
|||||||
"Please check https://github.com/gin-gonic/gin/blob/master/docs/doc.md#dont-trust-all-proxies for details.")
|
"Please check https://github.com/gin-gonic/gin/blob/master/docs/doc.md#dont-trust-all-proxies for details.")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = http.Serve(listener, engine.Handler())
|
server := &http.Server{ // #nosec G112
|
||||||
|
Handler: engine.Handler(),
|
||||||
|
}
|
||||||
|
err = server.Serve(listener)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
tree.go
13
tree.go
@ -5,6 +5,7 @@
|
|||||||
package gin
|
package gin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
@ -77,14 +78,22 @@ func (n *node) addChild(child *node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// safeUint16 converts int to uint16 safely, capping at math.MaxUint16
|
||||||
|
func safeUint16(n int) uint16 {
|
||||||
|
if n > math.MaxUint16 {
|
||||||
|
return math.MaxUint16
|
||||||
|
}
|
||||||
|
return uint16(n)
|
||||||
|
}
|
||||||
|
|
||||||
func countParams(path string) uint16 {
|
func countParams(path string) uint16 {
|
||||||
colons := strings.Count(path, ":")
|
colons := strings.Count(path, ":")
|
||||||
stars := strings.Count(path, "*")
|
stars := strings.Count(path, "*")
|
||||||
return uint16(colons + stars)
|
return safeUint16(colons + stars)
|
||||||
}
|
}
|
||||||
|
|
||||||
func countSections(path string) uint16 {
|
func countSections(path string) uint16 {
|
||||||
return uint16(strings.Count(path, "/"))
|
return safeUint16(strings.Count(path, "/"))
|
||||||
}
|
}
|
||||||
|
|
||||||
type nodeType uint8
|
type nodeType uint8
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user