From 73d4a8ba02292491fca289b324e89ef8c62fd435 Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Thu, 1 Sep 2022 21:15:20 -0600 Subject: map: Coerce val to string, fix #4987 Also prevent infinite recursion, and enforce placeholder syntax. --- modules/caddyhttp/map/caddyfile.go | 10 +++++----- modules/caddyhttp/map/map.go | 26 ++++++++++++++++++++------ 2 files changed, 25 insertions(+), 11 deletions(-) (limited to 'modules/caddyhttp/map') diff --git a/modules/caddyhttp/map/caddyfile.go b/modules/caddyhttp/map/caddyfile.go index f38aff7..9cc7d8c 100644 --- a/modules/caddyhttp/map/caddyfile.go +++ b/modules/caddyhttp/map/caddyfile.go @@ -27,10 +27,10 @@ func init() { // parseCaddyfile sets up the map handler from Caddyfile tokens. Syntax: // -// map [] { -// [~] -// default -// } +// map [] { +// [~] +// default +// } // // 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() { diff --git a/modules/caddyhttp/map/map.go b/modules/caddyhttp/map/map.go index bbc1249..d41806d 100644 --- a/modules/caddyhttp/map/map.go +++ b/modules/caddyhttp/map/map.go @@ -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 } } -- cgit v1.2.3