Fix nondeterminisim in xmlnotice

SafePathPrefixes contains "prebuilts/" which is a prefix of another
entry "prebuilts/module_sdk" which can both match the same path.
SafePathPrefixes is a map, so the iteration order is nondeterminisitic.
Move both SafePathPrefixes and SafePrebuiltPrefixes into lists that
will always have a deterministic iteration order.

Bug: 230357391
Test: build NOTICE.xml.gz multiple times
Change-Id: Ibfcd6715b70f26164e0ef4d59f73b240f47f8db7
This commit is contained in:
Colin Cross
2022-09-28 15:36:53 -07:00
parent 7017ac77fd
commit 4b54525b2b
2 changed files with 43 additions and 58 deletions

View File

@@ -360,19 +360,17 @@ func (ni *NoticeIndex) getLibName(noticeFor *TargetNode, h hash) string {
continue continue
} }
} }
for _, r := range OrderedSafePrebuiltPrefixes { for _, safePrebuiltPrefix := range safePrebuiltPrefixes {
prefix := SafePrebuiltPrefixes[r] match := safePrebuiltPrefix.re.FindString(licenseText)
match := r.FindString(licenseText)
if len(match) == 0 { if len(match) == 0 {
continue continue
} }
strip := SafePathPrefixes[prefix] if safePrebuiltPrefix.strip {
if strip {
// strip entire prefix // strip entire prefix
match = licenseText[len(match):] match = licenseText[len(match):]
} else { } else {
// strip from prebuilts/ until safe prefix // strip from prebuilts/ until safe prefix
match = licenseText[len(match)-len(prefix):] match = licenseText[len(match)-len(safePrebuiltPrefix.prefix):]
} }
// remove LICENSE or NOTICE or other filename // remove LICENSE or NOTICE or other filename
li := strings.LastIndex(match, "/") li := strings.LastIndex(match, "/")
@@ -392,10 +390,10 @@ func (ni *NoticeIndex) getLibName(noticeFor *TargetNode, h hash) string {
break break
} }
} }
for prefix, strip := range SafePathPrefixes { for _, safePathPrefix := range safePathPrefixes {
if strings.HasPrefix(p, prefix) { if strings.HasPrefix(p, safePathPrefix.prefix) {
if strip { if safePathPrefix.strip {
return p[len(prefix):] return p[len(safePathPrefix.prefix):]
} else { } else {
return p return p
} }

View File

@@ -16,7 +16,6 @@ package compliance
import ( import (
"regexp" "regexp"
"sort"
"strings" "strings"
) )
@@ -30,35 +29,31 @@ var (
"toolchain": "toolchain", "toolchain": "toolchain",
} }
// SafePathPrefixes maps the path prefixes presumed not to contain any // safePathPrefixes maps the path prefixes presumed not to contain any
// proprietary or confidential pathnames to whether to strip the prefix // proprietary or confidential pathnames to whether to strip the prefix
// from the path when used as the library name for notices. // from the path when used as the library name for notices.
SafePathPrefixes = map[string]bool{ safePathPrefixes = []safePathPrefixesType{
"external/": true, {"external/", true},
"art/": false, {"art/", false},
"build/": false, {"build/", false},
"cts/": false, {"cts/", false},
"dalvik/": false, {"dalvik/", false},
"developers/": false, {"developers/", false},
"development/": false, {"development/", false},
"frameworks/": false, {"frameworks/", false},
"packages/": true, {"packages/", true},
"prebuilts/module_sdk/": true, {"prebuilts/module_sdk/", true},
"prebuilts/": false, {"prebuilts/", false},
"sdk/": false, {"sdk/", false},
"system/": false, {"system/", false},
"test/": false, {"test/", false},
"toolchain/": false, {"toolchain/", false},
"tools/": false, {"tools/", false},
} }
// SafePrebuiltPrefixes maps the regular expression to match a prebuilt // safePrebuiltPrefixes maps the regular expression to match a prebuilt
// containing the path of a safe prefix to the safe prefix. // containing the path of a safe prefix to the safe prefix.
SafePrebuiltPrefixes = make(map[*regexp.Regexp]string) safePrebuiltPrefixes []safePrebuiltPrefixesType
// OrderedSafePrebuiltPrefixes lists the SafePrebuiltPrefixes ordered by
// increasing length.
OrderedSafePrebuiltPrefixes = make([]*regexp.Regexp, 0, 0)
// ImpliesUnencumbered lists the condition names representing an author attempt to disclaim copyright. // ImpliesUnencumbered lists the condition names representing an author attempt to disclaim copyright.
ImpliesUnencumbered = LicenseConditionSet(UnencumberedCondition) ImpliesUnencumbered = LicenseConditionSet(UnencumberedCondition)
@@ -89,6 +84,16 @@ var (
ImpliesShared = LicenseConditionSet(ReciprocalCondition | RestrictedCondition | WeaklyRestrictedCondition) ImpliesShared = LicenseConditionSet(ReciprocalCondition | RestrictedCondition | WeaklyRestrictedCondition)
) )
type safePathPrefixesType struct {
prefix string
strip bool
}
type safePrebuiltPrefixesType struct {
safePathPrefixesType
re *regexp.Regexp
}
var ( var (
anyLgpl = regexp.MustCompile(`^SPDX-license-identifier-LGPL.*`) anyLgpl = regexp.MustCompile(`^SPDX-license-identifier-LGPL.*`)
versionedGpl = regexp.MustCompile(`^SPDX-license-identifier-GPL-\p{N}.*`) versionedGpl = regexp.MustCompile(`^SPDX-license-identifier-GPL-\p{N}.*`)
@@ -96,33 +101,15 @@ var (
ccBySa = regexp.MustCompile(`^SPDX-license-identifier-CC-BY.*-SA.*`) ccBySa = regexp.MustCompile(`^SPDX-license-identifier-CC-BY.*-SA.*`)
) )
// byIncreasingLength implements `sort.Interface` to order regular expressions by increasing length.
type byIncreasingLength []*regexp.Regexp
func (l byIncreasingLength) Len() int { return len(l) }
func (l byIncreasingLength) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
func (l byIncreasingLength) Less(i, j int) bool {
ri := l[i].String()
rj := l[j].String()
if len(ri) == len(rj) {
return ri < rj
}
return len(ri) < len(rj)
}
func init() { func init() {
for prefix := range SafePathPrefixes { for _, safePathPrefix := range safePathPrefixes {
if strings.HasPrefix(prefix, "prebuilts/") { if strings.HasPrefix(safePathPrefix.prefix, "prebuilts/") {
continue continue
} }
r := regexp.MustCompile("^prebuilts/(?:runtime/mainline/)?" + prefix) r := regexp.MustCompile("^prebuilts/(?:runtime/mainline/)?" + safePathPrefix.prefix)
SafePrebuiltPrefixes[r] = prefix safePrebuiltPrefixes = append(safePrebuiltPrefixes,
safePrebuiltPrefixesType{safePathPrefix, r})
} }
OrderedSafePrebuiltPrefixes = make([]*regexp.Regexp, 0, len(SafePrebuiltPrefixes))
for r := range SafePrebuiltPrefixes {
OrderedSafePrebuiltPrefixes = append(OrderedSafePrebuiltPrefixes, r)
}
sort.Sort(byIncreasingLength(OrderedSafePrebuiltPrefixes))
} }
// LicenseConditionSetFromNames returns a set containing the recognized `names` and // LicenseConditionSetFromNames returns a set containing the recognized `names` and