You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by he...@apache.org on 2022/02/14 16:56:20 UTC

[commons-jexl] branch master updated: JEXL-357: foolproof getting package permissions thought package name;

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 fed413d  JEXL-357: foolproof getting package permissions thought package name;
     new 99054fb  Merge branch 'master' of https://gitbox.apache.org/repos/asf/commons-jexl
fed413d is described below

commit fed413dfa27ebb51dbeda1f173596d09c4e8d989
Author: henrib <he...@apache.org>
AuthorDate: Mon Feb 14 17:54:54 2022 +0100

    JEXL-357: foolproof getting package permissions thought package name;
---
 .../jexl3/internal/introspection/Permissions.java  | 82 +++++++++++++++++++---
 .../internal/introspection/PermissionsTest.java    | 19 +++++
 2 files changed, 90 insertions(+), 11 deletions(-)

diff --git a/src/main/java/org/apache/commons/jexl3/internal/introspection/Permissions.java b/src/main/java/org/apache/commons/jexl3/internal/introspection/Permissions.java
index 911f395..a2cebdf 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/introspection/Permissions.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/introspection/Permissions.java
@@ -17,6 +17,8 @@
 
 package org.apache.commons.jexl3.internal.introspection;
 
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
@@ -50,6 +52,20 @@ import org.apache.commons.jexl3.introspection.JexlPermissions;
  * not be altered using an instance of permissions using {@link JexlPermissions#parse(String...)}.</p>
  */
 public class Permissions implements JexlPermissions {
+    /**
+     * Java9 introduced Class.getPackageName(), use it if it exists.
+     */
+    private static final MethodHandle GETPKGNAME = getPackageNameHandle();
+    static MethodHandle getPackageNameHandle() {
+        MethodHandle mh;
+        try {
+            Method m = Class.class.getMethod("getPackageName");
+            mh = MethodHandles.lookup().unreflect(m);
+        } catch(Exception xm) {
+            mh = null;
+        }
+        return mh;
+    }
 
     /**
      * Equivalent of @NoJexl on a class in a package.
@@ -250,17 +266,61 @@ public class Permissions implements JexlPermissions {
         return allowed == null? Collections.emptySet() : Collections.unmodifiableSet(allowed);
     }
 
+
+    /**
+     * Gets the package name of a class (class.getPackage() may return null).
+     * @param clz the class
+     * @return the class package name
+     */
+    static String getPackageName(Class<?> clz) {
+        String pkgName = "";
+        if (clz != null) {
+            // use native if we can
+            if (GETPKGNAME != null) {
+                try {
+                    return (String) GETPKGNAME.invokeWithArguments(clz);
+                } catch(Throwable xany) {
+                    return "";
+                }
+            }
+            // remove array
+            Class<?> clazz = clz;
+            while(clazz.isArray()) {
+                clazz = clazz.getComponentType();
+            }
+            // mimic getPackageName()
+            if (clazz.isPrimitive()) {
+                return "java.lang";
+            }
+            // remove enclosing
+            Class<?> walk = clazz.getEnclosingClass();
+            while(walk != null) {
+                clazz = walk;
+                walk = walk.getEnclosingClass();
+            }
+            Package pkg = clazz.getPackage();
+            // pkg may be null for unobvious reasons
+            if (pkg == null) {
+                String name = clazz.getName();
+                int dot = name.lastIndexOf('.');
+                if (dot > 0) {
+                    pkgName = name.substring(0, dot);
+                }
+            } else {
+                pkgName = pkg.getName();
+            }
+        }
+        return pkgName;
+    }
+
     /**
      * Gets the package constraints.
-     * @param pack the package
+     * @param packageName the package name
      * @return the package constraints instance, not-null.
      */
-    private NoJexlPackage getNoJexl(Package pack) {
-        NoJexlPackage njp = packages.get(pack.getName());
-        if (njp != null) {
-            return njp;
-        }
-        return JEXL_PACKAGE;
+    private NoJexlPackage getNoJexlPackage(String packageName) {
+        NoJexlPackage njp = packages.get(packageName);
+        return njp != null? njp : JEXL_PACKAGE;
     }
 
     /**
@@ -270,7 +330,8 @@ public class Permissions implements JexlPermissions {
      * @return the class constraints instance, not-null.
      */
     private NoJexlClass getNoJexl(Class<?> clazz) {
-        NoJexlPackage njp = getNoJexl(clazz.getPackage());
+        String pkgName = getPackageName(clazz);
+        NoJexlPackage njp = getNoJexlPackage(pkgName);
         if (njp != null) {
             NoJexlClass njc = njp.getNoJexl(clazz);
             if (njc != null) {
@@ -286,7 +347,7 @@ public class Permissions implements JexlPermissions {
      * @return true if allowed, false otherwise
      */
     private boolean wildcardAllow(Class<?> clazz) {
-        return wildcardAllow(allowed, clazz.getPackage().getName());
+        return wildcardAllow(allowed, getPackageName(clazz));
     }
 
     /**
@@ -338,8 +399,7 @@ public class Permissions implements JexlPermissions {
         if (nojexl != null) {
             return true;
         }
-        Package pkg = clazz.getPackage();
-        NoJexlPackage njp = packages.get(pkg.getName());
+        NoJexlPackage njp = packages.get(getPackageName(clazz));
         return njp != null && Objects.equals(NOJEXL_CLASS, njp.getNoJexl(clazz));
     }
 
diff --git a/src/test/java/org/apache/commons/jexl3/internal/introspection/PermissionsTest.java b/src/test/java/org/apache/commons/jexl3/internal/introspection/PermissionsTest.java
index f9fdf4d..1cc6cf7 100644
--- a/src/test/java/org/apache/commons/jexl3/internal/introspection/PermissionsTest.java
+++ b/src/test/java/org/apache/commons/jexl3/internal/introspection/PermissionsTest.java
@@ -183,6 +183,25 @@ public class PermissionsTest {
     }
 
     @Test
+    public void testGetPackageName() {
+        final String PKG = "org.apache.commons.jexl3.internal.introspection";
+        String pkg = Permissions.getPackageName(Outer.class);
+        Assert.assertEquals(PKG, pkg);
+        pkg = Permissions.getPackageName(Outer.Inner.class);
+        Assert.assertEquals(PKG, pkg);
+        Outer[] oo = new Outer[0];
+        pkg = Permissions.getPackageName(oo.getClass());
+        Assert.assertEquals(PKG, pkg);
+        Outer.Inner[] ii = new Outer.Inner[0];
+        pkg = Permissions.getPackageName(ii.getClass());
+        Assert.assertEquals(PKG, pkg);
+        pkg = Permissions.getPackageName(Process.class);
+        Assert.assertEquals("java.lang", pkg);
+        pkg = Permissions.getPackageName(Integer.TYPE);
+        Assert.assertEquals("java.lang", pkg);
+    }
+
+    @Test
     public void testParsePermissions1() {
         String[] src = new String[]{
                 "java.lang.*",