Skip to content

Do not panic when routeRegexp.regexp is nil - #816

Closed
clydeeshun94 wants to merge 3 commits into
gorilla:mainfrom
clydeeshun94:fix/nil-route-regexp-match
Closed

clydeeshun94 wants to merge 3 commits into
gorilla:mainfrom
clydeeshun94:fix/nil-route-regexp-match

Conversation

@clydeeshun94

Copy link
Copy Markdown

Fixes #749
routeRegexp.Match called regexp.MatchString without checking the compiled pointer. Treat a nil routeRegexp or a nil compiled regexp as no match instead of panicking.

routeRegexp.Match called regexp.MatchString without checking the
compiled pointer. Treat a nil routeRegexp or a nil compiled regexp
as no match instead of panicking.

Fixes gorilla#749
@thaJeztah

Copy link
Copy Markdown

Comment thread regexp_test.go

func Test_routeRegexp_NilRegexp(t *testing.T) {
req := newRequest("GET", "/")
r := &routeRegexp{regexpType: regexpTypePath}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question as I left on the other PR;

This is manually constructing the routeRegexp, which is a type that's non-exported and has a constructor;

mux/regexp.go

Lines 31 to 41 in db9d1d0

// newRouteRegexp parses a route template and returns a routeRegexp,
// used to match a host, a path or a query string.
//
// It will extract named variables, assemble a regexp to be matched, create
// a "reverse" template to build URLs and compile regexps to validate variable
// values used in URL building.
//
// Previously we accepted only Python-like identifiers for variable
// names ([a-zA-Z_][a-zA-Z0-9_]*), but currently the only restriction is that
// name and pattern can't be empty, and names can't contain a colon.
func newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*routeRegexp, error) {

I'm not sure if fixing this by adding guards is the right thing to do; the related ticket indicates that either something is broken elsewhere, or that the code is used incorrectly, leading to the panic (which may actually be the correct thing to do for such cases);

routeRegexp.Match called regexp.MatchString without checking the
compiled pointer. Treat a nil routeRegexp or a nil compiled regexp
as no match instead of panicking.

Fixes gorilla#749

Comment added explaining rationale: a no-match response is preferable
to crashing the server on an unexpected nil state, as this panic has
been observed in production.
Instead of only guarding in Match (defense-in-depth), this commit
adds a check in newRouteRegexp that returns an error when
RegexpCompileFunc returns nil without error. This prevents a nil
regexp from ever being created through normal construction paths.

The Match guard is kept as defense-in-depth for edge cases like
copyRouteRegexp or RegexpCompileFunc returning nil without error.
@pull-request-size pull-request-size Bot added size/M and removed size/S labels Sep 18, 2026
@clydeeshun94

Copy link
Copy Markdown
Author

Closing this as it overlaps with #810 (same fix by different author). Will look for a new contribution to this repo or another repo in the future. Thanks for the review @thaJeztah.

Rameen07304 added a commit to Rameen07304/repo-pilot that referenced this pull request Sep 27, 2026
Paste a pull request URL, get the architecture delta between its two
ends. Almost everything it needed already existed and was pointed at the
wrong thing — the comparison, the rename resolution, the evidence, the
page. Two pieces were missing:

  * Reading a pull request's two commits from GitHub.
  * Ingesting at a commit. get_repo_tree and get_file_contents already
    took a sha; only the use case assumed HEAD, which is what stopped a
    pull request being read at both of its ends. One parameter.

It compares against the merge base GitHub reports, not the tip of the
base branch. Against the tip, every unrelated commit landed while the
pull request was open gets blamed on it, which is what makes structural
diffs useless on a busy repository.

The URL is parsed, not pattern-matched: that string decides which
repository the server fetches, and a loose match sends the server's
token to github.com.evil.com. Tested against that and four other
lookalikes. A bad URL never reaches GitHub, and the private-repo guard
runs before the pull request metadata is fetched, not just inside ingest.

Verified against gorilla/mux#816 end to end: 34 seconds for two ingests,
and it correctly reports NO structural change — the PR is a nil check
inside a function, no imports touched. That is the useful answer: a
reviewer learns the architecture is untouched without reading the diff.

Two defects found and fixed while testing:

  * A pull request number that does not exist returned 500. It is a 404.
  * The input first went in the diagram tab, where it sat behind "ingest
    a repo first" — for a feature that needs no repo loaded, because it
    ingests both ends itself. It lives beside the repo URL now, folded
    away, since both are "point me at something on GitHub".

Also checked, and found nothing wrong: mobile layout (no horizontal
scroll, nav reflows), all six tabs, console errors on a fresh load, and
that the CSP change really does let the webfont through.

449 Python tests, 66 frontend.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] runtime error in (*routeRegexp).Match

2 participants