Repository: labstack/echo (go)

Issue:
looping/panic router.go#Find when set param to context
### Issue Description

looping/panic router.go#Find when set param to context

### Checklist

- [x] Dependencies installed
- [x] No typos
- [x] Searched existing issues and docs

### Expected behaviour
get actual data by request

### Actual behaviour

```
echo: http: panic serving [::1]:54155: runtime error: index out of range [1] with length 1
goroutine 18 [running]:
net/http.(*conn).serve.func1(0xc000096000)
	/usr/local/Cellar/go/1.15.2/libexec/src/net/http/server.go:1801 +0x147
panic(0x1344100, 0xc0000a0020)
	/usr/local/Cellar/go/1.15.2/libexec/src/runtime/panic.go:975 +0x3e9
github.com/labstack/echo/v4.(*Router).Find(0xc00000e940, 0xc0000a0000, 0x3, 0xc0000a0004, 0x12, 0x13d1e60, 0xc0000960a0)
	/Users/andrey/go/pkg/mod/github.com/labstack/echo/v4@v4.1.17/router.go:415 +0x11d2
github.com/labstack/echo/v4.(*Echo).ServeHTTP(0xc00000c1e0, 0x13ce1e0, 0xc0000aa000, 0xc00009e000)
	/Users/andrey/go/pkg/mod/github.com/labstack/echo/v4@v4.1.17/echo.go:619 +0x12b
net/http.serverHandler.ServeHTTP(0xc000178000, 0x13ce1e0, 0xc0000aa000, 0xc00009e000)
	/usr/local/Cellar/go/1.15.2/libexec/src/net/http/server.go:2843 +0xa3
net/http.(*conn).serve(0xc000096000, 0x13ce9a0, 0xc00009a000)
	/usr/local/Cellar/go/1.15.2/libexec/src/net/http/server.go:1925 +0x8ad
created by net/http.(*Server).Serve
	/usr/local/Cellar/go/1.15.2/libexec/src/net/http/server.go:2969 +0x36c
```

### Steps to reproduce
`curl -X GET -H "Content-Type: application/json" localhost:8811/v1/admin`
panic - `curl -X GET -H "Content-Type: application/json" localhost:8811/v1/view/same-data`
looping - `curl -X GET -H "Content-Type: application/json" localhost:8811/v1/images/view`

### Working code to debug

```go
package main

import (
	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
)

func main() {
	s := echo.New()
	s.Use(middleware.Logger())

	v0 := s.Group("/:version")
	v0.GET("/admin", func(c echo.Context) error {
		c.SetParamNames("version")
		c.SetParamValues("v1")
		return nil
	})

	v0.GET("/images/view/:id", handler)
	v0.GET("/images/:id", handler)
	v0.GET("/view/*", func(c echo.Context) error {
		return c.JSON(200, c.Param("*"))
	})

	s.Start(":8811")
}

func handler(c echo.Context) error {
	return c.JSON(200, c.Param("id"))
}
```

### Version/commit
v4.1.17

Pull request:
Fixed Router#Find panic an infinite loop
Before this fix, Router#Find panics or enters in an infinite loop when the context params values were set to a number less than the max number of params supported by the Router.
This fix #1655 

Patch:
diff --git a/context.go b/context.go
index 8ba9847..380a52e 100644
--- a/context.go
+++ b/context.go
@@ -314,7 +314,19 @@ func (c *context) ParamNames() []string {
 
 func (c *context) SetParamNames(names ...string) {
 	c.pnames = names
-	*c.echo.maxParam = len(names)
+
+	l := len(names)
+	if *c.echo.maxParam < l {
+		*c.echo.maxParam = l
+	}
+
+	if len(c.pvalues) < l {
+		// Keeping the old pvalues just for backward compatibility, but it sounds that doesn't make sense to keep them,
+		// probably those values will be overriden in a Context#SetParamValues
+		newPvalues := make([]string, l)
+		copy(newPvalues, c.pvalues)
+		c.pvalues = newPvalues
+	}
 }
 
 func (c *context) ParamValues() []string {
@@ -322,7 +334,15 @@ func (c *context) ParamValues() []string {
 }
 
 func (c *context) SetParamValues(values ...string) {
-	c.pvalues = values
+	// NOTE: Don't just set c.pvalues = values, because it has to have length c.echo.maxParam at all times
+	// It will brake the Router#Find code
+	limit := len(values)
+	if limit > *c.echo.maxParam {
+		limit = *c.echo.maxParam
+	}
+	for i := 0; i < limit; i++ {
+		c.pvalues[i] = values[i]
+	}
 }
 
 func (c *context) QueryParam(name string) string {


Test patch:
diff --git a/context_test.go b/context_test.go
index 0044bf8..417d4a7 100644
--- a/context_test.go
+++ b/context_test.go
@@ -517,6 +517,40 @@ func TestContextGetAndSetParam(t *testing.T) {
 	})
 }
 
+// Issue #1655
+func TestContextSetParamNamesShouldUpdateEchoMaxParam(t *testing.T) {
+	assert := testify.New(t)
+
+	e := New()
+	assert.Equal(0, *e.maxParam)
+
+	expectedOneParam := []string{"one"}
+	expectedTwoParams := []string{"one", "two"}
+	expectedThreeParams := []string{"one", "two", ""}
+	expectedABCParams := []string{"A", "B", "C"}
+
+	c := e.NewContext(nil, nil)
+	c.SetParamNames("1", "2")
+	c.SetParamValues(expectedTwoParams...)
+	assert.Equal(2, *e.maxParam)
+	assert.EqualValues(expectedTwoParams, c.ParamValues())
+
+	c.SetParamNames("1")
+	assert.Equal(2, *e.maxParam)
+	// Here for backward compatibility the ParamValues remains as they are
+	assert.EqualValues(expectedOneParam, c.ParamValues())
+
+	c.SetParamNames("1", "2", "3")
+	assert.Equal(3, *e.maxParam)
+	// Here for backward compatibility the ParamValues remains as they are, but the len is extended to e.maxParam
+	assert.EqualValues(expectedThreeParams, c.ParamValues())
+
+	c.SetParamValues("A", "B", "C", "D")
+	assert.Equal(3, *e.maxParam)
+	// Here D shouldn't be returned
+	assert.EqualValues(expectedABCParams, c.ParamValues())
+}
+
 func TestContextFormValue(t *testing.T) {
 	f := make(url.Values)
 	f.Set("name", "Jon Snow")
diff --git a/router_test.go b/router_test.go
index fca3a79..947e0da 100644
--- a/router_test.go
+++ b/router_test.go
@@ -1298,6 +1298,43 @@ func TestRouterParam1466(t *testing.T) {
 	assert.Equal(t, 0, c.response.Status)
 }
 
+// Issue #1655
+func TestRouterFindNotPanicOrLoopsWhenContextSetParamValuesIsCalledWithLessValuesThanEchoMaxParam(t *testing.T) {
+	e := New()
+	r := e.router
+
+	v0 := e.Group("/:version")
+	v0.GET("/admin", func(c Context) error {
+		c.SetParamNames("version")
+		c.SetParamValues("v1")
+		return nil
+	})
+
+	v0.GET("/images/view/:id", handlerHelper("iv", 1))
+	v0.GET("/images/:id", handlerHelper("i", 1))
+	v0.GET("/view/*", handlerHelper("v", 1))
+
+	//If this API is called before the next two one panic the other loops ( of course without my fix ;) )
+	c := e.NewContext(nil, nil)
+	r.Find(http.MethodGet, "/v1/admin", c)
+	c.Handler()(c)
+	assert.Equal(t, "v1", c.Param("version"))
+
+	//panic
+	c = e.NewContext(nil, nil)
+	r.Find(http.MethodGet, "/v1/view/same-data", c)
+	c.Handler()(c)
+	assert.Equal(t, "same-data", c.Param("*"))
+	assert.Equal(t, 1, c.Get("v"))
+
+	//looping
+	c = e.NewContext(nil, nil)
+	r.Find(http.MethodGet, "/v1/images/view", c)
+	c.Handler()(c)
+	assert.Equal(t, "view", c.Param("id"))
+	assert.Equal(t, 1, c.Get("i"))
+}
+
 // Issue #1653
 func TestRouterPanicWhenParamNoRootOnlyChildsFailsFind(t *testing.T) {
 	e := New()