RESTRICT AUTOMERGE Preventing recursive referrence in drawables
Bug: 68706673 Bug: 66498711 Test: Added CTS tests Change-Id: I8034f49d16f9a7bc1749714fd6d6231bba5088d0 (cherry picked from commit I8034f49d16f9a7bc1749714fd6d6231bba5088d0) Merged-In: I8034f49d16f9a7bc1749714fd6d6231bba5088d0
This commit is contained in:
@@ -51,6 +51,8 @@ import android.util.TypedValue;
|
|||||||
import android.util.Xml;
|
import android.util.Xml;
|
||||||
import android.view.DisplayAdjustments;
|
import android.view.DisplayAdjustments;
|
||||||
|
|
||||||
|
import com.android.internal.util.GrowingArrayUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -106,6 +108,13 @@ public class ResourcesImpl {
|
|||||||
private final ConfigurationBoundResourceCache<StateListAnimator> mStateListAnimatorCache =
|
private final ConfigurationBoundResourceCache<StateListAnimator> mStateListAnimatorCache =
|
||||||
new ConfigurationBoundResourceCache<>();
|
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. */
|
/** Size of the cyclical cache used to map XML files to blocks. */
|
||||||
private static final int XML_BLOCK_CACHE_SIZE = 4;
|
private static final int XML_BLOCK_CACHE_SIZE = 4;
|
||||||
|
|
||||||
@@ -751,6 +760,13 @@ public class ResourcesImpl {
|
|||||||
final Drawable dr;
|
final Drawable dr;
|
||||||
|
|
||||||
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
|
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 {
|
try {
|
||||||
if (file.endsWith(".xml")) {
|
if (file.endsWith(".xml")) {
|
||||||
final XmlResourceParser rp = loadXmlResourceParser(
|
final XmlResourceParser rp = loadXmlResourceParser(
|
||||||
@@ -763,7 +779,10 @@ public class ResourcesImpl {
|
|||||||
dr = Drawable.createFromResourceStream(wrapper, value, is, file, null);
|
dr = Drawable.createFromResourceStream(wrapper, value, is, file, null);
|
||||||
is.close();
|
is.close();
|
||||||
}
|
}
|
||||||
} catch (Exception | StackOverflowError e) {
|
} finally {
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
|
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
|
||||||
final NotFoundException rnf = new NotFoundException(
|
final NotFoundException rnf = new NotFoundException(
|
||||||
"File " + file + " from drawable resource ID #0x" + Integer.toHexString(id));
|
"File " + file + " from drawable resource ID #0x" + Integer.toHexString(id));
|
||||||
@@ -1296,4 +1315,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--;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user