|
| 1 | +/** |
| 2 | + * Copyright (c) F5, Inc. |
| 3 | + * |
| 4 | + * This source code is licensed under the Apache License, Version 2.0 license found in the |
| 5 | + * LICENSE file in the root directory of this source tree. |
| 6 | + */ |
| 7 | + |
| 8 | +package crossplane |
| 9 | + |
| 10 | +import "fmt" |
| 11 | + |
| 12 | +// mapParameterMasks holds bit masks that define the behavior of the body of map-like directives. |
| 13 | +// Some map directives have "special parameter" with different behaviors than the default. |
| 14 | +type mapParameterMasks struct { |
| 15 | + specialParameterMasks map[string]uint |
| 16 | + defaultMasks uint |
| 17 | +} |
| 18 | + |
| 19 | +//nolint:gochecknoglobals |
| 20 | +var mapBodies = map[string]mapParameterMasks{ |
| 21 | + "charset_map": { |
| 22 | + defaultMasks: ngxConfTake1, |
| 23 | + }, |
| 24 | + "geo": { |
| 25 | + specialParameterMasks: map[string]uint{"ranges": ngxConfNoArgs, "proxy_recursive": ngxConfNoArgs}, |
| 26 | + defaultMasks: ngxConfTake1, |
| 27 | + }, |
| 28 | + "map": { |
| 29 | + specialParameterMasks: map[string]uint{"volatile": ngxConfNoArgs, "hostnames": ngxConfNoArgs}, |
| 30 | + defaultMasks: ngxConfTake1, |
| 31 | + }, |
| 32 | + "match": { |
| 33 | + defaultMasks: ngxConf1More, |
| 34 | + }, |
| 35 | +} |
| 36 | + |
| 37 | +// analyzeMapBody validates the body of a map-like directive. Map-like directives are block directives |
| 38 | +// that don't contain nginx directives, and therefore cannot be analyzed in the same way as other blocks. |
| 39 | +func analyzeMapBody(fname string, parameter *Directive, term string, mapCtx string) error { |
| 40 | + masks, known := mapBodies[mapCtx] |
| 41 | + |
| 42 | + // if we're not inside a known map-like directive, don't bother analyzing |
| 43 | + if !known { |
| 44 | + return nil |
| 45 | + } |
| 46 | + |
| 47 | + if term != ";" { |
| 48 | + return &ParseError{ |
| 49 | + What: fmt.Sprintf(`unexpected "%s"`, term), |
| 50 | + File: &fname, |
| 51 | + Line: ¶meter.Line, |
| 52 | + } |
| 53 | + } |
| 54 | + |
| 55 | + if mask, ok := masks.specialParameterMasks[parameter.Directive]; ok { |
| 56 | + // use mask to check the parameter's arguments |
| 57 | + if hasValidArguments(mask, parameter.Args) { |
| 58 | + return nil |
| 59 | + } |
| 60 | + |
| 61 | + return &ParseError{ |
| 62 | + What: "invalid number of parameters", |
| 63 | + File: &fname, |
| 64 | + Line: ¶meter.Line, |
| 65 | + } |
| 66 | + } |
| 67 | + |
| 68 | + mask := masks.defaultMasks |
| 69 | + |
| 70 | + // use mask to check the parameter's arguments |
| 71 | + if hasValidArguments(mask, parameter.Args) { |
| 72 | + return nil |
| 73 | + } |
| 74 | + |
| 75 | + return &ParseError{ |
| 76 | + What: "invalid number of parameters", |
| 77 | + File: &fname, |
| 78 | + Line: ¶meter.Line, |
| 79 | + } |
| 80 | +} |
| 81 | + |
| 82 | +func hasValidArguments(mask uint, args []string) bool { |
| 83 | + return ((mask>>len(args)&1) != 0 && len(args) <= 7) || // NOARGS to TAKE7 |
| 84 | + ((mask&ngxConfFlag) != 0 && len(args) == 1 && validFlag(args[0])) || |
| 85 | + ((mask & ngxConfAny) != 0) || |
| 86 | + ((mask&ngxConf1More) != 0 && len(args) >= 1) || |
| 87 | + ((mask&ngxConf2More) != 0 && len(args) >= 2) |
| 88 | +} |
0 commit comments