From df7731f13e58e719d0b0a703a0b53f2bc1e2d795 Mon Sep 17 00:00:00 2001 From: tomlu Date: Sat, 31 Mar 2018 10:07:39 -0700 Subject: Make ijar support not stripping the class data. This is done by adding a --[no]strip_classes flag to ijar. PiperOrigin-RevId: 191184258 --- third_party/ijar/ijar.cc | 292 ++++++++++++++++----- third_party/ijar/test/BUILD | 49 ++++ third_party/ijar/test/IjarTests.java | 101 +++++++ .../test/jar-with-manifest-and-target-label.jar | Bin 0 -> 3338 bytes third_party/ijar/test/jar-with-manifest.jar | Bin 0 -> 3312 bytes third_party/ijar/test/jar-without-manifest.jar | Bin 0 -> 2952 bytes 6 files changed, 373 insertions(+), 69 deletions(-) create mode 100644 third_party/ijar/test/jar-with-manifest-and-target-label.jar create mode 100644 third_party/ijar/test/jar-with-manifest.jar create mode 100644 third_party/ijar/test/jar-without-manifest.jar (limited to 'third_party') diff --git a/third_party/ijar/ijar.cc b/third_party/ijar/ijar.cc index 160645d7ae..a50b97037d 100644 --- a/third_party/ijar/ijar.cc +++ b/third_party/ijar/ijar.cc @@ -15,11 +15,11 @@ // ijar.cpp -- .jar -> _interface.jar tool. // +#include +#include #include -#include #include -#include -#include +#include #include #include "third_party/ijar/zip.h" @@ -31,9 +31,9 @@ bool verbose = false; // Reads a JVM class from classdata_in (of the specified length), and // writes out a simplified class to classdata_out, advancing the // pointer. Returns true if the class should be kept. -bool StripClass(u1*& classdata_out, const u1* classdata_in, size_t in_length); +bool StripClass(u1 *&classdata_out, const u1 *classdata_in, size_t in_length); -const char* CLASS_EXTENSION = ".class"; +const char *CLASS_EXTENSION = ".class"; const size_t CLASS_EXTENSION_LENGTH = strlen(CLASS_EXTENSION); const char *MANIFEST_DIR_PATH = "META-INF/"; @@ -51,29 +51,34 @@ const size_t TARGET_LABEL_KEY_LENGTH = strlen(TARGET_LABEL_KEY); const char *INJECTING_RULE_KIND_KEY = "Injecting-Rule-Kind: "; const size_t INJECTING_RULE_KIND_KEY_LENGTH = strlen(INJECTING_RULE_KIND_KEY); +class JarExtractorProcessor : public ZipExtractorProcessor { + public: + // Set the ZipBuilder to add the ijar class to the output zip file. + // This pointer should not be deleted while this class is still in use and + // it should be set before any call to the Process() method. + void SetZipBuilder(ZipBuilder *builder) { this->builder_ = builder; } + virtual void WriteManifest(const char *target_label, + const char *injecting_rule_kind) = 0; + + protected: + // Not owned by JarStripperProcessor, see SetZipBuilder(). + ZipBuilder *builder_; +}; + // ZipExtractorProcessor that select only .class file and use // StripClass to generate an interface class, storing as a new file // in the specified ZipBuilder. -class JarStripperProcessor : public ZipExtractorProcessor { +class JarStripperProcessor : public JarExtractorProcessor { public: JarStripperProcessor() {} virtual ~JarStripperProcessor() {} - virtual void Process(const char* filename, const u4 attr, - const u1* data, const size_t size); - virtual bool Accept(const char* filename, const u4 attr); - - private: - // Not owned by JarStripperProcessor, see SetZipBuilder(). - ZipBuilder* builder; + virtual void Process(const char *filename, const u4 attr, const u1 *data, + const size_t size); + virtual bool Accept(const char *filename, const u4 attr); - public: - // Set the ZipBuilder to add the ijar class to the output zip file. - // This pointer should not be deleted while this class is still in use and - // it should be set before any call to the Process() method. - void SetZipBuilder(ZipBuilder* builder) { - this->builder = builder; - } + virtual void WriteManifest(const char *target_label, + const char *injecting_rule_kind); }; bool JarStripperProcessor::Accept(const char *filename, const u4 /*attr*/) { @@ -86,8 +91,8 @@ bool JarStripperProcessor::Accept(const char *filename, const u4 /*attr*/) { return true; } -static bool IsModuleInfo(const char* filename) { - const char* slash = strrchr(filename, '/'); +static bool IsModuleInfo(const char *filename) { + const char *slash = strrchr(filename, '/'); if (slash == NULL) { slash = filename; } else { @@ -102,36 +107,195 @@ void JarStripperProcessor::Process(const char *filename, const u4 /*attr*/, fprintf(stderr, "INFO: StripClass: %s\n", filename); } if (IsModuleInfo(filename)) { - u1* q = builder->NewFile(filename, 0); + u1 *q = builder_->NewFile(filename, 0); memcpy(q, data, size); - builder->FinishFile(size, false, true); + builder_->FinishFile(size, /* compress: */ false, /* compute_crc: */ true); } else { - u1* buf = reinterpret_cast(malloc(size)); - u1* classdata_out = buf; + u1 *buf = reinterpret_cast(malloc(size)); + u1 *classdata_out = buf; if (!StripClass(buf, data, size)) { free(classdata_out); return; } - u1* q = builder->NewFile(filename, 0); + u1 *q = builder_->NewFile(filename, 0); size_t out_length = buf - classdata_out; memcpy(q, classdata_out, out_length); - builder->FinishFile(out_length, false, true); + builder_->FinishFile(out_length, /* compress: */ false, + /* compute_crc: */ true); free(classdata_out); } } -// Copies the string into the buffer without the null terminator, returns length -static size_t WriteStr(u1 *buf, const char *str) { +// Copies the string into the buffer without the null terminator, returns +// updated buffer pointer +static u1 *WriteStr(u1 *buf, const char *str) { size_t len = strlen(str); memcpy(buf, str, len); - return len; + return buf + len; +} + +// Writes a manifest attribute including a "\r\n" line break, returns updated +// buffer pointer. +static u1 *WriteManifestAttr(u1 *buf, const char *key, const char *val) { + buf = WriteStr(buf, key); + buf = WriteStr(buf, val); + *buf++ = '\r'; + *buf++ = '\n'; + return buf; +} + +void JarStripperProcessor::WriteManifest(const char *target_label, + const char *injecting_rule_kind) { + if (target_label == nullptr) { + return; + } + builder_->WriteEmptyFile(MANIFEST_DIR_PATH); + u1 *start = builder_->NewFile(MANIFEST_PATH, 0); + u1 *buf = start; + buf = WriteStr(buf, MANIFEST_HEADER); + buf = WriteManifestAttr(buf, TARGET_LABEL_KEY, target_label); + if (injecting_rule_kind) { + buf = WriteManifestAttr(buf, INJECTING_RULE_KIND_KEY, injecting_rule_kind); + } + size_t total_len = buf - start; + builder_->FinishFile(total_len, /* compress: */ false, + /* compute_crc: */ true); +} + +class JarCopierProcessor : public JarExtractorProcessor { + public: + JarCopierProcessor(const char *jar) : jar_(jar) {} + virtual ~JarCopierProcessor() {} + + virtual void Process(const char *filename, const u4 /*attr*/, const u1 *data, + const size_t size); + virtual bool Accept(const char *filename, const u4 /*attr*/); + + virtual void WriteManifest(const char *target_label, + const char *injecting_rule_kind); + + private: + class ManifestLocator : public ZipExtractorProcessor { + public: + ManifestLocator() : manifest_buf_(nullptr), manifest_size_(0) {} + virtual ~ManifestLocator() { free(manifest_buf_); } + + u1 *manifest_buf_; + size_t manifest_size_; + + virtual bool Accept(const char *filename, const u4 /*attr*/) { + return strcmp(filename, MANIFEST_PATH) == 0; + } + + virtual void Process(const char * /*filename*/, const u4 /*attr*/, + const u1 *data, const size_t size) { + manifest_buf_ = (u1 *)malloc(size); + memmove(manifest_buf_, data, size); + manifest_size_ = size; + } + }; + + const char *jar_; + + u1 *AppendTargetLabelToManifest(u1 *buf, const u1 *manifest_data, + const size_t size, const char *target_label, + const char *injecting_rule_kind); +}; + +void JarCopierProcessor::Process(const char *filename, const u4 /*attr*/, + const u1 *data, const size_t size) { + if (verbose) { + fprintf(stderr, "INFO: CopyFile: %s\n", filename); + } + // We already handled the manifest in WriteManifest + if (strcmp(filename, MANIFEST_DIR_PATH) == 0 || + strcmp(filename, MANIFEST_PATH) == 0) { + return; + } + u1 *q = builder_->NewFile(filename, 0); + memcpy(q, data, size); + builder_->FinishFile(size, /* compress: */ false, /* compute_crc: */ true); +} + +bool JarCopierProcessor::Accept(const char * /*filename*/, const u4 /*attr*/) { + return true; +} + +void JarCopierProcessor::WriteManifest(const char *target_label, + const char *injecting_rule_kind) { + ManifestLocator manifest_locator; + std::unique_ptr in( + ZipExtractor::Create(jar_, &manifest_locator)); + in->ProcessAll(); + + bool wants_manifest = + manifest_locator.manifest_buf_ != nullptr || target_label != nullptr; + if (wants_manifest) { + builder_->WriteEmptyFile(MANIFEST_DIR_PATH); + u1 *start = builder_->NewFile(MANIFEST_PATH, 0); + u1 *buf = start; + // Three cases: + // 1. We need to merge the target label into a pre-existing manifest + // 2. Write a manifest from scratch with a target label + // 3. Copy existing manifest without adding target label + if (manifest_locator.manifest_buf_ != nullptr && target_label != nullptr) { + buf = AppendTargetLabelToManifest(buf, manifest_locator.manifest_buf_, + manifest_locator.manifest_size_, + target_label, injecting_rule_kind); + } else if (target_label != nullptr) { + buf = WriteStr(buf, MANIFEST_HEADER); + buf = WriteManifestAttr(buf, TARGET_LABEL_KEY, target_label); + if (injecting_rule_kind) { + buf = WriteManifestAttr(buf, INJECTING_RULE_KIND_KEY, + injecting_rule_kind); + } + } else { + memcpy(buf, manifest_locator.manifest_buf_, + manifest_locator.manifest_size_); + buf += manifest_locator.manifest_size_; + } + + size_t total_len = buf - start; + builder_->FinishFile(total_len, /* compress: */ false, + /* compute_crc: */ true); + } +} + +u1 *JarCopierProcessor::AppendTargetLabelToManifest( + u1 *buf, const u1 *manifest_data, const size_t size, + const char *target_label, const char *injecting_rule_kind) { + const char *line_start = (const char *)manifest_data; + const char *data_end = (const char *)manifest_data + size; + while (line_start < data_end) { + const char *line_end = strchr(line_start, '\n'); + // Go past return char to point to next line, or to end of data buffer + line_end = line_end != nullptr ? line_end + 1 : data_end; + + // Copy line unless it's Target-Label/Injecting-Rule-Kind and we're writing + // that ourselves + if (strncmp(line_start, TARGET_LABEL_KEY, TARGET_LABEL_KEY_LENGTH) != 0 && + strncmp(line_start, INJECTING_RULE_KIND_KEY, + INJECTING_RULE_KIND_KEY_LENGTH) != 0) { + size_t len = line_end - line_start; + // Skip empty lines + if (len > 0 && line_start[0] != '\r' && line_start[0] != '\n') { + memcpy(buf, line_start, len); + buf += len; + } + } + line_start = line_end; + } + buf = WriteManifestAttr(buf, TARGET_LABEL_KEY, target_label); + if (injecting_rule_kind != nullptr) { + buf = WriteManifestAttr(buf, INJECTING_RULE_KIND_KEY, injecting_rule_kind); + } + return buf; } -// Computes the size of zip file content for the manifest created by // WriteManifest, including zip file format overhead. static size_t EstimateManifestOutputSize(const char *target_label, const char *injecting_rule_kind) { - if (target_label == NULL) { + if (target_label == nullptr) { return 0; } // local headers @@ -152,36 +316,21 @@ static size_t EstimateManifestOutputSize(const char *target_label, return length; } -static void WriteManifest(ZipBuilder *out, const char *target_label, - const char *injecting_rule_kind) { - if (target_label == NULL) { - return; - } - out->WriteEmptyFile(MANIFEST_DIR_PATH); - u1 *start = out->NewFile(MANIFEST_PATH, 0); - u1 *buf = start; - buf += WriteStr(buf, MANIFEST_HEADER); - buf += WriteStr(buf, TARGET_LABEL_KEY); - buf += WriteStr(buf, target_label); - *buf++ = '\r'; - *buf++ = '\n'; - if (injecting_rule_kind) { - buf += WriteStr(buf, INJECTING_RULE_KIND_KEY); - buf += WriteStr(buf, injecting_rule_kind); - *buf++ = '\r'; - *buf++ = '\n'; - } - size_t total_len = buf - start; - out->FinishFile(total_len); -} - // Opens "file_in" (a .jar file) for reading, and writes an interface // .jar to "file_out". static void OpenFilesAndProcessJar(const char *file_out, const char *file_in, - const char *target_label, + bool strip_jar, const char *target_label, const char *injecting_rule_kind) { - JarStripperProcessor processor; - std::unique_ptr in(ZipExtractor::Create(file_in, &processor)); + std::unique_ptr processor; + if (strip_jar) { + processor = + std::unique_ptr(new JarStripperProcessor()); + } else { + processor = + std::unique_ptr(new JarCopierProcessor(file_in)); + } + std::unique_ptr in( + ZipExtractor::Create(file_in, processor.get())); if (in.get() == NULL) { fprintf(stderr, "Unable to open Zip file %s: %s\n", file_in, strerror(errno)); @@ -196,9 +345,8 @@ static void OpenFilesAndProcessJar(const char *file_out, const char *file_in, strerror(errno)); abort(); } - processor.SetZipBuilder(out.get()); - - WriteManifest(out.get(), target_label, injecting_rule_kind); + processor->SetZipBuilder(out.get()); + processor->WriteManifest(target_label, injecting_rule_kind); // Process all files in the zip if (in->ProcessAll() < 0) { @@ -219,9 +367,8 @@ static void OpenFilesAndProcessJar(const char *file_out, const char *file_in, size_t in_length = in->GetSize(); size_t out_length = out->GetSize(); if (verbose) { - fprintf(stderr, "INFO: produced interface jar: %s -> %s (%d%%).\n", - file_in, file_out, - static_cast(100.0 * out_length / in_length)); + fprintf(stderr, "INFO: produced interface jar: %s -> %s (%d%%).\n", file_in, + file_out, static_cast(100.0 * out_length / in_length)); } } } // namespace devtools_ijar @@ -232,13 +379,15 @@ static void OpenFilesAndProcessJar(const char *file_out, const char *file_in, static void usage() { fprintf(stderr, "Usage: ijar " - "[-v] [--target label label] [--injecting_rule_kind kind] " + "[-v] [--[no]strip_jar] " + "[--target label label] [--injecting_rule_kind kind] " "x.jar [x_interface.jar>]\n"); fprintf(stderr, "Creates an interface jar from the specified jar file.\n"); exit(1); } int main(int argc, char **argv) { + bool strip_jar = true; const char *target_label = NULL; const char *injecting_rule_kind = NULL; const char *filename_in = NULL; @@ -247,6 +396,10 @@ int main(int argc, char **argv) { for (int ii = 1; ii < argc; ++ii) { if (strcmp(argv[ii], "-v") == 0) { devtools_ijar::verbose = true; + } else if (strcmp(argv[ii], "--strip_jar") == 0) { + strip_jar = true; + } else if (strcmp(argv[ii], "--nostrip_jar") == 0) { + strip_jar = false; } else if (strcmp(argv[ii], "--target_label") == 0) { if (++ii >= argc) { usage(); @@ -279,7 +432,8 @@ int main(int argc, char **argv) { strcpy(filename_out_buf + len - 4, "-interface.jar"); filename_out = filename_out_buf; } else { - fprintf(stderr, "Can't determine output filename since input filename " + fprintf(stderr, + "Can't determine output filename since input filename " "doesn't end with '.jar'.\n"); return 1; } @@ -289,7 +443,7 @@ int main(int argc, char **argv) { fprintf(stderr, "INFO: writing to '%s'.\n", filename_out); } - devtools_ijar::OpenFilesAndProcessJar(filename_out, filename_in, target_label, - injecting_rule_kind); + devtools_ijar::OpenFilesAndProcessJar(filename_out, filename_in, strip_jar, + target_label, injecting_rule_kind); return 0; } diff --git a/third_party/ijar/test/BUILD b/third_party/ijar/test/BUILD index 62b6edd3a3..816ae1221d 100644 --- a/third_party/ijar/test/BUILD +++ b/third_party/ijar/test/BUILD @@ -109,6 +109,46 @@ genrule( tools = ["//third_party/ijar"], ) +genrule( + name = "interface_ijar_testlib_nostrip", + srcs = [":ijar_testlib"], + outs = ["interface_ijar_testlib_nostrip.jar"], + cmd = "$(location //third_party/ijar) --target_label //foo:foo --nostrip_jar $< $@", + tools = ["//third_party/ijar"], +) + +genrule( + name = "jar_with_manifest_nostrip", + srcs = ["jar-with-manifest.jar"], + outs = ["jar-with-manifest-nostrip.jar"], + cmd = "$(location //third_party/ijar) --target_label //foo:foo --nostrip_jar $< $@", + tools = ["//third_party/ijar"], +) + +genrule( + name = "jar_with_manifest_and_target_label_nostrip", + srcs = ["jar-with-manifest-and-target-label.jar"], + outs = ["jar-with-manifest-and-target-label-nostrip.jar"], + cmd = "$(location //third_party/ijar) --target_label //foo:foo --nostrip_jar $< $@", + tools = ["//third_party/ijar"], +) + +genrule( + name = "jar_without_manifest_nostrip", + srcs = ["jar-without-manifest.jar"], + outs = ["jar-without-manifest-nostrip.jar"], + cmd = "$(location //third_party/ijar) --target_label //foo:foo --nostrip_jar $< $@", + tools = ["//third_party/ijar"], +) + +genrule( + name = "jar_without_manifest_nostrip_idempotence", + srcs = ["jar-without-manifest-nostrip.jar"], + outs = ["jar-without-manifest-nostrip-idempotence.jar"], + cmd = "$(location //third_party/ijar) --target_label //foo:foo --nostrip_jar $< $@", + tools = ["//third_party/ijar"], +) + genrule( name = "empty_with_target_label", srcs = [":empty_zip.jar"], @@ -194,10 +234,19 @@ java_test( "PrivateNestedClass.java", "UseDeprecatedParts.java", "UseRestrictedAnnotation.java", + "jar-with-manifest.jar", + "jar-with-manifest-and-target-label.jar", + "jar-without-manifest.jar", "package-info.java", ":empty_with_target_label", + ":ijar_testlib", ":interface_ijar_testlib", + ":interface_ijar_testlib_nostrip", ":interface_ijar_testlib_with_target_label", + ":jar_with_manifest_and_target_label_nostrip", + ":jar_with_manifest_nostrip", + ":jar_without_manifest_nostrip", + ":jar_without_manifest_nostrip_idempotence", ":liblocal_and_anonymous_lib.jar", ":local_and_anonymous-interface.jar", ":module_info-interface.jar", diff --git a/third_party/ijar/test/IjarTests.java b/third_party/ijar/test/IjarTests.java index f88616f469..f8e487ff64 100644 --- a/third_party/ijar/test/IjarTests.java +++ b/third_party/ijar/test/IjarTests.java @@ -25,6 +25,9 @@ import com.google.common.io.ByteStreams; import com.google.devtools.build.java.bazel.BazelJavaCompiler; import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Paths; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.util.Arrays; @@ -309,4 +312,102 @@ public class IjarTests { LocalDateTime.of(2010, 1, 1, 0, 0, 0).atZone(ZoneOffset.systemDefault()).toInstant()); } } + + // Tests --nostrip_jar with a jar that already has a manifest, but no target label + @Test + public void testNoStripJarWithManifest() throws Exception { + JarFile original = new JarFile("third_party/ijar/test/jar-with-manifest.jar"); + JarFile stripped = new JarFile("third_party/ijar/test/jar-with-manifest-nostrip.jar"); + try { + ImmutableList strippedEntries = + stripped.stream().map(JarEntry::getName).collect(toImmutableList()); + assertThat(strippedEntries.get(0)).isEqualTo("META-INF/"); + assertThat(strippedEntries.get(1)).isEqualTo("META-INF/MANIFEST.MF"); + Manifest manifest = stripped.getManifest(); + Attributes attributes = manifest.getMainAttributes(); + assertThat(attributes.getValue("Manifest-Version")).isEqualTo("1.0"); + // Created-By was already in manifest, doesn't get overwritten + assertThat(attributes.getValue("Created-By")).isEqualTo("test-code"); + assertThat(attributes.getValue("Target-Label")).isEqualTo("//foo:foo"); + assertNonManifestFilesBitIdentical(original, stripped); + } finally { + original.close(); + stripped.close(); + } + } + + // Tests --nostrip_jar with a jar that already has a manifest with a target label + @Test + public void testNoStripJarWithManifestAndTargetLabel() throws Exception { + JarFile original = new JarFile("third_party/ijar/test/jar-with-manifest-and-target-label.jar"); + JarFile stripped = + new JarFile("third_party/ijar/test/jar-with-manifest-and-target-label-nostrip.jar"); + try { + ImmutableList strippedEntries = + stripped.stream().map(JarEntry::getName).collect(toImmutableList()); + assertThat(strippedEntries.get(0)).isEqualTo("META-INF/"); + assertThat(strippedEntries.get(1)).isEqualTo("META-INF/MANIFEST.MF"); + Manifest manifest = stripped.getManifest(); + Attributes attributes = manifest.getMainAttributes(); + assertThat(attributes.getValue("Manifest-Version")).isEqualTo("1.0"); + // Created-By was already in manifest, doesn't get overwritten + assertThat(attributes.getValue("Created-By")).isEqualTo("test-code"); + assertThat(attributes.getValue("Target-Label")).isEqualTo("//foo:foo"); + assertNonManifestFilesBitIdentical(original, stripped); + } finally { + original.close(); + stripped.close(); + } + } + + // Tests --nostrip_jar with a jar that didn't already have a manifest + @Test + public void testNoStripJarWithoutManifest() throws Exception { + JarFile original = new JarFile("third_party/ijar/test/jar-without-manifest.jar"); + JarFile stripped = new JarFile("third_party/ijar/test/jar-without-manifest-nostrip.jar"); + try { + ImmutableList strippedEntries = + stripped.stream().map(JarEntry::getName).collect(toImmutableList()); + assertThat(strippedEntries.get(0)).isEqualTo("META-INF/"); + assertThat(strippedEntries.get(1)).isEqualTo("META-INF/MANIFEST.MF"); + Manifest manifest = stripped.getManifest(); + Attributes attributes = manifest.getMainAttributes(); + assertThat(attributes.getValue("Manifest-Version")).isEqualTo("1.0"); + assertThat(attributes.getValue("Created-By")).isEqualTo("bazel"); + assertThat(attributes.getValue("Target-Label")).isEqualTo("//foo:foo"); + assertNonManifestFilesBitIdentical(original, stripped); + } finally { + original.close(); + stripped.close(); + } + } + + // Tests idempotence of --nostrip + @Test + public void testNoStripIdempotence() throws Exception { + byte[] original = + Files.readAllBytes(Paths.get("third_party/ijar/test/jar-without-manifest-nostrip.jar")); + byte[] stripped = + Files.readAllBytes( + Paths.get("third_party/ijar/test/jar-without-manifest-nostrip-idempotence.jar")); + assertThat(original).isEqualTo(stripped); + } + + private static void assertNonManifestFilesBitIdentical(JarFile original, JarFile stripped) + throws IOException { + // Make sure that all other files came across bitwise equal + for (String classEntry : + original + .stream() + .map(JarEntry::getName) + .filter(name -> !name.equals("META-INF/MANIFEST.MF")) + .collect(toImmutableList())) { + ZipEntry originalEntry = original.getEntry(classEntry); + ZipEntry strippedEntry = stripped.getEntry(classEntry); + InputStream originalStream = original.getInputStream(originalEntry); + InputStream strippedStream = stripped.getInputStream(strippedEntry); + assertThat(ByteStreams.toByteArray(strippedStream)) + .isEqualTo(ByteStreams.toByteArray(originalStream)); + } + } } diff --git a/third_party/ijar/test/jar-with-manifest-and-target-label.jar b/third_party/ijar/test/jar-with-manifest-and-target-label.jar new file mode 100644 index 0000000000..aab7c701f2 Binary files /dev/null and b/third_party/ijar/test/jar-with-manifest-and-target-label.jar differ diff --git a/third_party/ijar/test/jar-with-manifest.jar b/third_party/ijar/test/jar-with-manifest.jar new file mode 100644 index 0000000000..7191935efb Binary files /dev/null and b/third_party/ijar/test/jar-with-manifest.jar differ diff --git a/third_party/ijar/test/jar-without-manifest.jar b/third_party/ijar/test/jar-without-manifest.jar new file mode 100644 index 0000000000..d2bd18d006 Binary files /dev/null and b/third_party/ijar/test/jar-without-manifest.jar differ -- cgit v1.2.3