fix: Better test for group ID in filename (#2565)

This fixes an issue where filenames containing a period that aren't a
group ID, such as some-jar.12.jar, would be mistakenly be reported as
having the name "12" by syft, instead of the name "some-jar.12".

It works by testing whether the parts of the filename split on "."
are all valid Java identifiers.

Signed-off-by: Will Murphy <will.murphy@anchore.com>
This commit is contained in:
William Murphy 2024-01-31 08:21:33 -05:00 committed by GitHub
parent aa702a72b4
commit 31e0fc36e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 1 deletions

View File

@ -6,6 +6,7 @@ import (
"io" "io"
"strconv" "strconv"
"strings" "strings"
"unicode"
"github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg"
@ -162,13 +163,40 @@ func extractNameFromArchiveFilename(a archiveFilename) string {
return a.name return a.name
} }
// Maybe the filename is like groupid + . + artifactid. If so, return artifact id.
fields := strings.Split(a.name, ".") fields := strings.Split(a.name, ".")
return fields[len(fields)-1] maybeGroupID := true
for _, f := range fields {
if !isValidJavaIdentifier(f) {
maybeGroupID = false
break
}
}
if maybeGroupID {
return fields[len(fields)-1]
}
} }
return a.name return a.name
} }
func isValidJavaIdentifier(field string) bool {
runes := []rune(field)
if len(runes) == 0 {
return false
}
// check whether first rune can start an identifier name in Java
// Java identifier start = [Lu]|[Ll]|[Lt]|[Lm]|[Lo]|[Nl]|[Sc]|[Pc]
// see https://developer.classpath.org/doc/java/lang/Character-source.html
// line 3295
r := runes[0]
return unicode.Is(unicode.Lu, r) ||
unicode.Is(unicode.Ll, r) || unicode.Is(unicode.Lt, r) ||
unicode.Is(unicode.Lm, r) || unicode.Is(unicode.Lo, r) ||
unicode.Is(unicode.Nl, r) ||
unicode.Is(unicode.Sc, r) || unicode.Is(unicode.Pc, r)
}
func selectName(manifest *pkg.JavaManifest, filenameObj archiveFilename) string { func selectName(manifest *pkg.JavaManifest, filenameObj archiveFilename) string {
name := extractNameFromApacheMavenBundlePlugin(manifest) name := extractNameFromApacheMavenBundlePlugin(manifest)
if name != "" { if name != "" {

View File

@ -209,6 +209,22 @@ func TestSelectName(t *testing.T) {
archive: newJavaArchiveFilename("/something/com.atlassian.gadgets.atlassian-gadgets-api.jar"), archive: newJavaArchiveFilename("/something/com.atlassian.gadgets.atlassian-gadgets-api.jar"),
expected: "atlassian-gadgets-api", expected: "atlassian-gadgets-api",
}, },
{
desc: "Filename has period that is not groupid + artifact id",
manifest: pkg.JavaManifest{
Main: map[string]string{},
},
archive: newJavaArchiveFilename("/something/http4s-crypto_2.12-0.1.0.jar"),
expected: "http4s-crypto_2.12",
},
{
desc: "Filename has period that is not groupid + artifact id, kafka",
manifest: pkg.JavaManifest{
Main: map[string]string{},
},
archive: newJavaArchiveFilename("/something//kafka_2.13-3.2.2.jar"),
expected: "kafka_2.13", // see https://mvnrepository.com/artifact/org.apache.kafka/kafka_2.13/3.2.2
},
{ {
desc: "Skip stripping groupId prefix from archive filename for org.eclipse", desc: "Skip stripping groupId prefix from archive filename for org.eclipse",
manifest: pkg.JavaManifest{ manifest: pkg.JavaManifest{