This is an automated email from the ASF dual-hosted git repository.

jaikiran pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ant.git

commit 689b6ea90ee1fbad580a437137d80609c9336f12
Author: Jaikiran Pai <jaiki...@apache.org>
AuthorDate: Thu Aug 10 17:11:57 2023 +0530

    For Java 18+, Ant will no longer use the SecurityManager
    
    Starting Java 18, setting SecurityManager at runtime is disallowed by 
default https://bugs.openjdk.org/browse/JDK-8270380 in preparation of 
deprecation (for removal)
    of the SecurityManager (https://openjdk.org/jeps/411). Ant (by default) 
internally used to create and set a SecurityManager. Among other things, one 
primary reason
    was to intercept a call to System.exit() in a JVM within which the Ant 
process is running. Ant (through) its custom SecurityManager would then prevent 
the call to
    System.exit() and instead throw a specific exception type that the Ant 
process knew how to handle. This is no longer feasible in Java 18+ and trying 
to allow usage
    of SecurityManager in such Java runtime versions is neither easy nor adding 
any value. Ant did a release (1.10.13) which attempted to keep around the 
SecurityManager
    usage for a few releases, by introducing some brittle and complex changes, 
but that is no longer feasible to maintain due to various other issues that it 
ended up
    creating (that have been tracked in the Ant bugzilla).
    
    This commit also skips some tests for Java 18+, those which required usage 
or testing of the SecurityManager
---
 src/main/org/apache/tools/ant/taskdefs/Java.java   |  3 ++-
 .../org/apache/tools/ant/types/Permissions.java    |  7 +++++
 .../apache/tools/ant/util/SecurityManagerUtil.java | 30 ++++++++++++++++++++++
 .../org/apache/tools/ant/taskdefs/JavaTest.java    | 19 +++++++++++++-
 .../ant/taskdefs/optional/TraXLiaisonTest.java     | 10 ++++++++
 .../optional/junit/XMLResultAggregatorTest.java    |  7 +++++
 .../apache/tools/ant/types/PermissionsTest.java    | 12 ++++++++-
 7 files changed, 85 insertions(+), 3 deletions(-)

diff --git a/src/main/org/apache/tools/ant/taskdefs/Java.java 
b/src/main/org/apache/tools/ant/taskdefs/Java.java
index 7c55bbe6e..292d66b0c 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Java.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Java.java
@@ -38,6 +38,7 @@ import org.apache.tools.ant.types.PropertySet;
 import org.apache.tools.ant.types.RedirectorElement;
 import org.apache.tools.ant.types.Reference;
 import org.apache.tools.ant.util.KeepAliveInputStream;
+import org.apache.tools.ant.util.SecurityManagerUtil;
 import org.apache.tools.ant.util.StringUtils;
 
 /**
@@ -202,7 +203,7 @@ public class Java extends Task {
                 log("bootclasspath ignored when same JVM is used.",
                     Project.MSG_WARN);
             }
-            if (perm == null) {
+            if (perm == null && 
SecurityManagerUtil.isSetSecurityManagerAllowed()) {
                 perm = new Permissions(true);
                 log("running " + this.getCommandLine().getClassname()
                     + " with default permissions (exit forbidden)", 
Project.MSG_VERBOSE);
diff --git a/src/main/org/apache/tools/ant/types/Permissions.java 
b/src/main/org/apache/tools/ant/types/Permissions.java
index b61d9f6c1..f017555c5 100644
--- a/src/main/org/apache/tools/ant/types/Permissions.java
+++ b/src/main/org/apache/tools/ant/types/Permissions.java
@@ -30,6 +30,7 @@ import java.util.StringTokenizer;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.ExitException;
+import org.apache.tools.ant.util.SecurityManagerUtil;
 
 /**
  * This class implements a security manager meant for usage by tasks that run 
inside the
@@ -98,6 +99,9 @@ public class Permissions {
      * @throws BuildException on error
      */
     public synchronized void setSecurityManager() throws BuildException {
+        if (!SecurityManagerUtil.isSetSecurityManagerAllowed()) {
+            return;
+        }
         origSm = System.getSecurityManager();
         init();
         System.setSecurityManager(new MySM());
@@ -169,6 +173,9 @@ public class Permissions {
      * To be used by tasks that just finished executing the parts subject to 
these permissions.
      */
     public synchronized void restoreSecurityManager() {
+        if (!SecurityManagerUtil.isSetSecurityManagerAllowed()) {
+            return;
+        }
         active = false;
         System.setSecurityManager(origSm);
     }
diff --git a/src/main/org/apache/tools/ant/util/SecurityManagerUtil.java 
b/src/main/org/apache/tools/ant/util/SecurityManagerUtil.java
new file mode 100644
index 000000000..e27b14efb
--- /dev/null
+++ b/src/main/org/apache/tools/ant/util/SecurityManagerUtil.java
@@ -0,0 +1,30 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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
+ *
+ *      https://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.
+ *
+ */
+package org.apache.tools.ant.util;
+
+public final class SecurityManagerUtil {
+
+    private static final boolean isJava18OrHigher = 
JavaEnvUtils.isAtLeastJavaVersion("18");
+
+    public static boolean isSetSecurityManagerAllowed() {
+        if (isJava18OrHigher) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/JavaTest.java 
b/src/tests/junit/org/apache/tools/ant/taskdefs/JavaTest.java
index 12654617d..3faf3a6fa 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/JavaTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/JavaTest.java
@@ -35,6 +35,7 @@ import org.apache.tools.ant.MagicNames;
 import org.apache.tools.ant.input.DefaultInputHandler;
 import org.apache.tools.ant.taskdefs.condition.JavaVersion;
 import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.util.JavaEnvUtils;
 import org.apache.tools.ant.util.TeeOutputStream;
 import org.junit.Assume;
 import org.junit.AssumptionViolatedException;
@@ -72,6 +73,18 @@ public class JavaTest {
 
     private boolean runFatalTests = false;
 
+    private static final boolean allowedToIssueSystemExit;
+    private static final String SKIP_MSG_CAUSE_SYSTEM_EXIT_USE =
+            "Skipping test on current Java version " + 
JavaEnvUtils.getJavaVersion()
+                    + " because test calls System.exit() in non-forked VM";
+    static {
+        final JavaVersion javaVersion = new JavaVersion();
+        javaVersion.setAtMost("17");
+        // don't run tests which call System.exit() on a non-forked VM because
+        // Ant no longer sets a custom SecurityManager to prevent the VM exit
+        // for Java versions >= 18
+        allowedToIssueSystemExit = javaVersion.eval();
+    }
 
     /**
      * configure the project.
@@ -209,12 +222,14 @@ public class JavaTest {
     @Test
     public void testRunFail() {
         assumeTrue("Fatal tests have not been set to run", runFatalTests);
+        assumeTrue(SKIP_MSG_CAUSE_SYSTEM_EXIT_USE, allowedToIssueSystemExit);
         buildRule.executeTarget("testRunFail");
     }
 
     @Test
     public void testRunFailFoe() {
         assumeTrue("Fatal tests have not been set to run", runFatalTests);
+        assumeTrue(SKIP_MSG_CAUSE_SYSTEM_EXIT_USE, allowedToIssueSystemExit);
         thrown.expect(BuildException.class);
         thrown.expectMessage("Java returned:");
         buildRule.executeTarget("testRunFailFoe");
@@ -273,12 +288,14 @@ public class JavaTest {
 
     @Test
     public void testResultPropertyNonZeroNoFork() {
+        assumeTrue(SKIP_MSG_CAUSE_SYSTEM_EXIT_USE, allowedToIssueSystemExit);
         buildRule.executeTarget("testResultPropertyNonZeroNoFork");
-         assertEquals("-1", buildRule.getProject().getProperty("exitcode"));
+        assertEquals("-1", buildRule.getProject().getProperty("exitcode"));
      }
 
     @Test
     public void testRunFailWithFailOnError() {
+        assumeTrue(SKIP_MSG_CAUSE_SYSTEM_EXIT_USE, allowedToIssueSystemExit);
         thrown.expect(BuildException.class);
         thrown.expectMessage("Java returned:");
         buildRule.executeTarget("testRunFailWithFailOnError");
diff --git 
a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/TraXLiaisonTest.java 
b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/TraXLiaisonTest.java
index 9ea6089c8..4d69126b6 100644
--- 
a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/TraXLiaisonTest.java
+++ 
b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/TraXLiaisonTest.java
@@ -35,7 +35,9 @@ import 
javax.xml.transform.TransformerFactoryConfigurationError;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.taskdefs.XSLTLiaison;
 import org.apache.tools.ant.taskdefs.XSLTLogger;
+import org.apache.tools.ant.taskdefs.condition.JavaVersion;
 import org.apache.tools.ant.util.JAXPUtils;
+import org.apache.tools.ant.util.JavaEnvUtils;
 import org.junit.After;
 import org.junit.Test;
 
@@ -60,6 +62,10 @@ public class TraXLiaisonTest extends AbstractXSLTLiaisonTest 
implements XSLTLogg
 
     @Test
     public void testXalan2RedirectViaJDKFactory() throws Exception {
+        final JavaVersion javaVersion = new JavaVersion();
+        javaVersion.setAtMost("17");
+        assumeTrue("Test sets SecurityManager at runtime which is no longer 
supported" +
+                " on Java version: " + JavaEnvUtils.getJavaVersion(), 
javaVersion.eval());
         try {
             
getClass().getClassLoader().loadClass("org.apache.xalan.lib.Redirect");
         } catch (Exception exc) {
@@ -106,6 +112,10 @@ public class TraXLiaisonTest extends 
AbstractXSLTLiaisonTest implements XSLTLogg
 
     @Test
     public void testXalan2RedirectViaXalan() throws Exception {
+        final JavaVersion javaVersion = new JavaVersion();
+        javaVersion.setAtMost("17");
+        assumeTrue("Test sets SecurityManager at runtime which is no longer 
supported" +
+                " on Java version: " + JavaEnvUtils.getJavaVersion(), 
javaVersion.eval());
         try {
             
getClass().getClassLoader().loadClass("org.apache.xalan.lib.Redirect");
         } catch (Exception exc) {
diff --git 
a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregatorTest.java
 
b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregatorTest.java
index 802f57209..301c339e4 100644
--- 
a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregatorTest.java
+++ 
b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregatorTest.java
@@ -20,6 +20,7 @@ package org.apache.tools.ant.taskdefs.optional.junit;
 
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -29,13 +30,19 @@ import java.security.Permission;
 import org.apache.tools.ant.DefaultLogger;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.Delete;
+import org.apache.tools.ant.taskdefs.condition.JavaVersion;
 import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.util.JavaEnvUtils;
 import org.junit.Test;
 
 public class XMLResultAggregatorTest {
 
     @Test
     public void testFrames() throws Exception {
+        final JavaVersion javaVersion = new JavaVersion();
+        javaVersion.setAtMost("17");
+        assumeTrue("Test sets SecurityManager at runtime which is no longer 
supported" +
+                " on Java version: " + JavaEnvUtils.getJavaVersion(), 
javaVersion.eval());
         // For now, skip this test on JDK 6 (and below); see below for why:
         try {
             Class.forName("java.nio.file.Files");
diff --git a/src/tests/junit/org/apache/tools/ant/types/PermissionsTest.java 
b/src/tests/junit/org/apache/tools/ant/types/PermissionsTest.java
index bbc7f1f4d..7578a25ab 100644
--- a/src/tests/junit/org/apache/tools/ant/types/PermissionsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/PermissionsTest.java
@@ -19,6 +19,8 @@
 package org.apache.tools.ant.types;
 
 import org.apache.tools.ant.ExitException;
+import org.apache.tools.ant.taskdefs.condition.JavaVersion;
+import org.apache.tools.ant.util.JavaEnvUtils;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
@@ -27,6 +29,7 @@ import org.junit.rules.ExpectedException;
 
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.hasProperty;
+import static org.junit.Assume.assumeTrue;
 
 /**
  * JUnit 4 testcases for org.apache.tools.ant.types.Permissions.
@@ -40,6 +43,11 @@ public class PermissionsTest {
 
     @Before
     public void setUp() {
+        final JavaVersion javaVersion = new JavaVersion();
+        javaVersion.setAtMost("17");
+        assumeTrue("org.apache.tools.ant.types.Permissions no longer supported 
on Java version: "
+                + JavaEnvUtils.getJavaVersion(), javaVersion.eval());
+
         perms = new Permissions();
         Permissions.Permission perm = new Permissions.Permission();
         // Grant extra permissions to read and write the user.* properties and 
read to the
@@ -87,7 +95,9 @@ public class PermissionsTest {
 
     @After
     public void tearDown() {
-        perms.restoreSecurityManager();
+        if (perms != null) {
+            perms.restoreSecurityManager();
+        }
     }
 
     /** Tests a permission that is granted per default. */

Reply via email to