neverallow.go 19 KB

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