From 7ef939111ee795f0f6f1eb2c1d56e3b4bbcced73 Mon Sep 17 00:00:00 2001 From: Elliotte Rusty Harold Date: Thu, 2 Jul 2026 11:50:09 +0000 Subject: [PATCH 1/2] MSHARED-815: Sanitize newlines in manifest entry values Newlines (\\n, \\r\\n, \\r) in manifest entry values can produce invalid MANIFEST.MF files, particularly when empty lines create section separators. Replace all newline characters with spaces before storing values in manifest attributes. Applies sanitization in both addManifestAttribute() (for main manifest attributes) and the manifest section entries loop. Fixes #362 --- .../maven/shared/archiver/MavenArchiver.java | 16 ++++--- .../shared/archiver/MavenArchiverTest.java | 42 ++++++++++++++++++- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/apache/maven/shared/archiver/MavenArchiver.java b/src/main/java/org/apache/maven/shared/archiver/MavenArchiver.java index 7ab7740..6a2a5b4 100644 --- a/src/main/java/org/apache/maven/shared/archiver/MavenArchiver.java +++ b/src/main/java/org/apache/maven/shared/archiver/MavenArchiver.java @@ -164,7 +164,7 @@ public Manifest getManifest(Session session, Project project, MavenArchiveConfig for (Map.Entry entry : sectionEntries.entrySet()) { String key = entry.getKey(); - String value = entry.getValue(); + String value = sanitizeManifestValue(entry.getValue()); Manifest.Attribute attr = new Manifest.Attribute(key, value); theSection.addConfiguredAttribute(attr); } @@ -207,17 +207,23 @@ private void addManifestAttribute(Manifest manifest, Map map, St } private void addManifestAttribute(Manifest manifest, String key, String value) throws ManifestException { - if (!(value == null || value.isEmpty())) { - Manifest.Attribute attr = new Manifest.Attribute(key, value); + String sanitized = sanitizeManifestValue(value); + if (!(sanitized == null || sanitized.isEmpty())) { + Manifest.Attribute attr = new Manifest.Attribute(key, sanitized); manifest.addConfiguredAttribute(attr); } else { - // if the value is empty, create an entry with an empty string - // to prevent null print in the manifest file Manifest.Attribute attr = new Manifest.Attribute(key, ""); manifest.addConfiguredAttribute(attr); } } + private static String sanitizeManifestValue(String value) { + if (value == null) { + return null; + } + return value.replace("\r\n", " ").replace('\r', ' ').replace('\n', ' '); + } + /** *

getManifest.

* diff --git a/src/test/java/org/apache/maven/shared/archiver/MavenArchiverTest.java b/src/test/java/org/apache/maven/shared/archiver/MavenArchiverTest.java index 2419bda..bf63723 100644 --- a/src/test/java/org/apache/maven/shared/archiver/MavenArchiverTest.java +++ b/src/test/java/org/apache/maven/shared/archiver/MavenArchiverTest.java @@ -314,8 +314,6 @@ void carriageReturnInManifestEntry() throws Exception { config.setForced(true); config.getManifest().setAddDefaultImplementationEntries(true); config.addManifestEntry("Description", project.getModel().getDescription()); - // config.addManifestEntry( "EntryWithTab", " foo tab " + ( '\u0009' ) + ( '\u0009' ) // + " bar tab" + ( // - // '\u0009' // ) ); archiver.createArchive(session, project, config); assertThat(jarFile).exists(); @@ -328,6 +326,46 @@ void carriageReturnInManifestEntry() throws Exception { assertThat(value.indexOf(ls)).isLessThanOrEqualTo(0); } + @Test + void newlinesInManifestEntryGetReplacedWithSpaces() throws Exception { + ProjectStub project = getDummyProject(); + + MavenArchiveConfiguration config = new MavenArchiveConfiguration(); + config.addManifestEntry("MultiLine", "line1\nline2\nline3"); + config.addManifestEntry("WithCRLF", "line1\r\nline2"); + config.addManifestEntry("WithTrailingNewline", "trailing\n"); + + MavenArchiver archiver = new MavenArchiver(); + Manifest manifest = archiver.getManifest(session, project, config); + Attributes attributes = manifest.getMainAttributes(); + + assertThat(attributes.getValue("MultiLine")).isEqualTo("line1 line2 line3"); + assertThat(attributes.getValue("WithCRLF")).isEqualTo("line1 line2"); + assertThat(attributes.getValue("WithTrailingNewline")).doesNotContain("\n"); + } + + @Test + void manifestEntryWithEmptyLinesDoesNotCorruptManifest() throws Exception { + File jarFile = new File("target/test/dummy.jar"); + JarArchiver jarArchiver = getCleanJarArchiver(jarFile); + + MavenArchiver archiver = getMavenArchiver(jarArchiver); + + ProjectStub project = getDummyProject(); + MavenArchiveConfiguration config = new MavenArchiveConfiguration(); + config.setForced(true); + config.addManifestEntry("WithEmptyLine", "para1\n\npara3"); + config.addManifestEntry("Normal", "value"); + + archiver.createArchive(session, project, config); + assertThat(jarFile).exists(); + + Manifest manifest = getJarFileManifest(jarFile); + Attributes attributes = manifest.getMainAttributes(); + assertThat(attributes.getValue("WithEmptyLine")).isEqualTo("para1 para3"); + assertThat(attributes.getValue("Normal")).isEqualTo("value"); + } + @Test void deprecatedCreateArchiveAPI() throws Exception { File jarFile = new File("target/test/dummy.jar"); From 4ac611827c00f235c527d4f55db584edfadced43 Mon Sep 17 00:00:00 2001 From: Elliotte Rusty Harold Date: Thu, 2 Jul 2026 11:59:11 +0000 Subject: [PATCH 2/2] Refactor addManifestAttribute for simplicity Simplified the addManifestAttribute method by removing unnecessary conditional checks for empty values. --- .../apache/maven/shared/archiver/MavenArchiver.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/apache/maven/shared/archiver/MavenArchiver.java b/src/main/java/org/apache/maven/shared/archiver/MavenArchiver.java index 6a2a5b4..89cd75f 100644 --- a/src/main/java/org/apache/maven/shared/archiver/MavenArchiver.java +++ b/src/main/java/org/apache/maven/shared/archiver/MavenArchiver.java @@ -208,18 +208,13 @@ private void addManifestAttribute(Manifest manifest, Map map, St private void addManifestAttribute(Manifest manifest, String key, String value) throws ManifestException { String sanitized = sanitizeManifestValue(value); - if (!(sanitized == null || sanitized.isEmpty())) { - Manifest.Attribute attr = new Manifest.Attribute(key, sanitized); - manifest.addConfiguredAttribute(attr); - } else { - Manifest.Attribute attr = new Manifest.Attribute(key, ""); - manifest.addConfiguredAttribute(attr); - } + Manifest.Attribute attr = new Manifest.Attribute(key, sanitized); + manifest.addConfiguredAttribute(attr); } private static String sanitizeManifestValue(String value) { if (value == null) { - return null; + return ""; } return value.replace("\r\n", " ").replace('\r', ' ').replace('\n', ' '); }