neverallow.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. // Copyright 2017 Google Inc. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package android
  15. import (
  16. "fmt"
  17. "path/filepath"
  18. "reflect"
  19. "regexp"
  20. "strconv"
  21. "strings"
  22. "github.com/google/blueprint/proptools"
  23. )
  24. // "neverallow" rules for the build system.
  25. //
  26. // This allows things which aren't related to the build system and are enforced
  27. // against assumptions, in progress code refactors, or policy to be expressed in a
  28. // straightforward away disjoint from implementations and tests which should
  29. // work regardless of these restrictions.
  30. //
  31. // A module is disallowed if all of the following are true:
  32. // - it is in one of the "In" paths
  33. // - it is not in one of the "NotIn" paths
  34. // - it has all "With" properties matched
  35. // - - values are matched in their entirety
  36. // - - nil is interpreted as an empty string
  37. // - - nested properties are separated with a '.'
  38. // - - if the property is a list, any of the values in the list being matches
  39. // counts as a match
  40. // - it has none of the "Without" properties matched (same rules as above)
  41. func registerNeverallowMutator(ctx RegisterMutatorsContext) {
  42. ctx.BottomUp("neverallow", neverallowMutator).Parallel()
  43. }
  44. var neverallows = []Rule{}
  45. func init() {
  46. AddNeverAllowRules(createIncludeDirsRules()...)
  47. AddNeverAllowRules(createTrebleRules()...)
  48. AddNeverAllowRules(createJavaDeviceForHostRules()...)
  49. AddNeverAllowRules(createCcSdkVariantRules()...)
  50. AddNeverAllowRules(createUncompressDexRules()...)
  51. AddNeverAllowRules(createMakefileGoalRules()...)
  52. AddNeverAllowRules(createInitFirstStageRules()...)
  53. AddNeverAllowRules(createProhibitFrameworkAccessRules()...)
  54. }
  55. // Add a NeverAllow rule to the set of rules to apply.
  56. func AddNeverAllowRules(rules ...Rule) {
  57. neverallows = append(neverallows, rules...)
  58. }
  59. func createIncludeDirsRules() []Rule {
  60. notInIncludeDir := []string{
  61. "art",
  62. "art/libnativebridge",
  63. "art/libnativeloader",
  64. "libcore",
  65. "libnativehelper",
  66. "external/apache-harmony",
  67. "external/apache-xml",
  68. "external/boringssl",
  69. "external/bouncycastle",
  70. "external/conscrypt",
  71. "external/icu",
  72. "external/okhttp",
  73. "external/vixl",
  74. "external/wycheproof",
  75. }
  76. noUseIncludeDir := []string{
  77. "frameworks/av/apex",
  78. "frameworks/av/tools",
  79. "frameworks/native/cmds",
  80. "system/apex",
  81. "system/bpf",
  82. "system/gatekeeper",
  83. "system/hwservicemanager",
  84. "system/libbase",
  85. "system/libfmq",
  86. "system/libvintf",
  87. }
  88. rules := make([]Rule, 0, len(notInIncludeDir)+len(noUseIncludeDir))
  89. for _, path := range notInIncludeDir {
  90. rule :=
  91. NeverAllow().
  92. WithMatcher("include_dirs", StartsWith(path+"/")).
  93. Because("include_dirs is deprecated, all usages of '" + path + "' have been migrated" +
  94. " to use alternate mechanisms and so can no longer be used.")
  95. rules = append(rules, rule)
  96. }
  97. for _, path := range noUseIncludeDir {
  98. rule := NeverAllow().In(path+"/").WithMatcher("include_dirs", isSetMatcherInstance).
  99. Because("include_dirs is deprecated, all usages of them in '" + path + "' have been migrated" +
  100. " to use alternate mechanisms and so can no longer be used.")
  101. rules = append(rules, rule)
  102. }
  103. return rules
  104. }
  105. func createTrebleRules() []Rule {
  106. return []Rule{
  107. NeverAllow().
  108. In("vendor", "device").
  109. With("vndk.enabled", "true").
  110. Without("vendor", "true").
  111. Without("product_specific", "true").
  112. Because("the VNDK can never contain a library that is device dependent."),
  113. NeverAllow().
  114. With("vndk.enabled", "true").
  115. Without("vendor", "true").
  116. Without("owner", "").
  117. Because("a VNDK module can never have an owner."),
  118. // TODO(b/67974785): always enforce the manifest
  119. NeverAllow().
  120. Without("name", "libhidlbase-combined-impl").
  121. Without("name", "libhidlbase").
  122. With("product_variables.enforce_vintf_manifest.cflags", "*").
  123. Because("manifest enforcement should be independent of ."),
  124. // TODO(b/67975799): vendor code should always use /vendor/bin/sh
  125. NeverAllow().
  126. Without("name", "libc_bionic_ndk").
  127. With("product_variables.treble_linker_namespaces.cflags", "*").
  128. Because("nothing should care if linker namespaces are enabled or not"),
  129. // Example:
  130. // *NeverAllow().with("Srcs", "main.cpp"))
  131. }
  132. }
  133. func createJavaDeviceForHostRules() []Rule {
  134. javaDeviceForHostProjectsAllowedList := []string{
  135. "development/build",
  136. "external/guava",
  137. "external/robolectric-shadows",
  138. "frameworks/layoutlib",
  139. }
  140. return []Rule{
  141. NeverAllow().
  142. NotIn(javaDeviceForHostProjectsAllowedList...).
  143. ModuleType("java_device_for_host", "java_host_for_device").
  144. Because("java_device_for_host can only be used in allowed projects"),
  145. }
  146. }
  147. func createCcSdkVariantRules() []Rule {
  148. sdkVersionOnlyAllowedList := []string{
  149. // derive_sdk_prefer32 has stem: "derive_sdk" which conflicts with the derive_sdk.
  150. // This sometimes works because the APEX modules that contain derive_sdk and
  151. // derive_sdk_prefer32 suppress the platform installation rules, but fails when
  152. // the APEX modules contain the SDK variant and the platform variant still exists.
  153. "packages/modules/SdkExtensions/derive_sdk",
  154. // These are for apps and shouldn't be used by non-SDK variant modules.
  155. "prebuilts/ndk",
  156. "tools/test/graphicsbenchmark/apps/sample_app",
  157. "tools/test/graphicsbenchmark/functional_tests/java",
  158. "vendor/xts/gts-tests/hostsidetests/gamedevicecert/apps/javatests",
  159. "external/libtextclassifier/native",
  160. }
  161. platformVariantPropertiesAllowedList := []string{
  162. // android_native_app_glue and libRSSupport use native_window.h but target old
  163. // sdk versions (minimum and 9 respectively) where libnativewindow didn't exist,
  164. // so they can't add libnativewindow to shared_libs to get the header directory
  165. // for the platform variant. Allow them to use the platform variant
  166. // property to set shared_libs.
  167. "prebuilts/ndk",
  168. "frameworks/rs",
  169. }
  170. return []Rule{
  171. NeverAllow().
  172. NotIn(sdkVersionOnlyAllowedList...).
  173. WithMatcher("sdk_variant_only", isSetMatcherInstance).
  174. Because("sdk_variant_only can only be used in allowed projects"),
  175. NeverAllow().
  176. NotIn(platformVariantPropertiesAllowedList...).
  177. WithMatcher("platform.shared_libs", isSetMatcherInstance).
  178. Because("platform variant properties can only be used in allowed projects"),
  179. }
  180. }
  181. func createUncompressDexRules() []Rule {
  182. return []Rule{
  183. NeverAllow().
  184. NotIn("art").
  185. WithMatcher("uncompress_dex", isSetMatcherInstance).
  186. Because("uncompress_dex is only allowed for certain jars for test in art."),
  187. }
  188. }
  189. func createMakefileGoalRules() []Rule {
  190. return []Rule{
  191. NeverAllow().
  192. ModuleType("makefile_goal").
  193. WithoutMatcher("product_out_path", Regexp("^boot[0-9a-zA-Z.-]*[.]img$")).
  194. Because("Only boot images may be imported as a makefile goal."),
  195. }
  196. }
  197. func createInitFirstStageRules() []Rule {
  198. return []Rule{
  199. NeverAllow().
  200. Without("name", "init_first_stage").
  201. With("install_in_root", "true").
  202. Because("install_in_root is only for init_first_stage."),
  203. }
  204. }
  205. func createProhibitFrameworkAccessRules() []Rule {
  206. return []Rule{
  207. NeverAllow().
  208. With("libs", "framework").
  209. WithoutMatcher("sdk_version", Regexp("(core_.*|^$)")).
  210. Because("framework can't be used when building against SDK"),
  211. }
  212. }
  213. func neverallowMutator(ctx BottomUpMutatorContext) {
  214. m, ok := ctx.Module().(Module)
  215. if !ok {
  216. return
  217. }
  218. dir := ctx.ModuleDir() + "/"
  219. properties := m.GetProperties()
  220. osClass := ctx.Module().Target().Os.Class
  221. for _, r := range neverallowRules(ctx.Config()) {
  222. n := r.(*rule)
  223. if !n.appliesToPath(dir) {
  224. continue
  225. }
  226. if !n.appliesToModuleType(ctx.ModuleType()) {
  227. continue
  228. }
  229. if !n.appliesToProperties(properties) {
  230. continue
  231. }
  232. if !n.appliesToOsClass(osClass) {
  233. continue
  234. }
  235. if !n.appliesToDirectDeps(ctx) {
  236. continue
  237. }
  238. ctx.ModuleErrorf("violates " + n.String())
  239. }
  240. }
  241. type ValueMatcher interface {
  242. Test(string) bool
  243. String() string
  244. }
  245. type equalMatcher struct {
  246. expected string
  247. }
  248. func (m *equalMatcher) Test(value string) bool {
  249. return m.expected == value
  250. }
  251. func (m *equalMatcher) String() string {
  252. return "=" + m.expected
  253. }
  254. type anyMatcher struct {
  255. }
  256. func (m *anyMatcher) Test(value string) bool {
  257. return true
  258. }
  259. func (m *anyMatcher) String() string {
  260. return "=*"
  261. }
  262. var anyMatcherInstance = &anyMatcher{}
  263. type startsWithMatcher struct {
  264. prefix string
  265. }
  266. func (m *startsWithMatcher) Test(value string) bool {
  267. return strings.HasPrefix(value, m.prefix)
  268. }
  269. func (m *startsWithMatcher) String() string {
  270. return ".starts-with(" + m.prefix + ")"
  271. }
  272. type regexMatcher struct {
  273. re *regexp.Regexp
  274. }
  275. func (m *regexMatcher) Test(value string) bool {
  276. return m.re.MatchString(value)
  277. }
  278. func (m *regexMatcher) String() string {
  279. return ".regexp(" + m.re.String() + ")"
  280. }
  281. type notInListMatcher struct {
  282. allowed []string
  283. }
  284. func (m *notInListMatcher) Test(value string) bool {
  285. return !InList(value, m.allowed)
  286. }
  287. func (m *notInListMatcher) String() string {
  288. return ".not-in-list(" + strings.Join(m.allowed, ",") + ")"
  289. }
  290. type isSetMatcher struct{}
  291. func (m *isSetMatcher) Test(value string) bool {
  292. return value != ""
  293. }
  294. func (m *isSetMatcher) String() string {
  295. return ".is-set"
  296. }
  297. var isSetMatcherInstance = &isSetMatcher{}
  298. type ruleProperty struct {
  299. fields []string // e.x.: Vndk.Enabled
  300. matcher ValueMatcher
  301. }
  302. func (r *ruleProperty) String() string {
  303. return fmt.Sprintf("%q matches: %s", strings.Join(r.fields, "."), r.matcher)
  304. }
  305. type ruleProperties []ruleProperty
  306. func (r ruleProperties) String() string {
  307. var s []string
  308. for _, r := range r {
  309. s = append(s, r.String())
  310. }
  311. return strings.Join(s, " ")
  312. }
  313. // A NeverAllow rule.
  314. type Rule interface {
  315. In(path ...string) Rule
  316. NotIn(path ...string) Rule
  317. InDirectDeps(deps ...string) Rule
  318. WithOsClass(osClasses ...OsClass) Rule
  319. ModuleType(types ...string) Rule
  320. NotModuleType(types ...string) Rule
  321. With(properties, value string) Rule
  322. WithMatcher(properties string, matcher ValueMatcher) Rule
  323. Without(properties, value string) Rule
  324. WithoutMatcher(properties string, matcher ValueMatcher) Rule
  325. Because(reason string) Rule
  326. }
  327. type rule struct {
  328. // User string for why this is a thing.
  329. reason string
  330. paths []string
  331. unlessPaths []string
  332. directDeps map[string]bool
  333. osClasses []OsClass
  334. moduleTypes []string
  335. unlessModuleTypes []string
  336. props ruleProperties
  337. unlessProps ruleProperties
  338. onlyBootclasspathJar bool
  339. }
  340. // Create a new NeverAllow rule.
  341. func NeverAllow() Rule {
  342. return &rule{directDeps: make(map[string]bool)}
  343. }
  344. // In adds path(s) where this rule applies.
  345. func (r *rule) In(path ...string) Rule {
  346. r.paths = append(r.paths, cleanPaths(path)...)
  347. return r
  348. }
  349. // NotIn adds path(s) to that this rule does not apply to.
  350. func (r *rule) NotIn(path ...string) Rule {
  351. r.unlessPaths = append(r.unlessPaths, cleanPaths(path)...)
  352. return r
  353. }
  354. // InDirectDeps adds dep(s) that are not allowed with this rule.
  355. func (r *rule) InDirectDeps(deps ...string) Rule {
  356. for _, d := range deps {
  357. r.directDeps[d] = true
  358. }
  359. return r
  360. }
  361. // WithOsClass adds osClass(es) that this rule applies to.
  362. func (r *rule) WithOsClass(osClasses ...OsClass) Rule {
  363. r.osClasses = append(r.osClasses, osClasses...)
  364. return r
  365. }
  366. // ModuleType adds type(s) that this rule applies to.
  367. func (r *rule) ModuleType(types ...string) Rule {
  368. r.moduleTypes = append(r.moduleTypes, types...)
  369. return r
  370. }
  371. // NotModuleType adds type(s) that this rule does not apply to..
  372. func (r *rule) NotModuleType(types ...string) Rule {
  373. r.unlessModuleTypes = append(r.unlessModuleTypes, types...)
  374. return r
  375. }
  376. // With specifies property/value combinations that are restricted for this rule.
  377. func (r *rule) With(properties, value string) Rule {
  378. return r.WithMatcher(properties, selectMatcher(value))
  379. }
  380. // WithMatcher specifies property/matcher combinations that are restricted for this rule.
  381. func (r *rule) WithMatcher(properties string, matcher ValueMatcher) Rule {
  382. r.props = append(r.props, ruleProperty{
  383. fields: fieldNamesForProperties(properties),
  384. matcher: matcher,
  385. })
  386. return r
  387. }
  388. // Without specifies property/value combinations that this rule does not apply to.
  389. func (r *rule) Without(properties, value string) Rule {
  390. return r.WithoutMatcher(properties, selectMatcher(value))
  391. }
  392. // Without specifies property/matcher combinations that this rule does not apply to.
  393. func (r *rule) WithoutMatcher(properties string, matcher ValueMatcher) Rule {
  394. r.unlessProps = append(r.unlessProps, ruleProperty{
  395. fields: fieldNamesForProperties(properties),
  396. matcher: matcher,
  397. })
  398. return r
  399. }
  400. func selectMatcher(expected string) ValueMatcher {
  401. if expected == "*" {
  402. return anyMatcherInstance
  403. }
  404. return &equalMatcher{expected: expected}
  405. }
  406. // Because specifies a reason for this rule.
  407. func (r *rule) Because(reason string) Rule {
  408. r.reason = reason
  409. return r
  410. }
  411. func (r *rule) String() string {
  412. s := []string{"neverallow requirements. Not allowed:"}
  413. if len(r.paths) > 0 {
  414. s = append(s, fmt.Sprintf("in dirs: %q", r.paths))
  415. }
  416. if len(r.moduleTypes) > 0 {
  417. s = append(s, fmt.Sprintf("module types: %q", r.moduleTypes))
  418. }
  419. if len(r.props) > 0 {
  420. s = append(s, fmt.Sprintf("properties matching: %s", r.props))
  421. }
  422. if len(r.directDeps) > 0 {
  423. s = append(s, fmt.Sprintf("dep(s): %q", SortedStringKeys(r.directDeps)))
  424. }
  425. if len(r.osClasses) > 0 {
  426. s = append(s, fmt.Sprintf("os class(es): %q", r.osClasses))
  427. }
  428. if len(r.unlessPaths) > 0 {
  429. s = append(s, fmt.Sprintf("EXCEPT in dirs: %q", r.unlessPaths))
  430. }
  431. if len(r.unlessModuleTypes) > 0 {
  432. s = append(s, fmt.Sprintf("EXCEPT module types: %q", r.unlessModuleTypes))
  433. }
  434. if len(r.unlessProps) > 0 {
  435. s = append(s, fmt.Sprintf("EXCEPT properties matching: %q", r.unlessProps))
  436. }
  437. if len(r.reason) != 0 {
  438. s = append(s, " which is restricted because "+r.reason)
  439. }
  440. if len(s) == 1 {
  441. s[0] = "neverallow requirements (empty)"
  442. }
  443. return strings.Join(s, "\n\t")
  444. }
  445. func (r *rule) appliesToPath(dir string) bool {
  446. includePath := len(r.paths) == 0 || HasAnyPrefix(dir, r.paths)
  447. excludePath := HasAnyPrefix(dir, r.unlessPaths)
  448. return includePath && !excludePath
  449. }
  450. func (r *rule) appliesToDirectDeps(ctx BottomUpMutatorContext) bool {
  451. if len(r.directDeps) == 0 {
  452. return true
  453. }
  454. matches := false
  455. ctx.VisitDirectDeps(func(m Module) {
  456. if !matches {
  457. name := ctx.OtherModuleName(m)
  458. matches = r.directDeps[name]
  459. }
  460. })
  461. return matches
  462. }
  463. func (r *rule) appliesToOsClass(osClass OsClass) bool {
  464. if len(r.osClasses) == 0 {
  465. return true
  466. }
  467. for _, c := range r.osClasses {
  468. if c == osClass {
  469. return true
  470. }
  471. }
  472. return false
  473. }
  474. func (r *rule) appliesToModuleType(moduleType string) bool {
  475. return (len(r.moduleTypes) == 0 || InList(moduleType, r.moduleTypes)) && !InList(moduleType, r.unlessModuleTypes)
  476. }
  477. func (r *rule) appliesToProperties(properties []interface{}) bool {
  478. includeProps := hasAllProperties(properties, r.props)
  479. excludeProps := hasAnyProperty(properties, r.unlessProps)
  480. return includeProps && !excludeProps
  481. }
  482. func StartsWith(prefix string) ValueMatcher {
  483. return &startsWithMatcher{prefix}
  484. }
  485. func Regexp(re string) ValueMatcher {
  486. r, err := regexp.Compile(re)
  487. if err != nil {
  488. panic(err)
  489. }
  490. return &regexMatcher{r}
  491. }
  492. func NotInList(allowed []string) ValueMatcher {
  493. return &notInListMatcher{allowed}
  494. }
  495. // assorted utils
  496. func cleanPaths(paths []string) []string {
  497. res := make([]string, len(paths))
  498. for i, v := range paths {
  499. res[i] = filepath.Clean(v) + "/"
  500. }
  501. return res
  502. }
  503. func fieldNamesForProperties(propertyNames string) []string {
  504. names := strings.Split(propertyNames, ".")
  505. for i, v := range names {
  506. names[i] = proptools.FieldNameForProperty(v)
  507. }
  508. return names
  509. }
  510. func hasAnyProperty(properties []interface{}, props []ruleProperty) bool {
  511. for _, v := range props {
  512. if hasProperty(properties, v) {
  513. return true
  514. }
  515. }
  516. return false
  517. }
  518. func hasAllProperties(properties []interface{}, props []ruleProperty) bool {
  519. for _, v := range props {
  520. if !hasProperty(properties, v) {
  521. return false
  522. }
  523. }
  524. return true
  525. }
  526. func hasProperty(properties []interface{}, prop ruleProperty) bool {
  527. for _, propertyStruct := range properties {
  528. propertiesValue := reflect.ValueOf(propertyStruct).Elem()
  529. for _, v := range prop.fields {
  530. if !propertiesValue.IsValid() {
  531. break
  532. }
  533. propertiesValue = propertiesValue.FieldByName(v)
  534. }
  535. if !propertiesValue.IsValid() {
  536. continue
  537. }
  538. check := func(value string) bool {
  539. return prop.matcher.Test(value)
  540. }
  541. if matchValue(propertiesValue, check) {
  542. return true
  543. }
  544. }
  545. return false
  546. }
  547. func matchValue(value reflect.Value, check func(string) bool) bool {
  548. if !value.IsValid() {
  549. return false
  550. }
  551. if value.Kind() == reflect.Ptr {
  552. if value.IsNil() {
  553. return check("")
  554. }
  555. value = value.Elem()
  556. }
  557. switch value.Kind() {
  558. case reflect.String:
  559. return check(value.String())
  560. case reflect.Bool:
  561. return check(strconv.FormatBool(value.Bool()))
  562. case reflect.Int:
  563. return check(strconv.FormatInt(value.Int(), 10))
  564. case reflect.Slice:
  565. slice, ok := value.Interface().([]string)
  566. if !ok {
  567. panic("Can only handle slice of string")
  568. }
  569. for _, v := range slice {
  570. if check(v) {
  571. return true
  572. }
  573. }
  574. return false
  575. }
  576. panic("Can't handle type: " + value.Kind().String())
  577. }
  578. var neverallowRulesKey = NewOnceKey("neverallowRules")
  579. func neverallowRules(config Config) []Rule {
  580. return config.Once(neverallowRulesKey, func() interface{} {
  581. // No test rules were set by setTestNeverallowRules, use the global rules
  582. return neverallows
  583. }).([]Rule)
  584. }
  585. // Overrides the default neverallow rules for the supplied config.
  586. //
  587. // For testing only.
  588. func setTestNeverallowRules(config Config, testRules []Rule) {
  589. config.Once(neverallowRulesKey, func() interface{} { return testRules })
  590. }
  591. // Prepares for a test by setting neverallow rules and enabling the mutator.
  592. //
  593. // If the supplied rules are nil then the default rules are used.
  594. func PrepareForTestWithNeverallowRules(testRules []Rule) FixturePreparer {
  595. return GroupFixturePreparers(
  596. FixtureModifyConfig(func(config Config) {
  597. if testRules != nil {
  598. setTestNeverallowRules(config, testRules)
  599. }
  600. }),
  601. FixtureRegisterWithContext(func(ctx RegistrationContext) {
  602. ctx.PostDepsMutators(registerNeverallowMutator)
  603. }),
  604. )
  605. }