CR, LF, and NUL are not permitted in ZIP entry names
am: 27fbfa6017
Change-Id: I02d63131530f812053cd5fdd8e24a3cc13250964
diff --git a/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeSigner.java b/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeSigner.java
index af98007..0509d73 100644
--- a/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeSigner.java
+++ b/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeSigner.java
@@ -362,6 +362,7 @@
SortedMap<String, byte[]> invidualSectionsContents = new TreeMap<>();
String entryDigestAttributeName = getEntryDigestAttributeName(jarEntryDigestAlgorithm);
for (String entryName : sortedEntryNames) {
+ checkEntryNameValid(entryName);
byte[] entryDigest = jarEntryDigests.get(entryName);
Attributes entryAttrs = new Attributes();
entryAttrs.putValue(
@@ -386,6 +387,22 @@
return result;
}
+ private static void checkEntryNameValid(String name) throws ApkFormatException {
+ // JAR signing spec says CR, LF, and NUL are not permitted in entry names
+ // CR or LF in entry names will result in malformed MANIFEST.MF and .SF files because there
+ // is no way to escape characters in MANIFEST.MF and .SF files. NUL can, presumably, cause
+ // issues when parsing using C and C++ like languages.
+ for (char c : name.toCharArray()) {
+ if ((c == '\r') || (c == '\n') || (c == 0)) {
+ throw new ApkFormatException(
+ String.format(
+ "Unsupported character 0x%1$02x in ZIP entry name \"%2$s\"",
+ (int) c,
+ name));
+ }
+ }
+ }
+
public static class OutputManifestFile {
public byte[] contents;
public SortedMap<String, byte[]> individualSectionsContents;
diff --git a/src/test/java/com/android/apksig/ApkSignerTest.java b/src/test/java/com/android/apksig/ApkSignerTest.java
index bcd0fe1..fe2b8cf 100644
--- a/src/test/java/com/android/apksig/ApkSignerTest.java
+++ b/src/test/java/com/android/apksig/ApkSignerTest.java
@@ -313,6 +313,31 @@
verifyForMinSdkVersion(out, 17), Issue.JAR_SIG_UNSUPPORTED_SIG_ALG);
}
+ @Test
+ public void testV1SigningRejectsInvalidZipEntryNames() throws Exception {
+ // ZIP/JAR entry name cannot contain CR, LF, or NUL characters when the APK is being
+ // JAR-signed.
+ List<ApkSigner.SignerConfig> signers =
+ Collections.singletonList(getDefaultSignerConfigFromResources("rsa-2048"));
+ try {
+ sign("v1-only-with-cr-in-entry-name.apk",
+ new ApkSigner.Builder(signers).setV1SigningEnabled(true));
+ fail();
+ } catch (ApkFormatException expected) {}
+
+ try {
+ sign("v1-only-with-lf-in-entry-name.apk",
+ new ApkSigner.Builder(signers).setV1SigningEnabled(true));
+ fail();
+ } catch (ApkFormatException expected) {}
+
+ try {
+ sign("v1-only-with-nul-in-entry-name.apk",
+ new ApkSigner.Builder(signers).setV1SigningEnabled(true));
+ fail();
+ } catch (ApkFormatException expected) {}
+ }
+
/**
* Asserts that signing the specified golden input file using the provided signing
* configuration produces output identical to the specified golden output file.
diff --git a/src/test/java/com/android/apksig/ApkVerifierTest.java b/src/test/java/com/android/apksig/ApkVerifierTest.java
index 0c1cc8b..6059ffc 100644
--- a/src/test/java/com/android/apksig/ApkVerifierTest.java
+++ b/src/test/java/com/android/apksig/ApkVerifierTest.java
@@ -629,6 +629,17 @@
"v1-sha1-sha256-manifest-and-sf-with-sha256-wrong-in-sf.apk", 17));
}
+ @Test
+ public void testV1WithUnsupportedCharacterInZipEntryName() throws Exception {
+ // Android Package Manager does not support ZIP entry names containing CR or LF
+ assertVerificationFailure(
+ verify("v1-only-with-cr-in-entry-name.apk"),
+ Issue.JAR_SIG_UNNNAMED_MANIFEST_SECTION);
+ assertVerificationFailure(
+ verify("v1-only-with-lf-in-entry-name.apk"),
+ Issue.JAR_SIG_UNNNAMED_MANIFEST_SECTION);
+ }
+
private ApkVerifier.Result verify(String apkFilenameInResources)
throws IOException, ApkFormatException, NoSuchAlgorithmException {
return verify(apkFilenameInResources, null, null);
diff --git a/src/test/resources/com/android/apksig/v1-only-with-cr-in-entry-name.apk b/src/test/resources/com/android/apksig/v1-only-with-cr-in-entry-name.apk
new file mode 100644
index 0000000..84828b0
--- /dev/null
+++ b/src/test/resources/com/android/apksig/v1-only-with-cr-in-entry-name.apk
Binary files differ
diff --git a/src/test/resources/com/android/apksig/v1-only-with-lf-in-entry-name.apk b/src/test/resources/com/android/apksig/v1-only-with-lf-in-entry-name.apk
new file mode 100644
index 0000000..7d341da
--- /dev/null
+++ b/src/test/resources/com/android/apksig/v1-only-with-lf-in-entry-name.apk
Binary files differ
diff --git a/src/test/resources/com/android/apksig/v1-only-with-nul-in-entry-name.apk b/src/test/resources/com/android/apksig/v1-only-with-nul-in-entry-name.apk
new file mode 100644
index 0000000..2bcdec1
--- /dev/null
+++ b/src/test/resources/com/android/apksig/v1-only-with-nul-in-entry-name.apk
Binary files differ