From b780b9f1d67096ac3055728bf0c5a9f5687067ec Mon Sep 17 00:00:00 2001 From: Andrey Loskutov Date: Mon, 16 Feb 2026 15:56:11 +0100 Subject: [PATCH] Allow IDE enable/disable escaping classpath entries in jars Since b74a7b82d9221b86893a88ea5453e92534ffe51b JDT Core (but not ecj!) supported Class-Path attribute for external jars and added all entries from such jar to the current project classpath. This change introduces new JavaCore preference that allows JDT ignore "escaping" classpath entries read from external jars (entries, containing ".." path segment). By default, JDT disables now old behavior and disallows such paths. See https://github.com/eclipse-jdt/eclipse.jdt.core/issues/258 See https://bugs.eclipse.org/bugs/show_bug.cgi?id=198572 --- .../model/org/eclipse/jdt/core/JavaCore.java | 28 +++++++++++++++++++ .../jdt/internal/core/ClasspathEntry.java | 10 +++++++ .../core/JavaCorePreferenceInitializer.java | 1 + 3 files changed, 39 insertions(+) diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java index fa71c1005f0..aeeb82ac8b9 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java @@ -2715,6 +2715,34 @@ public final class JavaCore extends Plugin { */ public static final String CORE_MAIN_ONLY_PROJECT_HAS_TEST_ONLY_DEPENDENCY = PLUGIN_ID + ".classpath.mainOnlyProjectHasTestOnlyDependency"; //$NON-NLS-1$ + /** + * Core option ID: Enable escaping classpath entries in jar manifests (like ../bad.jar). + *

+ * When enabled, the classpath entries in jar manifests can escape current jar directory tree (like + * ../lib/some.jar). When disabled, all classpath entries in manifest must be inside current jar directory tree. + *

+ *

+ * This option should be disabled to be consistent with command line compiler, but it is enabled by default for + * backward compatibility reasons (in the IDE escaping classpath entries was possible since Eclipse 3.5, see + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=198572). + *

+ *

+ * For performance reasons, any presence of the ".." segment in a classpath entry in a jar manifest will + * cause the compiler to assume that the entry is escaping the current jar directory tree. + *

+ *
+ *
Option id:
+ *
"org.eclipse.jdt.core.classpath.enableEscapingCpEntriesInJarManifest"
+ *
Possible values:
+ *
{ "enabled", "disabled" }
+ *
Default:
+ *
"disabled"
+ *
+ * + * @since 3.45 + */ + public static final String CORE_ENABLE_ESACAPING_CP_ENTRIES_IN_JAR_MANIFEST = PLUGIN_ID + ".classpath.enableEscapingCpEntriesInJarManifest"; //$NON-NLS-1$ + /** * Compiler option ID: Enabling support for preview language features. *

When enabled, the compiler will activate the preview language features of this Java version.

diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java index a0f38b0ccd0..b31e2dcee2f 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java @@ -978,6 +978,16 @@ private static void resolvedChainedLibraries(IPath jarPath, HashSet visited, Arr trace("Invalid Class-Path entry " + calledFileName + " in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$ } } else { + String escapePref = JavaCore.getOptions() + .get(JavaCore.CORE_ENABLE_ESACAPING_CP_ENTRIES_IN_JAR_MANIFEST); + if (JavaCore.DISABLED.equals(escapePref) && calledFileName.indexOf(DOT_DOT) != -1 + && hasDotDot(Path.fromPortableString(calledFileName))) { + if (JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE) { + trace("Invalid (escaping jar directory) Class-Path entry " + calledFileName //$NON-NLS-1$ + + " in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$ + } + continue; + } IPath calledJar = directoryPath.append(new Path(calledFileName)); // Ignore if segment count is Zero (https://bugs.eclipse.org/bugs/show_bug.cgi?id=308150) if (calledJar.segmentCount() == 0) { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java index 646f624a051..7648fbc1379 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java @@ -78,6 +78,7 @@ public void initializeDefaultPreferences() { defaultOptionsMap.put(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS, JavaCore.ENABLED); defaultOptionsMap.put(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE, JavaCore.ERROR); defaultOptionsMap.put(JavaCore.CORE_MAIN_ONLY_PROJECT_HAS_TEST_ONLY_DEPENDENCY, JavaCore.ERROR); + defaultOptionsMap.put(JavaCore.CORE_ENABLE_ESACAPING_CP_ENTRIES_IN_JAR_MANIFEST, JavaCore.DISABLED); // encoding setting comes from resource plug-in optionNames.add(JavaCore.CORE_ENCODING);