diff --git a/third_party/ijar/ijar.cc b/third_party/ijar/ijar.cc index 3bac6bd5364d61..4010c21132d78d 100644 --- a/third_party/ijar/ijar.cc +++ b/third_party/ijar/ijar.cc @@ -35,6 +35,8 @@ bool StripClass(u1 *&classdata_out, const u1 *classdata_in, size_t in_length); const char *CLASS_EXTENSION = ".class"; const size_t CLASS_EXTENSION_LENGTH = strlen(CLASS_EXTENSION); +const char *TRANSITIVE_PREFIX = "META-INF/TRANSITIVE/"; +const size_t TRANSITIVE_PREFIX_LENGTH = strlen(TRANSITIVE_PREFIX); const char *KOTLIN_BUILTINS_EXTENSION = ".kotlin_builtins"; const size_t KOTLIN_BUILTINS_EXTENSION_LENGTH = strlen(KOTLIN_BUILTINS_EXTENSION); @@ -133,6 +135,10 @@ bool JarStripperProcessor::Accept(const char *filename, const u4 /*attr*/) { CLASS_EXTENSION) != 0) { return false; } + if (StartsWith(filename, filename_len, TRANSITIVE_PREFIX, + TRANSITIVE_PREFIX_LENGTH)) { + return false; + } return true; } diff --git a/third_party/ijar/test/BUILD b/third_party/ijar/test/BUILD index eb8d4aefc78f56..61bf7417123ad0 100644 --- a/third_party/ijar/test/BUILD +++ b/third_party/ijar/test/BUILD @@ -372,6 +372,31 @@ genrule( tools = [":GenJarWithManifestSections"], ) +java_binary( + name = "GenMetaInfTransitive", + testonly = 1, + srcs = ["GenMetaInfTransitive.java"], + main_class = "GenMetaInfTransitive", + deps = ["//third_party:guava"], +) + +genrule( + name = "meta_inf_transitive", + testonly = 1, + outs = ["meta_inf_transitive.jar"], + cmd = "$(location :GenMetaInfTransitive) $@", + tools = [":GenMetaInfTransitive"], +) + +genrule( + name = "meta_inf_transitive-interface", + testonly = 1, + srcs = [":meta_inf_transitive.jar"], + outs = ["meta_inf_transitive-interface.jar"], + cmd = "$(location //third_party/ijar) $< $@", + tools = ["//third_party/ijar"], +) + java_test( name = "IjarTests", size = "small", @@ -402,6 +427,7 @@ java_test( ":kotlin_module-interface.jar", ":liblocal_and_anonymous_lib.jar", ":local_and_anonymous-interface.jar", + ":meta_inf_transitive-interface", ":module_info-interface.jar", ":scala_tasty-interface.jar", ], diff --git a/third_party/ijar/test/GenMetaInfTransitive.java b/third_party/ijar/test/GenMetaInfTransitive.java new file mode 100644 index 00000000000000..60402b623bdfe9 --- /dev/null +++ b/third_party/ijar/test/GenMetaInfTransitive.java @@ -0,0 +1,44 @@ +// Copyright 2024 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +import com.google.common.io.ByteStreams; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.jar.JarOutputStream; +import java.util.zip.ZipEntry; + +/** + * A generator for a jar file containing a META-INF/TRANSITIVE/ entries, and one real class file. + */ +public final class GenMetaInfTransitive { + public static void main(String[] args) throws IOException { + try (JarOutputStream jos = new JarOutputStream(Files.newOutputStream(Paths.get(args[0])))) { + addEntry(jos, "META-INF/TRANSITIVE/java/lang/String.class"); + ByteStreams.copy(String.class.getResourceAsStream("/java/lang/String.class"), jos); + + addEntry(jos, "java/lang/String.class"); + ByteStreams.copy(String.class.getResourceAsStream("/java/lang/String.class"), jos); + } + } + + private static void addEntry(JarOutputStream jos, String name) throws IOException { + ZipEntry ze = new ZipEntry(name); + ze.setTime(0); + jos.putNextEntry(ze); + } + + private GenMetaInfTransitive() {} +} diff --git a/third_party/ijar/test/IjarTests.java b/third_party/ijar/test/IjarTests.java index d2df340abd8625..719bea294f4148 100644 --- a/third_party/ijar/test/IjarTests.java +++ b/third_party/ijar/test/IjarTests.java @@ -473,6 +473,12 @@ public void testNoStripIdempotence() throws Exception { assertThat(original).isEqualTo(stripped); } + @Test + public void metaInfTtransitive() throws Exception { + Map lib = readJar("third_party/ijar/test/meta_inf_transitive-interface.jar"); + assertThat(lib.keySet()).containsExactly("java/lang/String.class"); + } + private static void assertNonManifestFilesBitIdentical(JarFile original, JarFile stripped) throws IOException { // Make sure that all other files came across bitwise equal