Loading core/java/android/content/res/ResourcesImpl.java +55 −11 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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( Loading @@ -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)); Loading Loading @@ -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--; } } } Loading
core/java/android/content/res/ResourcesImpl.java +55 −11 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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( Loading @@ -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)); Loading Loading @@ -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--; } } }