-
Notifications
You must be signed in to change notification settings - Fork 8.5k
avoid double unescaping #4447
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
base: master
Are you sure you want to change the base?
avoid double unescaping #4447
Changes from 2 commits
e2184ff
67c0ef7
cf959d7
d26a652
a61c9c6
9b3d7f6
a9b0085
1c407a2
f8b6b4a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,7 +5,7 @@ | |||||||||||||
| package gin | ||||||||||||||
|
|
||||||||||||||
| import ( | ||||||||||||||
| "math" | ||||||||||||||
| "bytes" | ||||||||||||||
| "net/url" | ||||||||||||||
| "strings" | ||||||||||||||
| "unicode" | ||||||||||||||
|
|
@@ -14,6 +14,12 @@ import ( | |||||||||||||
| "github.com/gin-gonic/gin/internal/bytesconv" | ||||||||||||||
| ) | ||||||||||||||
|
|
||||||||||||||
| var ( | ||||||||||||||
| strColon = []byte(":") | ||||||||||||||
| strStar = []byte("*") | ||||||||||||||
| strSlash = []byte("/") | ||||||||||||||
| ) | ||||||||||||||
|
|
||||||||||||||
| // Param is a single URL parameter, consisting of a key and a value. | ||||||||||||||
| type Param struct { | ||||||||||||||
| Key string | ||||||||||||||
|
|
@@ -78,22 +84,17 @@ 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 { | ||||||||||||||
| colons := strings.Count(path, ":") | ||||||||||||||
| stars := strings.Count(path, "*") | ||||||||||||||
| return safeUint16(colons + stars) | ||||||||||||||
| var n uint16 | ||||||||||||||
| s := bytesconv.StringToBytes(path) | ||||||||||||||
| n += uint16(bytes.Count(s, strColon)) | ||||||||||||||
| n += uint16(bytes.Count(s, strStar)) | ||||||||||||||
| return n | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| func countSections(path string) uint16 { | ||||||||||||||
| return safeUint16(strings.Count(path, "/")) | ||||||||||||||
| s := bytesconv.StringToBytes(path) | ||||||||||||||
| return uint16(bytes.Count(s, strSlash)) | ||||||||||||||
|
||||||||||||||
| return uint16(bytes.Count(s, strSlash)) | |
| count := bytes.Count(s, strSlash) | |
| if count > 0xFFFF { | |
| count = 0xFFFF | |
| } | |
| return uint16(count) |
Outdated
Copilot
AI
Nov 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same unescape logic is duplicated in two places (param and catchAll cases). Consider extracting this into a helper function to reduce code duplication and make maintenance easier.
Suggested refactoring:
func unescapeValue(val string, unescape bool) string {
if unescape && strings.ContainsAny(val, "%+") {
if v, err := url.QueryUnescape(val); err == nil {
return v
}
}
return val
}Then use it in both locations:
val := unescapeValue(path[:end], unescape)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The removal of
safeUint16safety check could cause overflow issues. The old implementation capped values atmath.MaxUint16(65535), but the new code directly casts touint16without bounds checking.If
bytes.Count()returns a value greater than 65535, the castuint16(bytes.Count(...))will silently overflow. While unlikely for typical path strings, extremely long paths with many colons or slashes could potentially cause this.Consider either:
safeUint16helper function, orcountParamsandcountSectionsExample problematic case: