Skip to content

Commit

Permalink
bucket: avoid crashing on malformed expression (fix crowdsecurity#3351)…
Browse files Browse the repository at this point in the history
  • Loading branch information
mmetc authored Jan 30, 2025
1 parent 5260cf1 commit 6827f06
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 6 deletions.
1 change: 0 additions & 1 deletion pkg/leakybucket/blackhole.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ type Blackhole struct {
func NewBlackhole(bucketFactory *BucketFactory) (*Blackhole, error) {
duration, err := time.ParseDuration(bucketFactory.Blackhole)
if err != nil {
bucketFactory.logger.Warning("Blackhole duration not valid, using 1h")
return nil, fmt.Errorf("blackhole duration not valid '%s'", bucketFactory.Blackhole)
}
return &Blackhole{
Expand Down
16 changes: 16 additions & 0 deletions pkg/leakybucket/manager_load.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,11 +405,22 @@ func LoadBucket(bucketFactory *BucketFactory, tomb *tomb.Tomb) error {
if bucketFactory.Distinct != "" {
bucketFactory.logger.Tracef("Adding a non duplicate filter")
bucketFactory.processors = append(bucketFactory.processors, &Uniq{})
bucketFactory.logger.Infof("Compiling distinct '%s'", bucketFactory.Distinct)
//we're compiling and discarding the expression to be able to detect it during loading
_, err = expr.Compile(bucketFactory.Distinct, exprhelpers.GetExprOptions(map[string]interface{}{"evt": &types.Event{}})...)
if err != nil {
return fmt.Errorf("invalid distinct '%s' in %s: %w", bucketFactory.Distinct, bucketFactory.Filename, err)
}
}

if bucketFactory.CancelOnFilter != "" {
bucketFactory.logger.Tracef("Adding a cancel_on filter")
bucketFactory.processors = append(bucketFactory.processors, &CancelOnFilter{})
//we're compiling and discarding the expression to be able to detect it during loading
_, err = expr.Compile(bucketFactory.CancelOnFilter, exprhelpers.GetExprOptions(map[string]interface{}{"evt": &types.Event{}})...)
if err != nil {
return fmt.Errorf("invalid cancel_on '%s' in %s: %w", bucketFactory.CancelOnFilter, bucketFactory.Filename, err)
}
}

if bucketFactory.OverflowFilter != "" {
Expand Down Expand Up @@ -439,6 +450,11 @@ func LoadBucket(bucketFactory *BucketFactory, tomb *tomb.Tomb) error {
if bucketFactory.ConditionalOverflow != "" {
bucketFactory.logger.Tracef("Adding conditional overflow")
bucketFactory.processors = append(bucketFactory.processors, &ConditionalOverflow{})
//we're compiling and discarding the expression to be able to detect it during loading
_, err = expr.Compile(bucketFactory.ConditionalOverflow, exprhelpers.GetExprOptions(map[string]interface{}{"queue": &types.Queue{}, "leaky": &Leaky{}, "evt": &types.Event{}})...)
if err != nil {
return fmt.Errorf("invalid condition '%s' in %s: %w", bucketFactory.ConditionalOverflow, bucketFactory.Filename, err)
}
}

if bucketFactory.BayesianThreshold != 0 {
Expand Down
14 changes: 14 additions & 0 deletions pkg/leakybucket/manager_load_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,24 @@ func TestLeakyBucketsConfig(t *testing.T) {
{BucketFactory{Name: "test", Description: "test1", Type: "leaky", Capacity: 1, LeakSpeed: "1s", Filter: "true"}, true, true},
// leaky with invalid filter
{BucketFactory{Name: "test", Description: "test1", Type: "leaky", Capacity: 1, LeakSpeed: "1s", Filter: "xu"}, false, true},
// leaky with invalid uniq
{BucketFactory{Name: "test", Description: "test1", Type: "leaky", Capacity: 1, LeakSpeed: "1s", Filter: "true", Distinct: "foo"}, false, true},
// leaky with valid uniq
{BucketFactory{Name: "test", Description: "test1", Type: "leaky", Capacity: 1, LeakSpeed: "1s", Filter: "true", Distinct: "evt.Parsed.foobar"}, true, true},
// leaky with valid filter
{BucketFactory{Name: "test", Description: "test1", Type: "leaky", Capacity: 1, LeakSpeed: "1s", Filter: "true"}, true, true},
// leaky with bad overflow filter
{BucketFactory{Name: "test", Description: "test1", Type: "leaky", Capacity: 1, LeakSpeed: "1s", Filter: "true", OverflowFilter: "xu"}, false, true},
// leaky with valid overflow filter
{BucketFactory{Name: "test", Description: "test1", Type: "leaky", Capacity: 1, LeakSpeed: "1s", Filter: "true", OverflowFilter: "true"}, true, true},
// leaky with invalid cancel_on filter
{BucketFactory{Name: "test", Description: "test1", Type: "leaky", Capacity: 1, LeakSpeed: "1s", Filter: "true", CancelOnFilter: "xu"}, false, true},
// leaky with valid cancel_on filter
{BucketFactory{Name: "test", Description: "test1", Type: "leaky", Capacity: 1, LeakSpeed: "1s", Filter: "true", CancelOnFilter: "true"}, true, true},
// leaky with invalid conditional overflow filter
{BucketFactory{Name: "test", Description: "test1", Type: "leaky", Capacity: 1, LeakSpeed: "1s", Filter: "true", ConditionalOverflow: "xu"}, false, true},
// leaky with valid conditional overflow filter
{BucketFactory{Name: "test", Description: "test1", Type: "leaky", Capacity: 1, LeakSpeed: "1s", Filter: "true", ConditionalOverflow: "true"}, true, true},
}

if err := runTest(CfgTests); err != nil {
Expand Down
10 changes: 5 additions & 5 deletions pkg/leakybucket/uniq.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@ func (u *Uniq) AfterBucketPour(bucketFactory *BucketFactory) func(types.Event, *
}

func (u *Uniq) OnBucketInit(bucketFactory *BucketFactory) error {
var err error
var compiledExpr *vm.Program

if uniqExprCache == nil {
uniqExprCache = make(map[string]vm.Program)
}
Expand All @@ -74,14 +71,17 @@ func (u *Uniq) OnBucketInit(bucketFactory *BucketFactory) error {
} else {
uniqExprCacheLock.Unlock()
//release the lock during compile
compiledExpr, err = expr.Compile(bucketFactory.Distinct, exprhelpers.GetExprOptions(map[string]interface{}{"evt": &types.Event{}})...)
compiledExpr, err := expr.Compile(bucketFactory.Distinct, exprhelpers.GetExprOptions(map[string]interface{}{"evt": &types.Event{}})...)
if err != nil {
return err
}
u.DistinctCompiled = compiledExpr
uniqExprCacheLock.Lock()
uniqExprCache[bucketFactory.Distinct] = *compiledExpr
uniqExprCacheLock.Unlock()
}
u.KeyCache = make(map[string]bool)
return err
return nil
}

// getElement computes a string from an event and a filter
Expand Down

0 comments on commit 6827f06

Please sign in to comment.