Repository: labstack/echo
File: bind.go (Go)

Code before:
		typeField := typ.Field(i)
		structField := val.Field(i)
		if !structField.CanSet() {
			continue
		}
		structFieldKind := structField.Kind()
		inputFieldName := typeField.Tag.Get(tag)

		if inputFieldName == "" {
			inputFieldName = typeField.Name
			// If tag is nil, we inspect if the field is a struct.
			if _, ok := bindUnmarshaler(structField); !ok && structFieldKind == reflect.Struct {
				err := b.bindData(structField.Addr().Interface(), data, tag)
				if err != nil {
					return err
				}
				continue
			}
		}

		var inputValue []string
		var exists bool

		// Go json.Unmarshal supports case insensitive binding.  However the url
		// params are bound case sensitive which is inconsistent.  To fix this
		// we must check all of the map values in a case-insensitive search.
		inputFieldName = strings.ToLower(inputFieldName)
		for k, v := range data {
			if strings.ToLower(k) == inputFieldName {
				inputValue = v
				exists = true
				break
			}
		}

		if !exists {
			continue
		}

		// Call this first, in case we're dealing with an alias to an array type
		if ok, err := unmarshalField(typeField.Type.Kind(), inputValue[0], structField); ok {
			if err != nil {
				return err
			}
			continue
		}

		numElems := len(inputValue)
		if structFieldKind == reflect.Slice && numElems > 0 {
			sliceOf := structField.Type().Elem().Kind()
			slice := reflect.MakeSlice(structField.Type(), numElems, numElems)

Review comment (security):
The [package docs for `json`](https://golang.org/pkg/encoding/json/) has:

> Unmarshal matches incoming object keys to the keys used by Marshal (either the struct field name or its tag), preferring an exact match but also accepting a case-insensitive match.

So I think that to match the `json.Unmarshal` behaviour, it should be something like:

```go
inputValue, exists := data[inputFieldName]
if !exists {
	inputFieldName = strings.ToLower(inputFieldName)
	for k, v := range data {
		if strings.ToLower(k) == inputFieldName {
			inputValue = v
			exists = true
			break
		}
	}
}
if !exists {
	continue
}
```

Code after:
		typeField := typ.Field(i)
		structField := val.Field(i)
		if !structField.CanSet() {
			continue
		}
		structFieldKind := structField.Kind()
		inputFieldName := typeField.Tag.Get(tag)

		if inputFieldName == "" {
			inputFieldName = typeField.Name
			// If tag is nil, we inspect if the field is a struct.
			if _, ok := bindUnmarshaler(structField); !ok && structFieldKind == reflect.Struct {
				err := b.bindData(structField.Addr().Interface(), data, tag)
				if err != nil {
					return err
				}
				continue
			}
		}

		inputValue, exists := data[inputFieldName]
		if !exists {
			// Go json.Unmarshal supports case insensitive binding.  However the
			// url params are bound case sensitive which is inconsistent.  To
			// fix this we must check all of the map values in a
			// case-insensitive search.
			inputFieldName = strings.ToLower(inputFieldName)
			for k, v := range data {
				if strings.ToLower(k) == inputFieldName {
					inputValue = v
					exists = true
					break
				}
			}
		}

		if !exists {
			continue
		}

		// Call this first, in case we're dealing with an alias to an array type
		if ok, err := unmarshalField(typeField.Type.Kind(), inputValue[0], structField); ok {
			if err != nil {
				return err
			}
			continue
		}

		numElems := len(inputValue)
		if structFieldKind == reflect.Slice && numElems > 0 {
			sliceOf := structField.Type().Elem().Kind()