mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01:00
Handle extra empty lines in Java manifest parsing (#687)
* Add failing test for extra empty lines in manifest Signed-off-by: Dan Luhring <dan+github@luhrings.com> * Handle extra empty lines in Java manifests Signed-off-by: Dan Luhring <dan+github@luhrings.com>
This commit is contained in:
parent
3d8c16649d
commit
85ac5bcbf8
@ -19,48 +19,60 @@ const manifestGlob = "/META-INF/MANIFEST.MF"
|
|||||||
// For more information: https://docs.oracle.com/en/java/javase/11/docs/specs/jar/jar.html#jar-manifest
|
// For more information: https://docs.oracle.com/en/java/javase/11/docs/specs/jar/jar.html#jar-manifest
|
||||||
func parseJavaManifest(path string, reader io.Reader) (*pkg.JavaManifest, error) {
|
func parseJavaManifest(path string, reader io.Reader) (*pkg.JavaManifest, error) {
|
||||||
var manifest pkg.JavaManifest
|
var manifest pkg.JavaManifest
|
||||||
sections := []map[string]string{
|
var sections []map[string]string
|
||||||
make(map[string]string),
|
|
||||||
|
currentSection := func() int {
|
||||||
|
return len(sections) - 1
|
||||||
}
|
}
|
||||||
currentSection := 0
|
|
||||||
scanner := bufio.NewScanner(reader)
|
|
||||||
var lastKey string
|
var lastKey string
|
||||||
|
scanner := bufio.NewScanner(reader)
|
||||||
|
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
line := scanner.Text()
|
line := scanner.Text()
|
||||||
|
|
||||||
// empty lines denote section separators
|
// empty lines denote section separators
|
||||||
if strings.TrimSpace(line) == "" {
|
if strings.TrimSpace(line) == "" {
|
||||||
currentSection++
|
// we don't want to allocate a new section map that won't necessarily be used, do that once there is
|
||||||
// we don't want to allocate a new section map that wont necessarily be used, do that once there is
|
|
||||||
// a non-empty line to process
|
// a non-empty line to process
|
||||||
|
|
||||||
// do not process line continuations after this
|
// do not process line continuations after this
|
||||||
lastKey = ""
|
lastKey = ""
|
||||||
|
|
||||||
continue
|
continue
|
||||||
} else if currentSection >= len(sections) {
|
|
||||||
sections = append(sections, make(map[string]string))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if line[0] == ' ' {
|
if line[0] == ' ' {
|
||||||
// this is a continuation
|
// this is a continuation
|
||||||
|
|
||||||
if lastKey == "" {
|
if lastKey == "" {
|
||||||
return nil, fmt.Errorf("found continuation with no previous key (%s)", line)
|
return nil, fmt.Errorf("found continuation with no previous key (%s)", line)
|
||||||
}
|
}
|
||||||
sections[currentSection][lastKey] += strings.TrimSpace(line)
|
|
||||||
} else {
|
|
||||||
// this is a new key-value pair
|
|
||||||
idx := strings.Index(line, ":")
|
|
||||||
if idx == -1 {
|
|
||||||
return nil, fmt.Errorf("unable to split java manifest key-value pairs: %q", line)
|
|
||||||
}
|
|
||||||
|
|
||||||
key := strings.TrimSpace(line[0:idx])
|
sections[currentSection()][lastKey] += strings.TrimSpace(line)
|
||||||
value := strings.TrimSpace(line[idx+1:])
|
|
||||||
sections[currentSection][key] = value
|
|
||||||
|
|
||||||
// keep track of key for potential future continuations
|
continue
|
||||||
lastKey = key
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if lastKey == "" {
|
||||||
|
// we're entering a new section
|
||||||
|
|
||||||
|
sections = append(sections, make(map[string]string))
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is a new key-value pair
|
||||||
|
idx := strings.Index(line, ":")
|
||||||
|
if idx == -1 {
|
||||||
|
return nil, fmt.Errorf("unable to split java manifest key-value pairs: %q", line)
|
||||||
|
}
|
||||||
|
|
||||||
|
key := strings.TrimSpace(line[0:idx])
|
||||||
|
value := strings.TrimSpace(line[idx+1:])
|
||||||
|
|
||||||
|
sections[currentSection()][key] = value
|
||||||
|
|
||||||
|
// keep track of key for potential future continuations
|
||||||
|
lastKey = key
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
if err := scanner.Err(); err != nil {
|
||||||
@ -75,7 +87,7 @@ func parseJavaManifest(path string, reader io.Reader) (*pkg.JavaManifest, error)
|
|||||||
name, ok := s["Name"]
|
name, ok := s["Name"]
|
||||||
if !ok {
|
if !ok {
|
||||||
// per the manifest spec (https://docs.oracle.com/en/java/javase/11/docs/specs/jar/jar.html#jar-manifest)
|
// per the manifest spec (https://docs.oracle.com/en/java/javase/11/docs/specs/jar/jar.html#jar-manifest)
|
||||||
// this should never happen. If it does we want to know about it, but not necessarily stop
|
// this should never happen. If it does, we want to know about it, but not necessarily stop
|
||||||
// cataloging entirely... for this reason we only log.
|
// cataloging entirely... for this reason we only log.
|
||||||
log.Warnf("java manifest section found without a name: %s", path)
|
log.Warnf("java manifest section found without a name: %s", path)
|
||||||
name = strconv.Itoa(i)
|
name = strconv.Itoa(i)
|
||||||
|
|||||||
@ -58,6 +58,21 @@ func TestParseJavaManifest(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
fixture: "test-fixtures/manifest/extra-empty-lines",
|
||||||
|
expected: pkg.JavaManifest{
|
||||||
|
Main: map[string]string{
|
||||||
|
"Manifest-Version": "1.0",
|
||||||
|
"Archiver-Version": "Plexus Archiver",
|
||||||
|
"Created-By": "Apache Maven 3.6.3",
|
||||||
|
},
|
||||||
|
NamedSections: map[string]map[string]string{
|
||||||
|
"thing-1": {
|
||||||
|
"Built-By": "?",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fixture: "test-fixtures/manifest/continuation",
|
fixture: "test-fixtures/manifest/continuation",
|
||||||
expected: pkg.JavaManifest{
|
expected: pkg.JavaManifest{
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Archiver-Version: Plexus Archiver
|
||||||
|
Created-By: Apache Maven 3.6.3
|
||||||
|
|
||||||
|
|
||||||
|
Name: thing-1
|
||||||
|
Built-By: ?
|
||||||
Loading…
x
Reference in New Issue
Block a user