This is an automated email from the ASF dual-hosted git repository.
henrib pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jexl.git
The following commit(s) were added to refs/heads/master by this push:
new 757dcb9 JEXL-253: Added public API to allow creation of inheritable
permissions in sandbox; added tests Task #JEXL-253 - Permissions by super type
in JexlSandbox
757dcb9 is described below
commit 757dcb90f2ca2ba92fd9ec43291deb4305eee02c
Author: henrib <[email protected]>
AuthorDate: Mon Jun 17 16:36:39 2019 +0200
JEXL-253: Added public API to allow creation of inheritable permissions in
sandbox; added tests
Task #JEXL-253 - Permissions by super type in JexlSandbox
---
RELEASE-NOTES.txt | 1 +
.../commons/jexl3/introspection/JexlSandbox.java | 39 ++++++++---
.../commons/jexl3/scripting/JexlScriptEngine.java | 2 +-
src/site/xdoc/changes.xml | 7 +-
.../commons/jexl3/introspection/SandboxTest.java | 80 ++++++++++++++++------
5 files changed, 97 insertions(+), 32 deletions(-)
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 9d01ebe..44dba2a 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -56,6 +56,7 @@ New Features in 3.2:
* JEXL-273: Add do...while(...) loops
* JEXL-264: Allow space, quote & double-quote in identifiers
* JEXL-260: Automatically inject JexlContext in constructor call when
possible
+* JEXL-253: Permissions by super type in JexlSandbox
* JEXL-252: Allow for interpolated strings to be used in property access
operators
* JEXL-250: Safe navigation operator (?.)
* JEXL-248: Allow range subexpression as an array property assignment
identifier
diff --git
a/src/main/java/org/apache/commons/jexl3/introspection/JexlSandbox.java
b/src/main/java/org/apache/commons/jexl3/introspection/JexlSandbox.java
index fecacb7..178e95b 100644
--- a/src/main/java/org/apache/commons/jexl3/introspection/JexlSandbox.java
+++ b/src/main/java/org/apache/commons/jexl3/introspection/JexlSandbox.java
@@ -24,8 +24,8 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
- * A sandbox describes permissions on a class by explicitly allowing or
forbidding access to methods and properties
- * through "whitelists" and "blacklists".
+ * A sandbox describes permissions on a class by explicitly allowing or
forbidding
+ * access to methods and properties through "whitelists" and "blacklists".
*
* <p>A <b>whitelist</b> explicitly allows methods/properties for a class;</p>
*
@@ -43,16 +43,25 @@ import java.util.concurrent.ConcurrentHashMap;
* <li>If it is not empty, the only forbidden properties/methods are the
ones contained.</li>
* </ul>
*
- * <p>Permissions are composed of three lists, read, write, execute, each
being "white" or "black":</p>
+ * <p>Permissions are composed of three lists, read, write, execute, each being
+ * "white" or "black":</p>
*
* <ul>
* <li><b>read</b> controls readable properties </li>
* <li><b>write</b> controls writable properties</li>
* <li><b>execute</b> controls executable methods and constructor</li>
* </ul>
+ *
+ * <p>When specified, permissions - white or black lists - can be created
inheritable
+ * on interfaces or classes and thus applicable to their implementations or
derived
+ * classes; the sandbox must be created with the 'inheritable' flag for this
behavior
+ * to be triggered. Note that even in this configuration, it is still possible
to
+ * add non-inheritable permissions.
+ * Adding inheritable lists to a non inheritable sandbox has no added effect;
+ * permissions only apply to their specified class.</p>
*
- * <p>Note that a JexlUberspect always uses a copy of the JexlSandbox used to
built it to avoid synchronization and/or
- * concurrent modifications at runtime.</p>
+ * <p>Note that a JexlUberspect always uses a <em>copy</em> of the JexlSandbox
+ * used to built it preventing permission changes after its instantiation.</p>
*
* @since 3.0
*/
@@ -76,7 +85,7 @@ public final class JexlSandbox {
* sandbox is a white-box, white-listing that class for all permissions
(read, write and execute).
*/
public JexlSandbox() {
- this(true, new HashMap<String, Permissions>());
+ this(true, false, null);
}
/**
@@ -88,15 +97,26 @@ public final class JexlSandbox {
* @since 3.1
*/
public JexlSandbox(boolean wb) {
- this(wb, new HashMap<String, Permissions>());
+ this(wb, false, null);
+ }
+
+ /**
+ * Creates a sandbox.
+ * @param wb whether this sandbox is white (true) or black (false)
+ * @param inh whether permissions on interfaces and classes are inherited
(true) or not (false)
+ * @since 3.2
+ */
+ public JexlSandbox(boolean wb, boolean inh) {
+ this(wb, inh, null);
}
/**
* Creates a sandbox based on an existing permissions map.
* @param map the permissions map
*/
+ @Deprecated
protected JexlSandbox(Map<String, Permissions> map) {
- this(true, map);
+ this(true, false, map);
}
/**
@@ -105,6 +125,7 @@ public final class JexlSandbox {
* @param map the permissions map
* @since 3.1
*/
+ @Deprecated
protected JexlSandbox(boolean wb, Map<String, Permissions> map) {
this(wb, false, map);
}
@@ -119,7 +140,7 @@ public final class JexlSandbox {
protected JexlSandbox(boolean wb, boolean inh, Map<String, Permissions>
map) {
white = wb;
inherit = inh;
- sandbox = map;
+ sandbox = map != null? map : new HashMap<String, Permissions>();
}
/**
diff --git
a/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngine.java
b/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngine.java
index 73cf14c..fdf11e2 100644
--- a/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngine.java
+++ b/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngine.java
@@ -96,7 +96,7 @@ public class JexlScriptEngine extends AbstractScriptEngine
implements Compilable
/**
* Implements engine and engine context properties for use by JEXL scripts.
- * Those properties are allways bound to the default engine scope context.
+ * Those properties are always bound to the default engine scope context.
*
* <p>The following properties are defined:</p>
*
diff --git a/src/site/xdoc/changes.xml b/src/site/xdoc/changes.xml
index 709b5ac..800064e 100644
--- a/src/site/xdoc/changes.xml
+++ b/src/site/xdoc/changes.xml
@@ -119,11 +119,14 @@
<action dev="henrib" type="add" issue="JEXL-261">
JexlEngine.setClassLoader(...) should reload namespaces that
are classes
</action>
+ <action dev="henrib" type="add" issue="JEXL-260" due-to="Dmitri
Blinov">
+ Automatically inject JexlContext in constructor call when
possible
+ </action>
<action dev="henrib" type="fix" issue="JEXL-257" due-to="Dmitri
Blinov">
Function throwing IllegalArgumentException may be called twice
</action>
- <action dev="henrib" type="add" issue="JEXL-260" due-to="Dmitri
Blinov">
- Automatically inject JexlContext in constructor call when
possible
+ <action dev="henrib" type="add" issue="JEXL-253" due-to="Woonsan
Ko">
+ Permissions by super type in JexlSandbox
</action>
<action dev="henrib" type="add" issue="JEXL-252" due-to="Dmitri
Blinov">
Allow for interpolated strings to be used in property access
operators
diff --git
a/src/test/java/org/apache/commons/jexl3/introspection/SandboxTest.java
b/src/test/java/org/apache/commons/jexl3/introspection/SandboxTest.java
index 2f5f063..4e718c2 100644
--- a/src/test/java/org/apache/commons/jexl3/introspection/SandboxTest.java
+++ b/src/test/java/org/apache/commons/jexl3/introspection/SandboxTest.java
@@ -17,9 +17,7 @@
package org.apache.commons.jexl3.introspection;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import org.apache.commons.jexl3.JexlBuilder;
import org.apache.commons.jexl3.JexlContext;
import org.apache.commons.jexl3.JexlEngine;
@@ -384,36 +382,78 @@ public class SandboxTest extends JexlTestCase {
}
@Test
- public void testSandboxInherit() throws Exception {
+ public void testSandboxInherit0() throws Exception {
Object result;
JexlContext ctxt = null;
- Map<String, JexlSandbox.Permissions> perms = new HashMap<String,
JexlSandbox.Permissions>();
List<String> foo = new ArrayList<String>();
- JexlSandbox sandbox = new JexlSandbox(false, true, perms);
+ JexlSandbox sandbox = new JexlSandbox(false, true);
sandbox.white(java.util.List.class.getName());
- //sandbox.black(Foo.class.getName()).execute();
+
JexlEngine sjexl = new
JexlBuilder().sandbox(sandbox).strict(true).create();
JexlScript method = sjexl.createScript("foo.add(y)", "foo", "y");
JexlScript set = sjexl.createScript("foo[x] = y", "foo", "x", "y");
JexlScript get = sjexl.createScript("foo[x]", "foo", "x");
+
+ result = method.execute(ctxt, foo, "nothing");
+ Assert.assertEquals(true, result);
+ result = null;
+ result = get.execute(null, foo, 0);
+ Assert.assertEquals("nothing", result);
+ result = null;
+ result = set.execute(null, foo, 0, "42");
+ Assert.assertEquals("42", result);
+
+ result = null;
+ result = get.execute(null, foo, 0);
+ Assert.assertEquals("42", result);
+ }
+
+ public abstract static class Operation {
+ protected final int base;
+ public Operation(int sz) {
+ base = sz;
+ }
+
+ public abstract int someOp(int x);
+ public abstract int nonCallable(int y);
+ }
+
+ public static class Operation2 extends Operation {
+ public Operation2(int sz) {
+ super(sz);
+ }
+
+ @Override
+ public int someOp(int x) {
+ return base + x;
+ }
+
+ @Override
+ public int nonCallable(int y) {
+ throw new UnsupportedOperationException("do NOT call");
+ }
+ }
+
+ @Test
+ public void testSandboxInherit1() throws Exception {
+ Object result;
+ JexlContext ctxt = null;
+ Operation2 foo = new Operation2(12);
+ JexlSandbox sandbox = new JexlSandbox(false, true);
+ sandbox.white(Operation.class.getName());
+ sandbox.black(Operation.class.getName()).execute("nonCallable");
+ //sandbox.black(Foo.class.getName()).execute();
+ JexlEngine sjexl = new
JexlBuilder().sandbox(sandbox).strict(true).create();
+ JexlScript someOp = sjexl.createScript("foo.someOp(y)", "foo", "y");
+ result = someOp.execute(ctxt, foo, 30);
+ Assert.assertEquals(42, result);
+ JexlScript nonCallable = sjexl.createScript("foo.nonCallable(y)",
"foo", "y");
try {
- result = method.execute(ctxt, foo, "nothing");
- Assert.assertEquals(true, result);
- result = null;
- result = get.execute(null, foo, 0);
- Assert.assertEquals("nothing", result);
- result = null;
- result = set.execute(null, foo, 0, "42");
- Assert.assertEquals("42", result);
-
- result = null;
- result = get.execute(null, foo, 0);
- Assert.assertEquals("42", result);
- //Assert.fail("should have not been possible");
+ result = nonCallable.execute(null, foo, 0);
+ Assert.fail("should not be possible");
} catch (JexlException xjm) {
// ok
LOGGER.info(xjm.toString());
}
-
}
}