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

Commit b2985209 authored by Sunny Goyal's avatar Sunny Goyal Committed by android-build-merger
Browse files

Preventing recursive referrence in drawables am: 99b25d28

am: ced997ec

Change-Id: Iab88125b030bfe21aad82a1b287495cb9e3f54a2
parents 7dbaf899 ced997ec
Loading
Loading
Loading
Loading
+55 −11
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@ import android.util.TypedValue;
import android.util.Xml;
import android.view.DisplayAdjustments;

import com.android.internal.util.GrowingArrayUtils;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

@@ -117,6 +119,13 @@ public class ResourcesImpl {
    private final ConfigurationBoundResourceCache<StateListAnimator> mStateListAnimatorCache =
            new ConfigurationBoundResourceCache<>();

    // A stack of all the resourceIds already referenced when parsing a resource. This is used to
    // detect circular references in the xml.
    // Using a ThreadLocal variable ensures that we have different stacks for multiple parallel
    // calls to ResourcesImpl
    private final ThreadLocal<LookupStack> mLookupStack =
            ThreadLocal.withInitial(() -> new LookupStack());

    /** Size of the cyclical cache used to map XML files to blocks. */
    private static final int XML_BLOCK_CACHE_SIZE = 4;

@@ -784,6 +793,13 @@ public class ResourcesImpl {
        final Drawable dr;

        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
        LookupStack stack = mLookupStack.get();
        try {
            // Perform a linear search to check if we have already referenced this resource before.
            if (stack.contains(id)) {
                throw new Exception("Recursive reference in drawable");
            }
            stack.push(id);
            try {
                if (file.endsWith(".xml")) {
                    final XmlResourceParser rp = loadXmlResourceParser(
@@ -796,7 +812,10 @@ public class ResourcesImpl {
                    dr = Drawable.createFromResourceStream(wrapper, value, is, file, null);
                    is.close();
                }
        } catch (Exception | StackOverflowError e) {
            } finally {
                stack.pop();
            }
        } catch (Exception e) {
            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
            final NotFoundException rnf = new NotFoundException(
                    "File " + file + " from drawable resource ID #0x" + Integer.toHexString(id));
@@ -1377,4 +1396,29 @@ public class ResourcesImpl {
            }
        }
    }

    private static class LookupStack {

        // Pick a reasonable default size for the array, it is grown as needed.
        private int[] mIds = new int[4];
        private int mSize = 0;

        public void push(int id) {
            mIds = GrowingArrayUtils.append(mIds, mSize, id);
            mSize++;
        }

        public boolean contains(int id) {
            for (int i = 0; i < mSize; i++) {
                if (mIds[i] == id) {
                    return true;
                }
            }
            return false;
        }

        public void pop() {
            mSize--;
        }
    }
}