fix(parameters): avoid panic on double-slash request paths#275
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #275 +/- ##
=======================================
Coverage 98.08% 98.08%
=======================================
Files 64 64
Lines 6987 6999 +12
=======================================
+ Hits 6853 6865 +12
Misses 133 133
Partials 1 1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| } | ||
|
|
||
| matches := rgx.FindStringSubmatch(submittedSegments[x]) | ||
| if matches == nil { |
There was a problem hiding this comment.
this avoids the panic, but it can silently accept the bad request. For //test/path/fubar against /test/path/{param}, the extra empty segment shifts indexing, so {param} is validated against "path" instead of "fubar", and ValidateHttpRequestWithPathItem returns valid=true, errs=0. This should either normalize segments consistently and validate fubar, or return a validation error; current behavior is neither.
There was a problem hiding this comment.
Here is a suggestion.
submittedSegments := nonEmptyPathSegments(paths.StripRequestPath(request, v.document))
pathSegments := nonEmptyPathSegments(pathValue)
if len(submittedSegments) != len(pathSegments) {
return false, []*errors.ValidationError{
errors.PathParameterMissing(p, pathValue, request.URL.Path),
}
}
for x := range pathSegments {
var rgx *regexp.Regexp
// existing regex cache/build code...
matches := rgx.FindStringSubmatch(submittedSegments[x])
if matches == nil {
continue
}
matches = matches[1:]
// existing match validation code...
}
Helper:
func nonEmptyPathSegments(path string) []string {
raw := strings.Split(path, helpers.Slash)
segments := make([]string, 0, len(raw))
for _, segment := range raw {
if segment == "" {
continue
}
segments = append(segments, segment)
}
return segments
}The key is: don’t keep the original indexes after dropping/skipping empty template segments.
Either compact both sides first, or return a path/missing-param error when the segment counts
differ.
There was a problem hiding this comment.
Fixed in the latest push: the approach now uses to drop empty segments from both sides before aligning them, so correctly validates against . For paths where segment counts still differ after stripping, the validator now returns a error (modeled on your suggestion). Test at line 2383 asserts the exact outcomes.
| pathItem := m.Model.Paths.PathItems.GetOrZero("/test/path/{param}") | ||
| require.NotNil(t, pathItem) | ||
|
|
||
| assert.NotPanics(t, func() { |
There was a problem hiding this comment.
only asserts NotPanics, so it misses the validation bypass above. The regression test should assert the returned valid/errors outcome for the issue request and the missing-segment request.
There was a problem hiding this comment.
Updated the test to assert valid/errors outcomes: double-slash path returns valid=true, errs=0 (segments align after stripping); short path returns valid=false, errs=1.
|
Reworked per your suggestion: both sides now compact empty segments via a nonEmptyPathSegments helper, and a segment-count mismatch returns PathParameterMissing instead of silently passing. The regression test now asserts the request validates fubar (valid, no errors) and that a missing-segment path is rejected. |
Signed-off-by: Sai Asish Y <say.apm35@gmail.com>
|
Added a test covering the nil-match guard: |
Fixes #274.
Request paths containing a leading double slash (e.g.
//test/path/x) makestrings.Splitproduce an extra empty segment, sosubmittedSegmentsends up longer thanpathSegments. The loop then indexessubmittedSegments[x]against a segment the request never actually had, the regex returns nil, andmatches[1:]panics withslice bounds out of range [1:0].The patch skips iterations where
xis out of bounds forsubmittedSegments, and treats a nil regex match as a non-match rather than panicking. Regression test inparameters/path_parameters_test.goexercises the exact panic stack from the issue.