github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/pkg/subsystem/match.go (about)

     1  // Copyright 2023 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  package subsystem
     5  
     6  import (
     7  	"maps"
     8  	"regexp"
     9  	"slices"
    10  	"strings"
    11  )
    12  
    13  type PathMatcher struct {
    14  	matches []*match
    15  }
    16  
    17  type match struct {
    18  	include *regexp.Regexp
    19  	exclude *regexp.Regexp
    20  	object  *Subsystem
    21  }
    22  
    23  func MakePathMatcher(list []*Subsystem) *PathMatcher {
    24  	m := &PathMatcher{}
    25  	for _, item := range list {
    26  		m.register(item)
    27  	}
    28  	return m
    29  }
    30  
    31  func (p *PathMatcher) register(item *Subsystem) {
    32  	onlyInclude := []string{}
    33  	list := []PathRule{}
    34  	for _, r := range item.PathRules {
    35  		if r.ExcludeRegexp == "" {
    36  			// It's expected that almost everything will go to this branch.
    37  			onlyInclude = append(onlyInclude, r.IncludeRegexp)
    38  		} else {
    39  			list = append(list, r)
    40  		}
    41  	}
    42  	if len(onlyInclude) > 0 {
    43  		list = append(list, PathRule{
    44  			IncludeRegexp: strings.Join(onlyInclude, "|"),
    45  		})
    46  	}
    47  	for _, rule := range list {
    48  		p.matches = append(p.matches, buildMatch(rule, item))
    49  	}
    50  }
    51  
    52  func (p *PathMatcher) Match(path string) []*Subsystem {
    53  	ret := map[*Subsystem]struct{}{}
    54  	for _, m := range p.matches {
    55  		if m.exclude != nil && m.exclude.MatchString(path) {
    56  			continue
    57  		}
    58  		if m.include != nil && !m.include.MatchString(path) {
    59  			continue
    60  		}
    61  		ret[m.object] = struct{}{}
    62  	}
    63  	return slices.Collect(maps.Keys(ret))
    64  }
    65  
    66  func buildMatch(rule PathRule, item *Subsystem) *match {
    67  	m := &match{object: item}
    68  	if rule.IncludeRegexp != "" {
    69  		m.include = regexp.MustCompile(rule.IncludeRegexp)
    70  	}
    71  	if rule.ExcludeRegexp != "" {
    72  		m.exclude = regexp.MustCompile(rule.ExcludeRegexp)
    73  	}
    74  	return m
    75  }