Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4985c5c7 authored by Mathew Inwood's avatar Mathew Inwood
Browse files

Experimental: verify cached constructors before use.

Caching constructors can cause problems for dynamically loaded code if
the same class name appears in more than on classloader. Before using
cached constructors, verifty that they come from a valid classloader, i.e.
one that appears in the classloader chain of the current contexts
classloader. Remove ones that do not from the map to allow the associated
classes to be unloaded in case they're no longer in use.

Bug: 21690610
Change-Id: I84f2894cd03a5dc0c33aed9cd710e4a1f6d9515f
parent b4270104
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -555,6 +555,26 @@ public abstract class LayoutInflater {
        }
    }

    private static final ClassLoader BOOT_CLASS_LOADER = LayoutInflater.class.getClassLoader();

    private final boolean verifyClassLoader(Constructor<? extends View> constructor) {
        final ClassLoader constructorLoader = constructor.getDeclaringClass().getClassLoader();
        if (constructorLoader == BOOT_CLASS_LOADER) {
            // fast path for boot class loader (most common case?) - always ok
            return true;
        }
        // in all normal cases (no dynamic code loading), we will exit the following loop on the
        // first iteration (i.e. when the declaring classloader is the contexts class loader).
        ClassLoader cl = mContext.getClassLoader();
        do {
            if (constructorLoader == cl) {
                return true;
            }
            cl = cl.getParent();
        } while (cl != null);
        return false;
    }

    /**
     * Low-level function for instantiating a view by name. This attempts to
     * instantiate a view class of the given <var>name</var> found in this
@@ -575,6 +595,10 @@ public abstract class LayoutInflater {
    public final View createView(String name, String prefix, AttributeSet attrs)
            throws ClassNotFoundException, InflateException {
        Constructor<? extends View> constructor = sConstructorMap.get(name);
        if (constructor != null && !verifyClassLoader(constructor)) {
            constructor = null;
            sConstructorMap.remove(name);
        }
        Class<? extends View> clazz = null;

        try {