mirror of
https://github.com/caddyserver/caddy.git
synced 2026-05-21 14:26:30 -04:00
map: Coerce val to string, fix #4987
Also prevent infinite recursion, and enforce placeholder syntax.
This commit is contained in:
@@ -27,10 +27,10 @@ func init() {
|
||||
|
||||
// parseCaddyfile sets up the map handler from Caddyfile tokens. Syntax:
|
||||
//
|
||||
// map [<matcher>] <source> <destinations...> {
|
||||
// [~]<input> <outputs...>
|
||||
// default <defaults...>
|
||||
// }
|
||||
// map [<matcher>] <source> <destinations...> {
|
||||
// [~]<input> <outputs...>
|
||||
// default <defaults...>
|
||||
// }
|
||||
//
|
||||
// If the input value is prefixed with a tilde (~), then the input will be parsed as a
|
||||
// regular expression.
|
||||
@@ -76,7 +76,7 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
|
||||
continue
|
||||
}
|
||||
|
||||
// every other line maps one input to one or more outputs
|
||||
// every line maps an input value to one or more outputs
|
||||
in := h.Val()
|
||||
var outs []any
|
||||
for h.NextArg() {
|
||||
|
||||
@@ -62,6 +62,9 @@ func (Handler) CaddyModule() caddy.ModuleInfo {
|
||||
// Provision sets up h.
|
||||
func (h *Handler) Provision(_ caddy.Context) error {
|
||||
for j, dest := range h.Destinations {
|
||||
if strings.Count(dest, "{") != 1 || !strings.HasPrefix(dest, "{") {
|
||||
return fmt.Errorf("destination must be a placeholder and only a placeholder")
|
||||
}
|
||||
h.Destinations[j] = strings.Trim(dest, "{}")
|
||||
}
|
||||
|
||||
@@ -106,6 +109,16 @@ func (h *Handler) Validate() error {
|
||||
}
|
||||
seen[input] = i
|
||||
|
||||
// prevent infinite recursion
|
||||
for _, out := range m.Outputs {
|
||||
for _, dest := range h.Destinations {
|
||||
if strings.Contains(caddy.ToString(out), dest) ||
|
||||
strings.Contains(m.Input, dest) {
|
||||
return fmt.Errorf("mapping %d requires value of {%s} to define value of {%s}: infinite recursion", i, dest, dest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ensure mappings have 1:1 output-to-destination correspondence
|
||||
nOut := len(m.Outputs)
|
||||
if nOut != nDest {
|
||||
@@ -135,21 +148,22 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhtt
|
||||
if output == nil {
|
||||
continue
|
||||
}
|
||||
outputStr := caddy.ToString(output)
|
||||
|
||||
// evaluate regular expression if configured
|
||||
if m.re != nil {
|
||||
var result []byte
|
||||
matches := m.re.FindStringSubmatchIndex(input)
|
||||
if matches == nil {
|
||||
continue
|
||||
}
|
||||
result = m.re.ExpandString(result, output.(string), input, matches)
|
||||
result = m.re.ExpandString(result, outputStr, input, matches)
|
||||
return string(result), true
|
||||
}
|
||||
|
||||
// otherwise simple string comparison
|
||||
if input == m.Input {
|
||||
if outputStr, ok := output.(string); ok {
|
||||
// NOTE: if the output has a placeholder that has the same key as the input, this is infinite recursion
|
||||
return repl.ReplaceAll(outputStr, ""), true
|
||||
}
|
||||
return output, true
|
||||
return repl.ReplaceAll(outputStr, ""), true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user