1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jexl3.internal.introspection;
18
19 import static org.apache.commons.jexl3.introspection.JexlPermissions.RESTRICTED;
20 import static org.apache.commons.jexl3.introspection.JexlPermissions.SECURE;
21 import static org.junit.jupiter.api.Assertions.assertFalse;
22 import static org.junit.jupiter.api.Assertions.assertNotNull;
23 import static org.junit.jupiter.api.Assertions.assertNull;
24 import static org.junit.jupiter.api.Assertions.assertTrue;
25 import static org.junit.jupiter.api.Assumptions.assumeTrue;
26
27 import java.lang.reflect.Method;
28 import java.nio.ByteBuffer;
29 import java.util.Collection;
30 import java.util.ListResourceBundle;
31 import java.util.Locale;
32 import java.util.ResourceBundle;
33 import java.util.TimeZone;
34 import java.util.Timer;
35 import java.util.TimerTask;
36 import java.util.concurrent.CompletableFuture;
37 import java.util.concurrent.Phaser;
38 import java.util.concurrent.Semaphore;
39 import java.util.stream.BaseStream;
40
41 import org.apache.commons.jexl3.introspection.JexlUberspect;
42 import org.junit.jupiter.api.Test;
43
44
45
46
47
48
49 class PermissionsRestrictedSweepTest {
50
51 private static Method getMethod(final Class<?> clazz, final String name) {
52 for (final Method method : clazz.getMethods()) {
53 if (method.getName().equals(name)) {
54 return method;
55 }
56 }
57 throw new AssertionError("Missing method: " + clazz.getName() + "#" + name);
58 }
59
60
61 private static Class<?> forName(final String name) {
62 try {
63 return Class.forName(name);
64 } catch (final ClassNotFoundException xnf) {
65 return null;
66 }
67 }
68
69 @Test
70 void testProcessHandleDenied() {
71
72 final Class<?> processHandle = forName("java.lang.ProcessHandle");
73 assumeTrue(processHandle != null);
74 final Class<?> processHandleInfo = forName("java.lang.ProcessHandle$Info");
75 assertFalse(RESTRICTED.allow(processHandle));
76 assertFalse(RESTRICTED.allow(processHandleInfo));
77 assertFalse(RESTRICTED.allow(getMethod(processHandle, "current")));
78 assertFalse(RESTRICTED.allow(getMethod(processHandle, "allProcesses")));
79 assertFalse(RESTRICTED.allow(getMethod(processHandle, "destroyForcibly")));
80 final JexlUberspect uber = new Uberspect(null, null, RESTRICTED);
81 assertNull(uber.getClassByName("java.lang.ProcessHandle"));
82 }
83
84 @Test
85 void testWholeClassDenialCoversNestedClasses() {
86
87
88 final Class<?> loggerFinder = forName("java.lang.System$LoggerFinder");
89 if (loggerFinder != null) {
90 assertFalse(RESTRICTED.allow(loggerFinder));
91 }
92 assertFalse(RESTRICTED.allow(ProcessBuilder.Redirect.class));
93 assertFalse(RESTRICTED.allow(Thread.State.class));
94
95 assertTrue(RESTRICTED.allow(java.util.Map.Entry.class));
96 }
97
98 @Test
99 void testModuleAndResourceLoadingDenied() {
100
101 final Class<?> module = forName("java.lang.Module");
102 assumeTrue(module != null);
103 assertFalse(RESTRICTED.allow(module));
104 assertFalse(RESTRICTED.allow(forName("java.lang.ModuleLayer")));
105 assertFalse(RESTRICTED.allow(getMethod(module, "getResourceAsStream")));
106
107 assertFalse(RESTRICTED.allow(ResourceBundle.Control.class));
108 assertFalse(RESTRICTED.allow(getMethod(ResourceBundle.Control.class, "newBundle")));
109
110 assertFalse(RESTRICTED.allow(ListResourceBundle.class));
111
112 assertFalse(RESTRICTED.allow(getMethod(ResourceBundle.class, "getBundle")));
113 assertTrue(RESTRICTED.allow(getMethod(ResourceBundle.class, "getString")));
114 }
115
116 @Test
117 void testGlobalMutatorsDenied() {
118
119 for (final org.apache.commons.jexl3.introspection.JexlPermissions p
120 : new org.apache.commons.jexl3.introspection.JexlPermissions[] { RESTRICTED, SECURE }) {
121 assertFalse(p.allow(getMethod(Locale.class, "setDefault")));
122 assertFalse(p.allow(getMethod(TimeZone.class, "setDefault")));
123 }
124
125 assertTrue(RESTRICTED.allow(getMethod(Locale.class, "getDefault")));
126 assertTrue(RESTRICTED.allow(getMethod(TimeZone.class, "getDefault")));
127 }
128
129 @Test
130 void testUninterruptibleBlockersDenied() {
131
132 assertFalse(RESTRICTED.allow(getMethod(CompletableFuture.class, "join")));
133 assertFalse(RESTRICTED.allow(getMethod(Semaphore.class, "acquireUninterruptibly")));
134 assertFalse(RESTRICTED.allow(getMethod(Phaser.class, "awaitAdvance")));
135 assertFalse(RESTRICTED.allow(getMethod(Phaser.class, "arriveAndAwaitAdvance")));
136
137 assertTrue(RESTRICTED.allow(getMethod(CompletableFuture.class, "get")));
138 assertTrue(RESTRICTED.allow(getMethod(Semaphore.class, "acquire")));
139 assertTrue(RESTRICTED.allow(getMethod(Phaser.class, "awaitAdvanceInterruptibly")));
140
141 assertFalse(RESTRICTED.allow(Timer.class));
142 assertFalse(RESTRICTED.allow(TimerTask.class));
143 }
144
145 @Test
146 void testResourceBurnDenied() {
147
148 assertFalse(RESTRICTED.allow(getMethod(BaseStream.class, "parallel")));
149 assertFalse(RESTRICTED.allow(getMethod(Collection.class, "parallelStream")));
150 assertFalse(RESTRICTED.allow(getMethod(ByteBuffer.class, "allocateDirect")));
151
152 assertTrue(RESTRICTED.allow(getMethod(BaseStream.class, "sequential")));
153 assertTrue(RESTRICTED.allow(getMethod(Collection.class, "stream")));
154 assertTrue(RESTRICTED.allow(getMethod(ByteBuffer.class, "allocate")));
155 final Method spliterator = getMethod(Collection.class, "spliterator");
156 assertNotNull(spliterator);
157 assertTrue(RESTRICTED.allow(spliterator));
158 }
159 }