github.com/DataDog/datadog-agent/pkg/security/secl@v0.55.0-devel.0.20240517055856-10c4965fea94/compiler/eval/operators.go (about)

     1  // Unless explicitly stated otherwise all files in this repository are licensed
     2  // under the Apache License Version 2.0.
     3  // This product includes software developed at Datadog (https://www.datadoghq.com/).
     4  // Copyright 2016-present Datadog, Inc.
     5  
     6  // Package eval holds eval related files
     7  package eval
     8  
     9  import (
    10  	"net"
    11  	"strings"
    12  )
    13  
    14  // OpOverrides defines operator override functions
    15  type OpOverrides struct {
    16  	StringEquals         func(a *StringEvaluator, b *StringEvaluator, state *State) (*BoolEvaluator, error)
    17  	StringValuesContains func(a *StringEvaluator, b *StringValuesEvaluator, state *State) (*BoolEvaluator, error)
    18  	StringArrayContains  func(a *StringEvaluator, b *StringArrayEvaluator, state *State) (*BoolEvaluator, error)
    19  	StringArrayMatches   func(a *StringArrayEvaluator, b *StringValuesEvaluator, state *State) (*BoolEvaluator, error)
    20  }
    21  
    22  // return whether a arithmetic operation is deterministic
    23  func isArithmDeterministic(a Evaluator, b Evaluator, state *State) bool {
    24  	isDc := a.IsDeterministicFor(state.field) || b.IsDeterministicFor(state.field)
    25  
    26  	if aField := a.GetField(); aField != "" && state.field != "" && aField != state.field {
    27  		isDc = false
    28  	}
    29  	if bField := b.GetField(); bField != "" && state.field != "" && bField != state.field {
    30  		isDc = false
    31  	}
    32  
    33  	return isDc
    34  }
    35  
    36  // Or operator
    37  func Or(a *BoolEvaluator, b *BoolEvaluator, state *State) (*BoolEvaluator, error) {
    38  
    39  	isDc := a.IsDeterministicFor(state.field) || b.IsDeterministicFor(state.field)
    40  
    41  	if a.EvalFnc != nil && b.EvalFnc != nil {
    42  		ea, eb := a.EvalFnc, b.EvalFnc
    43  
    44  		if state.field != "" {
    45  			if !a.IsDeterministicFor(state.field) && !a.IsStatic() {
    46  				ea = func(ctx *Context) bool {
    47  					return true
    48  				}
    49  			}
    50  			if !b.IsDeterministicFor(state.field) && !b.IsStatic() {
    51  				eb = func(ctx *Context) bool {
    52  					return true
    53  				}
    54  			}
    55  		}
    56  
    57  		if a.Weight > b.Weight {
    58  			tmp := ea
    59  			ea = eb
    60  			eb = tmp
    61  		}
    62  
    63  		evalFnc := func(ctx *Context) bool {
    64  			return ea(ctx) || eb(ctx)
    65  		}
    66  
    67  		return &BoolEvaluator{
    68  			EvalFnc:         evalFnc,
    69  			Weight:          a.Weight + b.Weight,
    70  			isDeterministic: isDc,
    71  		}, nil
    72  	}
    73  
    74  	if a.EvalFnc == nil && b.EvalFnc == nil {
    75  		ea, eb := a.Value, b.Value
    76  
    77  		ctx := NewContext(nil)
    78  		_ = ctx
    79  
    80  		return &BoolEvaluator{
    81  			Value:           ea || eb,
    82  			isDeterministic: isDc,
    83  		}, nil
    84  	}
    85  
    86  	if a.EvalFnc != nil {
    87  		ea, eb := a.EvalFnc, b.Value
    88  
    89  		if a.Field != "" {
    90  			if err := state.UpdateFieldValues(a.Field, FieldValue{Value: eb, Type: ScalarValueType}); err != nil {
    91  				return nil, err
    92  			}
    93  		}
    94  
    95  		if state.field != "" {
    96  			if !a.IsDeterministicFor(state.field) && !a.IsStatic() {
    97  				ea = func(ctx *Context) bool {
    98  					return true
    99  				}
   100  			}
   101  			if !b.IsDeterministicFor(state.field) && !b.IsStatic() {
   102  				eb = true
   103  			}
   104  		}
   105  
   106  		evalFnc := func(ctx *Context) bool {
   107  			return ea(ctx) || eb
   108  		}
   109  
   110  		return &BoolEvaluator{
   111  			EvalFnc:         evalFnc,
   112  			Field:           a.Field,
   113  			Weight:          a.Weight,
   114  			isDeterministic: isDc,
   115  		}, nil
   116  	}
   117  
   118  	ea, eb := a.Value, b.EvalFnc
   119  
   120  	if b.Field != "" {
   121  		if err := state.UpdateFieldValues(b.Field, FieldValue{Value: ea, Type: ScalarValueType}); err != nil {
   122  			return nil, err
   123  		}
   124  	}
   125  
   126  	if state.field != "" {
   127  		if !a.IsDeterministicFor(state.field) && !a.IsStatic() {
   128  			ea = true
   129  		}
   130  		if !b.IsDeterministicFor(state.field) && !b.IsStatic() {
   131  			eb = func(ctx *Context) bool {
   132  				return true
   133  			}
   134  		}
   135  	}
   136  
   137  	evalFnc := func(ctx *Context) bool {
   138  		return ea || eb(ctx)
   139  	}
   140  
   141  	return &BoolEvaluator{
   142  		EvalFnc:         evalFnc,
   143  		Field:           b.Field,
   144  		Weight:          b.Weight,
   145  		isDeterministic: isDc,
   146  	}, nil
   147  }
   148  
   149  // And operator
   150  func And(a *BoolEvaluator, b *BoolEvaluator, state *State) (*BoolEvaluator, error) {
   151  
   152  	isDc := a.IsDeterministicFor(state.field) || b.IsDeterministicFor(state.field)
   153  
   154  	if a.EvalFnc != nil && b.EvalFnc != nil {
   155  		ea, eb := a.EvalFnc, b.EvalFnc
   156  
   157  		if state.field != "" {
   158  			if !a.IsDeterministicFor(state.field) && !a.IsStatic() {
   159  				ea = func(ctx *Context) bool {
   160  					return true
   161  				}
   162  			}
   163  			if !b.IsDeterministicFor(state.field) && !b.IsStatic() {
   164  				eb = func(ctx *Context) bool {
   165  					return true
   166  				}
   167  			}
   168  		}
   169  
   170  		if a.Weight > b.Weight {
   171  			tmp := ea
   172  			ea = eb
   173  			eb = tmp
   174  		}
   175  
   176  		evalFnc := func(ctx *Context) bool {
   177  			return ea(ctx) && eb(ctx)
   178  		}
   179  
   180  		return &BoolEvaluator{
   181  			EvalFnc:         evalFnc,
   182  			Weight:          a.Weight + b.Weight,
   183  			isDeterministic: isDc,
   184  		}, nil
   185  	}
   186  
   187  	if a.EvalFnc == nil && b.EvalFnc == nil {
   188  		ea, eb := a.Value, b.Value
   189  
   190  		ctx := NewContext(nil)
   191  		_ = ctx
   192  
   193  		return &BoolEvaluator{
   194  			Value:           ea && eb,
   195  			isDeterministic: isDc,
   196  		}, nil
   197  	}
   198  
   199  	if a.EvalFnc != nil {
   200  		ea, eb := a.EvalFnc, b.Value
   201  
   202  		if a.Field != "" {
   203  			if err := state.UpdateFieldValues(a.Field, FieldValue{Value: eb, Type: ScalarValueType}); err != nil {
   204  				return nil, err
   205  			}
   206  		}
   207  
   208  		if state.field != "" {
   209  			if !a.IsDeterministicFor(state.field) && !a.IsStatic() {
   210  				ea = func(ctx *Context) bool {
   211  					return true
   212  				}
   213  			}
   214  			if !b.IsDeterministicFor(state.field) && !b.IsStatic() {
   215  				eb = true
   216  			}
   217  		}
   218  
   219  		evalFnc := func(ctx *Context) bool {
   220  			return ea(ctx) && eb
   221  		}
   222  
   223  		return &BoolEvaluator{
   224  			EvalFnc:         evalFnc,
   225  			Field:           a.Field,
   226  			Weight:          a.Weight,
   227  			isDeterministic: isDc,
   228  		}, nil
   229  	}
   230  
   231  	ea, eb := a.Value, b.EvalFnc
   232  
   233  	if b.Field != "" {
   234  		if err := state.UpdateFieldValues(b.Field, FieldValue{Value: ea, Type: ScalarValueType}); err != nil {
   235  			return nil, err
   236  		}
   237  	}
   238  
   239  	if state.field != "" {
   240  		if !a.IsDeterministicFor(state.field) && !a.IsStatic() {
   241  			ea = true
   242  		}
   243  		if !b.IsDeterministicFor(state.field) && !b.IsStatic() {
   244  			eb = func(ctx *Context) bool {
   245  				return true
   246  			}
   247  		}
   248  	}
   249  
   250  	evalFnc := func(ctx *Context) bool {
   251  		return ea && eb(ctx)
   252  	}
   253  
   254  	return &BoolEvaluator{
   255  		EvalFnc:         evalFnc,
   256  		Field:           b.Field,
   257  		Weight:          b.Weight,
   258  		isDeterministic: isDc,
   259  	}, nil
   260  }
   261  
   262  // IntNot ^int operator
   263  func IntNot(a *IntEvaluator, state *State) *IntEvaluator {
   264  	isDc := a.IsDeterministicFor(state.field)
   265  
   266  	if a.EvalFnc != nil {
   267  		ea := a.EvalFnc
   268  
   269  		evalFnc := func(ctx *Context) int {
   270  			return ^ea(ctx)
   271  		}
   272  
   273  		return &IntEvaluator{
   274  			EvalFnc:         evalFnc,
   275  			Weight:          a.Weight,
   276  			isDeterministic: isDc,
   277  		}
   278  	}
   279  
   280  	return &IntEvaluator{
   281  		Value:           ^a.Value,
   282  		Weight:          a.Weight,
   283  		isDeterministic: isDc,
   284  	}
   285  }
   286  
   287  // StringEquals evaluates string
   288  func StringEquals(a *StringEvaluator, b *StringEvaluator, state *State) (*BoolEvaluator, error) {
   289  	isDc := isArithmDeterministic(a, b, state)
   290  
   291  	if a.Field != "" {
   292  		if err := state.UpdateFieldValues(a.Field, FieldValue{Value: b.Value, Type: b.ValueType}); err != nil {
   293  			return nil, err
   294  		}
   295  	}
   296  
   297  	if b.Field != "" {
   298  		if err := state.UpdateFieldValues(b.Field, FieldValue{Value: a.Value, Type: a.ValueType}); err != nil {
   299  			return nil, err
   300  		}
   301  	}
   302  
   303  	// default comparison
   304  	op := func(as string, bs string) bool {
   305  		return as == bs
   306  	}
   307  
   308  	if a.Field != "" && b.Field != "" {
   309  		if a.StringCmpOpts.CaseInsensitive || b.StringCmpOpts.CaseInsensitive {
   310  			op = strings.EqualFold
   311  		}
   312  	} else if a.Field != "" {
   313  		matcher, err := b.ToStringMatcher(a.StringCmpOpts)
   314  		if err != nil {
   315  			return nil, err
   316  		}
   317  
   318  		if matcher != nil {
   319  			op = func(as string, bs string) bool {
   320  				return matcher.Matches(as)
   321  			}
   322  		}
   323  	} else if b.Field != "" {
   324  		matcher, err := a.ToStringMatcher(b.StringCmpOpts)
   325  		if err != nil {
   326  			return nil, err
   327  		}
   328  
   329  		if matcher != nil {
   330  			op = func(as string, bs string) bool {
   331  				return matcher.Matches(bs)
   332  			}
   333  		}
   334  	}
   335  
   336  	if a.EvalFnc != nil && b.EvalFnc != nil {
   337  		ea, eb := a.EvalFnc, b.EvalFnc
   338  
   339  		evalFnc := func(ctx *Context) bool {
   340  			return op(ea(ctx), eb(ctx))
   341  		}
   342  
   343  		return &BoolEvaluator{
   344  			EvalFnc:         evalFnc,
   345  			Weight:          a.Weight + b.Weight,
   346  			isDeterministic: isDc,
   347  		}, nil
   348  	}
   349  
   350  	if a.EvalFnc == nil && b.EvalFnc == nil {
   351  		ea, eb := a.Value, b.Value
   352  
   353  		return &BoolEvaluator{
   354  			Value:           op(ea, eb),
   355  			Weight:          a.Weight + InArrayWeight*len(eb),
   356  			isDeterministic: isDc,
   357  		}, nil
   358  	}
   359  
   360  	if a.EvalFnc != nil {
   361  		ea, eb := a.EvalFnc, b.Value
   362  
   363  		evalFnc := func(ctx *Context) bool {
   364  			return op(ea(ctx), eb)
   365  		}
   366  
   367  		return &BoolEvaluator{
   368  			EvalFnc:         evalFnc,
   369  			Weight:          a.Weight + InArrayWeight*len(eb),
   370  			isDeterministic: isDc,
   371  		}, nil
   372  	}
   373  
   374  	ea, eb := a.Value, b.EvalFnc
   375  
   376  	evalFnc := func(ctx *Context) bool {
   377  		return op(ea, eb(ctx))
   378  	}
   379  
   380  	return &BoolEvaluator{
   381  		EvalFnc:         evalFnc,
   382  		Weight:          b.Weight,
   383  		isDeterministic: isDc,
   384  	}, nil
   385  }
   386  
   387  // Not !true operator
   388  func Not(a *BoolEvaluator, state *State) *BoolEvaluator {
   389  	isDc := a.IsDeterministicFor(state.field)
   390  
   391  	if a.EvalFnc != nil {
   392  		ea := func(ctx *Context) bool {
   393  			return !a.EvalFnc(ctx)
   394  		}
   395  
   396  		if state.field != "" && !a.IsDeterministicFor(state.field) {
   397  			ea = func(ctx *Context) bool {
   398  				return true
   399  			}
   400  		}
   401  
   402  		return &BoolEvaluator{
   403  			EvalFnc:         ea,
   404  			Weight:          a.Weight,
   405  			isDeterministic: isDc,
   406  		}
   407  	}
   408  
   409  	return &BoolEvaluator{
   410  		Value:           !a.Value,
   411  		Weight:          a.Weight,
   412  		isDeterministic: isDc,
   413  	}
   414  }
   415  
   416  // Minus -int operator
   417  func Minus(a *IntEvaluator, state *State) *IntEvaluator {
   418  	isDc := a.IsDeterministicFor(state.field)
   419  
   420  	if a.EvalFnc != nil {
   421  		ea := a.EvalFnc
   422  
   423  		evalFnc := func(ctx *Context) int {
   424  			return -ea(ctx)
   425  		}
   426  
   427  		return &IntEvaluator{
   428  			EvalFnc:         evalFnc,
   429  			Weight:          a.Weight,
   430  			isDeterministic: isDc,
   431  		}
   432  	}
   433  
   434  	return &IntEvaluator{
   435  		Value:           -a.Value,
   436  		Weight:          a.Weight,
   437  		isDeterministic: isDc,
   438  	}
   439  }
   440  
   441  // StringArrayContains evaluates array of strings against a value
   442  func StringArrayContains(a *StringEvaluator, b *StringArrayEvaluator, state *State) (*BoolEvaluator, error) {
   443  	isDc := isArithmDeterministic(a, b, state)
   444  
   445  	if a.Field != "" {
   446  		for _, value := range b.Values {
   447  			if err := state.UpdateFieldValues(a.Field, FieldValue{Value: value, Type: ScalarValueType}); err != nil {
   448  				return nil, err
   449  			}
   450  		}
   451  	}
   452  
   453  	if b.Field != "" {
   454  		if err := state.UpdateFieldValues(b.Field, FieldValue{Value: a.Value, Type: a.ValueType}); err != nil {
   455  			return nil, err
   456  		}
   457  	}
   458  
   459  	op := func(a string, b []string, cmp func(a, b string) bool) bool {
   460  		for _, bs := range b {
   461  			if cmp(a, bs) {
   462  				return true
   463  			}
   464  		}
   465  		return false
   466  	}
   467  
   468  	cmp := func(a, b string) bool {
   469  		return a == b
   470  	}
   471  
   472  	if a.Field != "" && b.Field != "" {
   473  		if a.StringCmpOpts.CaseInsensitive || b.StringCmpOpts.CaseInsensitive {
   474  			cmp = strings.EqualFold
   475  		}
   476  	} else if a.Field != "" && a.StringCmpOpts.CaseInsensitive {
   477  		cmp = strings.EqualFold
   478  	} else if b.Field != "" {
   479  		matcher, err := a.ToStringMatcher(b.StringCmpOpts)
   480  		if err != nil {
   481  			return nil, err
   482  		}
   483  
   484  		if matcher != nil {
   485  			cmp = func(a, b string) bool {
   486  				return matcher.Matches(b)
   487  			}
   488  		}
   489  	}
   490  
   491  	if a.EvalFnc != nil && b.EvalFnc != nil {
   492  		ea, eb := a.EvalFnc, b.EvalFnc
   493  
   494  		evalFnc := func(ctx *Context) bool {
   495  			return op(ea(ctx), eb(ctx), cmp)
   496  		}
   497  
   498  		return &BoolEvaluator{
   499  			EvalFnc:         evalFnc,
   500  			Weight:          a.Weight + b.Weight,
   501  			isDeterministic: isDc,
   502  		}, nil
   503  	}
   504  
   505  	if a.EvalFnc == nil && b.EvalFnc == nil {
   506  		ea, eb := a.Value, b.Values
   507  
   508  		return &BoolEvaluator{
   509  			Value:           op(ea, eb, cmp),
   510  			Weight:          a.Weight + InArrayWeight*len(eb),
   511  			isDeterministic: isDc,
   512  		}, nil
   513  	}
   514  
   515  	if a.EvalFnc != nil {
   516  		ea, eb := a.EvalFnc, b.Values
   517  
   518  		evalFnc := func(ctx *Context) bool {
   519  			return op(ea(ctx), eb, cmp)
   520  		}
   521  
   522  		return &BoolEvaluator{
   523  			EvalFnc:         evalFnc,
   524  			Weight:          a.Weight + InArrayWeight*len(eb),
   525  			isDeterministic: isDc,
   526  		}, nil
   527  	}
   528  
   529  	ea, eb := a.Value, b.EvalFnc
   530  
   531  	evalFnc := func(ctx *Context) bool {
   532  		return op(ea, eb(ctx), cmp)
   533  	}
   534  
   535  	return &BoolEvaluator{
   536  		EvalFnc:         evalFnc,
   537  		Weight:          b.Weight,
   538  		isDeterministic: isDc,
   539  	}, nil
   540  }
   541  
   542  // StringValuesContains evaluates a string against values
   543  func StringValuesContains(a *StringEvaluator, b *StringValuesEvaluator, state *State) (*BoolEvaluator, error) {
   544  	isDc := isArithmDeterministic(a, b, state)
   545  
   546  	if a.Field != "" {
   547  		for _, value := range b.Values.fieldValues {
   548  			if err := state.UpdateFieldValues(a.Field, value); err != nil {
   549  				return nil, err
   550  			}
   551  		}
   552  	}
   553  
   554  	if err := b.Compile(a.StringCmpOpts); err != nil {
   555  		return nil, err
   556  	}
   557  
   558  	if a.EvalFnc != nil && b.EvalFnc != nil {
   559  		ea, eb := a.EvalFnc, b.EvalFnc
   560  
   561  		evalFnc := func(ctx *Context) bool {
   562  			values := eb(ctx)
   563  			return values.Matches(ea(ctx))
   564  		}
   565  
   566  		return &BoolEvaluator{
   567  			EvalFnc:         evalFnc,
   568  			Weight:          a.Weight + b.Weight,
   569  			isDeterministic: isDc,
   570  		}, nil
   571  	}
   572  
   573  	if a.EvalFnc == nil && b.EvalFnc == nil {
   574  		ea, eb := a.Value, b.Values
   575  
   576  		return &BoolEvaluator{
   577  			Value:           eb.Matches(ea),
   578  			Weight:          a.Weight + InArrayWeight*len(eb.fieldValues),
   579  			isDeterministic: isDc,
   580  		}, nil
   581  	}
   582  
   583  	if a.EvalFnc != nil {
   584  		ea, eb := a.EvalFnc, b.Values
   585  
   586  		evalFnc := func(ctx *Context) bool {
   587  			return eb.Matches(ea(ctx))
   588  		}
   589  
   590  		return &BoolEvaluator{
   591  			EvalFnc:         evalFnc,
   592  			Weight:          a.Weight + InArrayWeight*len(eb.fieldValues),
   593  			isDeterministic: isDc,
   594  		}, nil
   595  	}
   596  
   597  	ea, eb := a.Value, b.EvalFnc
   598  
   599  	evalFnc := func(ctx *Context) bool {
   600  		values := eb(ctx)
   601  		return values.Matches(ea)
   602  	}
   603  
   604  	return &BoolEvaluator{
   605  		EvalFnc:         evalFnc,
   606  		Weight:          b.Weight,
   607  		isDeterministic: isDc,
   608  	}, nil
   609  }
   610  
   611  // StringArrayMatches weak comparison, a least one element of a should be in b. a can't contain regexp
   612  func StringArrayMatches(a *StringArrayEvaluator, b *StringValuesEvaluator, state *State) (*BoolEvaluator, error) {
   613  	isDc := isArithmDeterministic(a, b, state)
   614  
   615  	if a.Field != "" {
   616  		for _, value := range b.Values.fieldValues {
   617  			if err := state.UpdateFieldValues(a.Field, value); err != nil {
   618  				return nil, err
   619  			}
   620  		}
   621  	}
   622  
   623  	if err := b.Compile(a.StringCmpOpts); err != nil {
   624  		return nil, err
   625  	}
   626  
   627  	arrayOp := func(a []string, b *StringValues) bool {
   628  		for _, as := range a {
   629  			if b.Matches(as) {
   630  				return true
   631  			}
   632  		}
   633  		return false
   634  	}
   635  
   636  	if a.EvalFnc != nil && b.EvalFnc != nil {
   637  		ea, eb := a.EvalFnc, b.EvalFnc
   638  
   639  		evalFnc := func(ctx *Context) bool {
   640  			return arrayOp(ea(ctx), eb(ctx))
   641  		}
   642  
   643  		return &BoolEvaluator{
   644  			EvalFnc:         evalFnc,
   645  			Weight:          a.Weight + b.Weight,
   646  			isDeterministic: isDc,
   647  		}, nil
   648  	}
   649  
   650  	if a.EvalFnc == nil && b.EvalFnc == nil {
   651  		ea, eb := a.Values, b.Values
   652  
   653  		return &BoolEvaluator{
   654  			Value:           arrayOp(ea, &eb),
   655  			Weight:          a.Weight + InArrayWeight*len(eb.fieldValues),
   656  			isDeterministic: isDc,
   657  		}, nil
   658  	}
   659  
   660  	if a.EvalFnc != nil {
   661  		ea, eb := a.EvalFnc, b.Values
   662  
   663  		evalFnc := func(ctx *Context) bool {
   664  			return arrayOp(ea(ctx), &eb)
   665  		}
   666  
   667  		return &BoolEvaluator{
   668  			EvalFnc:         evalFnc,
   669  			Weight:          a.Weight + InArrayWeight*len(eb.fieldValues),
   670  			isDeterministic: isDc,
   671  		}, nil
   672  	}
   673  
   674  	ea, eb := a.Values, b.EvalFnc
   675  
   676  	evalFnc := func(ctx *Context) bool {
   677  		return arrayOp(ea, eb(ctx))
   678  	}
   679  
   680  	return &BoolEvaluator{
   681  		EvalFnc:         evalFnc,
   682  		Weight:          b.Weight,
   683  		isDeterministic: isDc,
   684  	}, nil
   685  }
   686  
   687  // IntArrayMatches weak comparison, a least one element of a should be in b
   688  func IntArrayMatches(a *IntArrayEvaluator, b *IntArrayEvaluator, state *State) (*BoolEvaluator, error) {
   689  	isDc := isArithmDeterministic(a, b, state)
   690  
   691  	if a.Field != "" {
   692  		for _, value := range b.Values {
   693  			if err := state.UpdateFieldValues(a.Field, FieldValue{Value: value}); err != nil {
   694  				return nil, err
   695  			}
   696  		}
   697  	}
   698  
   699  	arrayOp := func(a []int, b []int) bool {
   700  		for _, va := range a {
   701  			for _, vb := range b {
   702  				if va == vb {
   703  					return true
   704  				}
   705  			}
   706  		}
   707  		return false
   708  	}
   709  
   710  	if a.EvalFnc != nil && b.EvalFnc != nil {
   711  		ea, eb := a.EvalFnc, b.EvalFnc
   712  
   713  		evalFnc := func(ctx *Context) bool {
   714  			return arrayOp(ea(ctx), eb(ctx))
   715  		}
   716  
   717  		return &BoolEvaluator{
   718  			EvalFnc:         evalFnc,
   719  			Weight:          a.Weight + b.Weight,
   720  			isDeterministic: isDc,
   721  		}, nil
   722  	}
   723  
   724  	if a.EvalFnc == nil && b.EvalFnc == nil {
   725  		ea, eb := a.Values, b.Values
   726  
   727  		return &BoolEvaluator{
   728  			Value:           arrayOp(ea, eb),
   729  			Weight:          a.Weight + InArrayWeight*len(eb),
   730  			isDeterministic: isDc,
   731  		}, nil
   732  	}
   733  
   734  	if a.EvalFnc != nil {
   735  		ea, eb := a.EvalFnc, b.Values
   736  
   737  		evalFnc := func(ctx *Context) bool {
   738  			return arrayOp(ea(ctx), eb)
   739  		}
   740  
   741  		return &BoolEvaluator{
   742  			EvalFnc:         evalFnc,
   743  			Weight:          a.Weight + InArrayWeight*len(eb),
   744  			isDeterministic: isDc,
   745  		}, nil
   746  	}
   747  
   748  	ea, eb := a.Values, b.EvalFnc
   749  
   750  	evalFnc := func(ctx *Context) bool {
   751  		return arrayOp(ea, eb(ctx))
   752  	}
   753  
   754  	return &BoolEvaluator{
   755  		EvalFnc:         evalFnc,
   756  		Weight:          b.Weight,
   757  		isDeterministic: isDc,
   758  	}, nil
   759  }
   760  
   761  // ArrayBoolContains evaluates array of bool against a value
   762  func ArrayBoolContains(a *BoolEvaluator, b *BoolArrayEvaluator, state *State) (*BoolEvaluator, error) {
   763  	isDc := isArithmDeterministic(a, b, state)
   764  
   765  	if a.Field != "" {
   766  		for _, value := range b.Values {
   767  			if err := state.UpdateFieldValues(a.Field, FieldValue{Value: value}); err != nil {
   768  				return nil, err
   769  			}
   770  		}
   771  	}
   772  
   773  	if b.Field != "" {
   774  		if err := state.UpdateFieldValues(b.Field, FieldValue{Value: a.Value}); err != nil {
   775  			return nil, err
   776  		}
   777  	}
   778  
   779  	arrayOp := func(a bool, b []bool) bool {
   780  		for _, v := range b {
   781  			if v == a {
   782  				return true
   783  			}
   784  		}
   785  		return false
   786  	}
   787  	if a.EvalFnc != nil && b.EvalFnc != nil {
   788  		ea, eb := a.EvalFnc, b.EvalFnc
   789  
   790  		evalFnc := func(ctx *Context) bool {
   791  			return arrayOp(ea(ctx), eb(ctx))
   792  		}
   793  
   794  		return &BoolEvaluator{
   795  			EvalFnc:         evalFnc,
   796  			Weight:          a.Weight + b.Weight,
   797  			isDeterministic: isDc,
   798  		}, nil
   799  	}
   800  
   801  	if a.EvalFnc == nil && b.EvalFnc == nil {
   802  		ea, eb := a.Value, b.Values
   803  
   804  		return &BoolEvaluator{
   805  			Value:           arrayOp(ea, eb),
   806  			Weight:          a.Weight + InArrayWeight*len(eb),
   807  			isDeterministic: isDc,
   808  		}, nil
   809  	}
   810  
   811  	if a.EvalFnc != nil {
   812  		ea, eb := a.EvalFnc, b.Values
   813  
   814  		evalFnc := func(ctx *Context) bool {
   815  			return arrayOp(ea(ctx), eb)
   816  		}
   817  
   818  		return &BoolEvaluator{
   819  			EvalFnc:         evalFnc,
   820  			Weight:          a.Weight + InArrayWeight*len(eb),
   821  			isDeterministic: isDc,
   822  		}, nil
   823  	}
   824  
   825  	ea, eb := a.Value, b.EvalFnc
   826  
   827  	evalFnc := func(ctx *Context) bool {
   828  		return arrayOp(ea, eb(ctx))
   829  	}
   830  
   831  	return &BoolEvaluator{
   832  		EvalFnc:         evalFnc,
   833  		Weight:          b.Weight,
   834  		isDeterministic: isDc,
   835  	}, nil
   836  }
   837  
   838  // CIDREquals evaluates CIDR ranges
   839  func CIDREquals(a *CIDREvaluator, b *CIDREvaluator, state *State) (*BoolEvaluator, error) {
   840  	isDc := isArithmDeterministic(a, b, state)
   841  
   842  	if a.Field != "" {
   843  		if err := state.UpdateFieldValues(a.Field, FieldValue{Value: b.Value, Type: b.ValueType}); err != nil {
   844  			return nil, err
   845  		}
   846  	}
   847  
   848  	if b.Field != "" {
   849  		if err := state.UpdateFieldValues(b.Field, FieldValue{Value: a.Value, Type: a.ValueType}); err != nil {
   850  			return nil, err
   851  		}
   852  	}
   853  
   854  	if a.EvalFnc != nil && b.EvalFnc != nil {
   855  		ea, eb := a.EvalFnc, b.EvalFnc
   856  
   857  		evalFnc := func(ctx *Context) bool {
   858  			a, b := ea(ctx), eb(ctx)
   859  			return IPNetsMatch(&a, &b)
   860  		}
   861  
   862  		return &BoolEvaluator{
   863  			EvalFnc:         evalFnc,
   864  			Weight:          a.Weight + b.Weight,
   865  			isDeterministic: isDc,
   866  		}, nil
   867  	}
   868  
   869  	if a.EvalFnc == nil && b.EvalFnc == nil {
   870  		ea, eb := a.Value, b.Value
   871  
   872  		return &BoolEvaluator{
   873  			Value:           IPNetsMatch(&ea, &eb),
   874  			Weight:          a.Weight + b.Weight,
   875  			isDeterministic: isDc,
   876  		}, nil
   877  	}
   878  
   879  	if a.EvalFnc != nil {
   880  		ea, eb := a.EvalFnc, b.Value
   881  
   882  		evalFnc := func(ctx *Context) bool {
   883  			a := ea(ctx)
   884  			return IPNetsMatch(&a, &eb)
   885  		}
   886  
   887  		return &BoolEvaluator{
   888  			EvalFnc:         evalFnc,
   889  			Weight:          a.Weight + b.Weight,
   890  			isDeterministic: isDc,
   891  		}, nil
   892  	}
   893  
   894  	ea, eb := a.Value, b.EvalFnc
   895  
   896  	evalFnc := func(ctx *Context) bool {
   897  		b := eb(ctx)
   898  		return IPNetsMatch(&ea, &b)
   899  	}
   900  
   901  	return &BoolEvaluator{
   902  		EvalFnc:         evalFnc,
   903  		Weight:          b.Weight,
   904  		isDeterministic: isDc,
   905  	}, nil
   906  }
   907  
   908  // CIDRValuesContains evaluates a CIDR against a list of CIDRs
   909  func CIDRValuesContains(a *CIDREvaluator, b *CIDRValuesEvaluator, state *State) (*BoolEvaluator, error) {
   910  	isDc := isArithmDeterministic(a, b, state)
   911  
   912  	if a.Field != "" {
   913  		for _, value := range b.Value.fieldValues {
   914  			if err := state.UpdateFieldValues(a.Field, value); err != nil {
   915  				return nil, err
   916  			}
   917  		}
   918  	}
   919  
   920  	if a.EvalFnc != nil && b.EvalFnc != nil {
   921  		ea, eb := a.EvalFnc, b.EvalFnc
   922  
   923  		evalFnc := func(ctx *Context) bool {
   924  			a := ea(ctx)
   925  			return eb(ctx).Contains(&a)
   926  		}
   927  
   928  		return &BoolEvaluator{
   929  			EvalFnc:         evalFnc,
   930  			Weight:          a.Weight + b.Weight,
   931  			isDeterministic: isDc,
   932  		}, nil
   933  	}
   934  
   935  	if a.EvalFnc == nil && b.EvalFnc == nil {
   936  		ea, eb := a.Value, b.Value
   937  
   938  		return &BoolEvaluator{
   939  			Value:           eb.Contains(&ea),
   940  			Weight:          a.Weight + InArrayWeight*len(eb.ipnets),
   941  			isDeterministic: isDc,
   942  		}, nil
   943  	}
   944  
   945  	if a.EvalFnc != nil {
   946  		ea, eb := a.EvalFnc, b.Value
   947  
   948  		evalFnc := func(ctx *Context) bool {
   949  			ipnet := ea(ctx)
   950  			return eb.Contains(&ipnet)
   951  		}
   952  
   953  		return &BoolEvaluator{
   954  			EvalFnc:         evalFnc,
   955  			Weight:          a.Weight + InArrayWeight*len(eb.fieldValues),
   956  			isDeterministic: isDc,
   957  		}, nil
   958  	}
   959  
   960  	ea, eb := a.Value, b.EvalFnc
   961  
   962  	evalFnc := func(ctx *Context) bool {
   963  		return eb(ctx).Contains(&ea)
   964  	}
   965  
   966  	return &BoolEvaluator{
   967  		EvalFnc:         evalFnc,
   968  		Weight:          b.Weight,
   969  		isDeterministic: isDc,
   970  	}, nil
   971  }
   972  
   973  func cidrArrayMatches(a *CIDRArrayEvaluator, b *CIDRValuesEvaluator, state *State, arrayOp func(a *CIDRValues, b []net.IPNet) bool) (*BoolEvaluator, error) {
   974  	isDc := isArithmDeterministic(a, b, state)
   975  
   976  	if a.Field != "" {
   977  		for _, value := range b.Value.fieldValues {
   978  			if err := state.UpdateFieldValues(a.Field, value); err != nil {
   979  				return nil, err
   980  			}
   981  		}
   982  	}
   983  
   984  	if a.EvalFnc != nil && b.EvalFnc != nil {
   985  		ea, eb := a.EvalFnc, b.EvalFnc
   986  
   987  		evalFnc := func(ctx *Context) bool {
   988  			return arrayOp(eb(ctx), ea(ctx))
   989  		}
   990  
   991  		return &BoolEvaluator{
   992  			EvalFnc:         evalFnc,
   993  			Weight:          a.Weight + b.Weight,
   994  			isDeterministic: isDc,
   995  		}, nil
   996  	}
   997  
   998  	if a.EvalFnc == nil && b.EvalFnc == nil {
   999  		ea, eb := a.Value, b.Value
  1000  
  1001  		return &BoolEvaluator{
  1002  			Value:           arrayOp(&eb, ea),
  1003  			Weight:          a.Weight + InArrayWeight*len(eb.fieldValues),
  1004  			isDeterministic: isDc,
  1005  		}, nil
  1006  	}
  1007  
  1008  	if a.EvalFnc != nil {
  1009  		ea, eb := a.EvalFnc, b.Value
  1010  
  1011  		evalFnc := func(ctx *Context) bool {
  1012  			return arrayOp(&eb, ea(ctx))
  1013  		}
  1014  
  1015  		return &BoolEvaluator{
  1016  			EvalFnc:         evalFnc,
  1017  			Weight:          a.Weight + InArrayWeight*len(eb.fieldValues),
  1018  			isDeterministic: isDc,
  1019  		}, nil
  1020  	}
  1021  
  1022  	ea, eb := a.Value, b.EvalFnc
  1023  
  1024  	evalFnc := func(ctx *Context) bool {
  1025  		return arrayOp(eb(ctx), ea)
  1026  	}
  1027  
  1028  	return &BoolEvaluator{
  1029  		EvalFnc:         evalFnc,
  1030  		Weight:          b.Weight,
  1031  		isDeterministic: isDc,
  1032  	}, nil
  1033  }
  1034  
  1035  // CIDRArrayMatches weak comparison, at least one element of a should be in b.
  1036  func CIDRArrayMatches(a *CIDRArrayEvaluator, b *CIDRValuesEvaluator, state *State) (*BoolEvaluator, error) {
  1037  	op := func(values *CIDRValues, ipnets []net.IPNet) bool {
  1038  		return values.Match(ipnets)
  1039  	}
  1040  	return cidrArrayMatches(a, b, state, op)
  1041  }
  1042  
  1043  // CIDRArrayMatchesAll ensures that all values from a and b match.
  1044  func CIDRArrayMatchesAll(a *CIDRArrayEvaluator, b *CIDRValuesEvaluator, state *State) (*BoolEvaluator, error) {
  1045  	op := func(values *CIDRValues, ipnets []net.IPNet) bool {
  1046  		return values.MatchAll(ipnets)
  1047  	}
  1048  	return cidrArrayMatches(a, b, state, op)
  1049  }
  1050  
  1051  // CIDRArrayContains evaluates a CIDR against a list of CIDRs
  1052  func CIDRArrayContains(a *CIDREvaluator, b *CIDRArrayEvaluator, state *State) (*BoolEvaluator, error) {
  1053  	isDc := isArithmDeterministic(a, b, state)
  1054  
  1055  	if a.Field != "" {
  1056  		for _, value := range b.Value {
  1057  			if err := state.UpdateFieldValues(a.Field, FieldValue{Type: IPNetValueType, Value: value}); err != nil {
  1058  				return nil, err
  1059  			}
  1060  		}
  1061  	}
  1062  
  1063  	arrayOp := func(a *net.IPNet, b []net.IPNet) bool {
  1064  		for _, n := range b {
  1065  			if IPNetsMatch(a, &n) {
  1066  				return true
  1067  			}
  1068  		}
  1069  		return false
  1070  	}
  1071  
  1072  	if a.EvalFnc != nil && b.EvalFnc != nil {
  1073  		ea, eb := a.EvalFnc, b.EvalFnc
  1074  
  1075  		evalFnc := func(ctx *Context) bool {
  1076  			a := ea(ctx)
  1077  			return arrayOp(&a, eb(ctx))
  1078  		}
  1079  
  1080  		return &BoolEvaluator{
  1081  			EvalFnc:         evalFnc,
  1082  			Weight:          a.Weight + b.Weight,
  1083  			isDeterministic: isDc,
  1084  		}, nil
  1085  	}
  1086  
  1087  	if a.EvalFnc == nil && b.EvalFnc == nil {
  1088  		ea, eb := a.Value, b.Value
  1089  
  1090  		return &BoolEvaluator{
  1091  			Value:           arrayOp(&ea, eb),
  1092  			Weight:          a.Weight + InArrayWeight*len(eb),
  1093  			isDeterministic: isDc,
  1094  		}, nil
  1095  	}
  1096  
  1097  	if a.EvalFnc != nil {
  1098  		ea, eb := a.EvalFnc, b.Value
  1099  
  1100  		evalFnc := func(ctx *Context) bool {
  1101  			ipnet := ea(ctx)
  1102  			return arrayOp(&ipnet, eb)
  1103  		}
  1104  
  1105  		return &BoolEvaluator{
  1106  			EvalFnc:         evalFnc,
  1107  			Weight:          a.Weight + InArrayWeight*len(eb),
  1108  			isDeterministic: isDc,
  1109  		}, nil
  1110  	}
  1111  
  1112  	ea, eb := a.Value, b.EvalFnc
  1113  
  1114  	evalFnc := func(ctx *Context) bool {
  1115  		return arrayOp(&ea, eb(ctx))
  1116  	}
  1117  
  1118  	return &BoolEvaluator{
  1119  		EvalFnc:         evalFnc,
  1120  		Weight:          b.Weight,
  1121  		isDeterministic: isDc,
  1122  	}, nil
  1123  }