diff --git a/src/main/java/org/jenkinsci/plugins/scriptsecurity/sandbox/whitelists/EnumeratingWhitelist.java b/src/main/java/org/jenkinsci/plugins/scriptsecurity/sandbox/whitelists/EnumeratingWhitelist.java index 944296138..c9b19d33c 100644 --- a/src/main/java/org/jenkinsci/plugins/scriptsecurity/sandbox/whitelists/EnumeratingWhitelist.java +++ b/src/main/java/org/jenkinsci/plugins/scriptsecurity/sandbox/whitelists/EnumeratingWhitelist.java @@ -314,7 +314,7 @@ static String canonicalStaticFieldSig(@NonNull Field field) { public static class MethodSignature extends Signature { final String receiverType, method; final String[] argumentTypes; - public MethodSignature(String receiverType, String method, String[] argumentTypes) { + public MethodSignature(String receiverType, String method, String... argumentTypes) { this.receiverType = receiverType; this.method = method; this.argumentTypes = argumentTypes.clone(); @@ -360,7 +360,7 @@ public boolean isWildcard() { } static class StaticMethodSignature extends MethodSignature { - StaticMethodSignature(String receiverType, String method, String[] argumentTypes) { + StaticMethodSignature(String receiverType, String method, String... argumentTypes) { super(receiverType, method, argumentTypes); } @Override public String toString() { diff --git a/src/main/resources/org/jenkinsci/plugins/scriptsecurity/sandbox/whitelists/generic-whitelist b/src/main/resources/org/jenkinsci/plugins/scriptsecurity/sandbox/whitelists/generic-whitelist index a28598f15..5504e45b8 100644 --- a/src/main/resources/org/jenkinsci/plugins/scriptsecurity/sandbox/whitelists/generic-whitelist +++ b/src/main/resources/org/jenkinsci/plugins/scriptsecurity/sandbox/whitelists/generic-whitelist @@ -115,6 +115,7 @@ staticMethod java.lang.Boolean parseBoolean java.lang.String staticMethod java.lang.Boolean valueOf boolean staticMethod java.lang.Boolean valueOf java.lang.String method java.lang.CharSequence charAt int +method java.lang.CharSequence isEmpty method java.lang.CharSequence length method java.lang.CharSequence subSequence int int method java.lang.Class getName @@ -773,6 +774,14 @@ staticField java.util.concurrent.TimeUnit HOURS staticField java.util.concurrent.TimeUnit MILLISECONDS staticField java.util.concurrent.TimeUnit MINUTES staticField java.util.concurrent.TimeUnit SECONDS +method java.util.random.RandomGenerator nextBoolean +method java.util.random.RandomGenerator nextBytes byte[] +method java.util.random.RandomGenerator nextDouble +method java.util.random.RandomGenerator nextFloat +method java.util.random.RandomGenerator nextGaussian +method java.util.random.RandomGenerator nextInt +method java.util.random.RandomGenerator nextInt int +method java.util.random.RandomGenerator nextLong method java.util.regex.MatchResult end method java.util.regex.MatchResult end int method java.util.regex.MatchResult group diff --git a/src/test/java/org/jenkinsci/plugins/scriptsecurity/sandbox/whitelists/EnumeratingWhitelistTest.java b/src/test/java/org/jenkinsci/plugins/scriptsecurity/sandbox/whitelists/EnumeratingWhitelistTest.java index ec6d38349..5252e266e 100644 --- a/src/test/java/org/jenkinsci/plugins/scriptsecurity/sandbox/whitelists/EnumeratingWhitelistTest.java +++ b/src/test/java/org/jenkinsci/plugins/scriptsecurity/sandbox/whitelists/EnumeratingWhitelistTest.java @@ -78,8 +78,8 @@ public void m(Object[] args) {} assertFalse(new EnumeratingWhitelist.MethodSignature(HashMap.class, "size").exists()); assertTrue(new EnumeratingWhitelist.MethodSignature(Map.class, "size").exists()); assertTrue(new EnumeratingWhitelist.MethodSignature(Map.Entry.class, "getKey").exists()); - assertTrue(new EnumeratingWhitelist.MethodSignature("java.util.Map$Entry", "getKey", new String[0]).exists()); - assertThrows(ClassNotFoundException.class, new EnumeratingWhitelist.MethodSignature("java.util.Map.Entry", "getKey", new String[0])::exists); + assertTrue(new EnumeratingWhitelist.MethodSignature("java.util.Map$Entry", "getKey").exists()); + assertThrows(ClassNotFoundException.class, new EnumeratingWhitelist.MethodSignature("java.util.Map.Entry", "getKey")::exists); } @Test diff --git a/src/test/java/org/jenkinsci/plugins/scriptsecurity/sandbox/whitelists/StaticWhitelistTest.java b/src/test/java/org/jenkinsci/plugins/scriptsecurity/sandbox/whitelists/StaticWhitelistTest.java index e12273ea4..b9482f364 100644 --- a/src/test/java/org/jenkinsci/plugins/scriptsecurity/sandbox/whitelists/StaticWhitelistTest.java +++ b/src/test/java/org/jenkinsci/plugins/scriptsecurity/sandbox/whitelists/StaticWhitelistTest.java @@ -37,6 +37,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Random; import java.util.Set; import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.EnumeratingWhitelist.MethodSignature; @@ -98,26 +99,50 @@ static void sanity(URL definition) throws Exception { for (EnumeratingWhitelist.Signature sig : sigs) { + if (KNOWN_GOOD_SIGNATURES.contains(sig)) { + continue; + } try { assertTrue(sig + " does not exist (or is an override)", sig.exists()); } catch (ClassNotFoundException x) { - if (!KNOWN_GOOD_SIGNATURES.contains(sig)) { - throw new Exception("Unable to verify existence of " + sig, x); - } + // Wrapping exception to include the full signature in the error message. + throw new Exception("Unable to verify existence of " + sig, x); } } } /** - * A set of signatures that are well-formed, but for which {@link Signature#exists} throws an exception because - * they involve types that are not available on the classpath when these tests run. + * A set of signatures that are well-formed, but for which {@link Signature#exists} may throw an exception depending + * on the test environment. */ private static final Set KNOWN_GOOD_SIGNATURES = new HashSet<>(Arrays.asList( - // From blacklist - new MethodSignature("org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper", "getRawBuild", new String[0]), - // From generic-whitelist + // From workflow-support, which is not a dependency of this plugin. + new MethodSignature("org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper", "getRawBuild"), + // From groovy-cps, which is not a dependency of this plugin. new StaticMethodSignature("com.cloudbees.groovy.cps.CpsDefaultGroovyMethods", "each", - new String[] { "java.util.Iterator", "groovy.lang.Closure" }) + "java.util.Iterator", "groovy.lang.Closure"), + // Overrides CharSequence.isEmpty in Java 15+. + new MethodSignature(String.class, "isEmpty"), + // Does not exist until Java 15. + new MethodSignature(CharSequence.class, "isEmpty"), + // Override the corresponding RandomGenerator methods in Java 17+. + new MethodSignature(Random.class, "nextBoolean"), + new MethodSignature(Random.class, "nextBytes", byte[].class), + new MethodSignature(Random.class, "nextDouble"), + new MethodSignature(Random.class, "nextFloat"), + new MethodSignature(Random.class, "nextGaussian"), + new MethodSignature(Random.class, "nextInt"), + new MethodSignature(Random.class, "nextInt", int.class), + new MethodSignature(Random.class, "nextLong"), + // Do not exist until Java 17. + new MethodSignature("java.util.random.RandomGenerator", "nextBoolean"), + new MethodSignature("java.util.random.RandomGenerator", "nextBytes", "byte[]"), + new MethodSignature("java.util.random.RandomGenerator", "nextDouble"), + new MethodSignature("java.util.random.RandomGenerator", "nextFloat"), + new MethodSignature("java.util.random.RandomGenerator", "nextGaussian"), + new MethodSignature("java.util.random.RandomGenerator", "nextInt"), + new MethodSignature("java.util.random.RandomGenerator", "nextInt", "int"), + new MethodSignature("java.util.random.RandomGenerator", "nextLong") )); @Test public void sanity() throws Exception {