diff options
author | Ryan Mitchell <rtmitchell@google.com> | 2020-01-15 11:43:47 -0800 |
---|---|---|
committer | Anis Assi <anisassi@google.com> | 2020-02-06 15:17:36 -0800 |
commit | b7a2a333232ae9ba60797918f75d9f50a3a856f0 (patch) | |
tree | 2a46f84224b82b7f5ff22d074aeb7b0d7f07b256 | |
parent | 35c455959054dc61237d2fe20a5d4ace6103393d (diff) | |
download | base-b7a2a333232ae9ba60797918f75d9f50a3a856f0.tar.gz |
Fix potential double destroy of AssetManagerandroid-8.1.0_r75
Assume there is a XmlBlock [X] created by a AssetManager [A]
([A] will have mNumRefs = 2). After [A].close is called
(mNumRefs = 1) and then both [X] and [A] are going to be GCed,
if [A].finalize is called first (nativeDestroy), the later
[X].finalize will invoke [A].xmlBlockGone that triggers the
second nativeDestroy of [A] and leads to crash.
By clearing the mObject in AssetManager.finalize, the
decRefsLocked from other paths won't call nativeDestroy again.
Bug: 144028297
Test: atest android.security.cts.AssetManagerTest
Change-Id: Ia938502d2443f5a6de6a3cabdb7ce1d41d3ff6d1
Merged-In: Ia938502d2443f5a6de6a3cabdb7ce1d41d3ff6d1
(cherry picked from commit 93320661ca9a23c7b38b3f166d0facf048f2a8a3)
-rw-r--r-- | core/java/android/content/res/AssetManager.java | 71 |
1 files changed, 39 insertions, 32 deletions
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index f0adcd6cfb3e..4a187cd774bb 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -68,24 +68,24 @@ public final class AssetManager implements AutoCloseable { private static final String TAG = "AssetManager"; private static final boolean localLOGV = false || false; - + private static final boolean DEBUG_REFS = false; - + private static final Object sSync = new Object(); /*package*/ static AssetManager sSystem = null; private final TypedValue mValue = new TypedValue(); private final long[] mOffsets = new long[2]; - + // For communication with native code. private long mObject; private StringBlock mStringBlocks[] = null; - + private int mNumRefs = 1; private boolean mOpen = true; private HashMap<Long, RuntimeException> mRefStacks; - + /** * Create a new AssetManager containing only the basic system assets. * Applications will not generally use this method, instead retrieving the @@ -114,7 +114,7 @@ public final class AssetManager implements AutoCloseable { } } } - + private AssetManager(boolean isSystem) { if (DEBUG_REFS) { synchronized (this) { @@ -337,10 +337,10 @@ public final class AssetManager implements AutoCloseable { * Open an asset using ACCESS_STREAMING mode. This provides access to * files that have been bundled with an application as assets -- that is, * files placed in to the "assets" directory. - * + * * @param fileName The name of the asset to open. This name can be * hierarchical. - * + * * @see #open(String, int) * @see #list */ @@ -353,11 +353,11 @@ public final class AssetManager implements AutoCloseable { * read its contents. This provides access to files that have been bundled * with an application as assets -- that is, files placed in to the * "assets" directory. - * + * * @param fileName The name of the asset to open. This name can be * hierarchical. * @param accessMode Desired access mode for retrieving the data. - * + * * @see #ACCESS_UNKNOWN * @see #ACCESS_STREAMING * @see #ACCESS_RANDOM @@ -397,14 +397,14 @@ public final class AssetManager implements AutoCloseable { /** * Return a String array of all the assets at the given path. - * + * * @param path A relative path within the assets, i.e., "docs/home.html". - * + * * @return String[] Array of strings, one for each asset. These file * names are relative to 'path'. You can open the file by * concatenating 'path' and a name in the returned string (via * File) and passing that to open(). - * + * * @see #open */ public native final String[] list(String path) @@ -416,7 +416,7 @@ public final class AssetManager implements AutoCloseable { * provides direct access to all of the files included in an application * package (not only its assets). Applications should not normally use * this. - * + * * @see #open(String) */ public final InputStream openNonAsset(String fileName) throws IOException { @@ -429,7 +429,7 @@ public final class AssetManager implements AutoCloseable { * provides direct access to all of the files included in an application * package (not only its assets). Applications should not normally use * this. - * + * * @see #open(String, int) */ public final InputStream openNonAsset(String fileName, int accessMode) @@ -440,7 +440,7 @@ public final class AssetManager implements AutoCloseable { /** * {@hide} * Open a non-asset in a specified package. Not for use by applications. - * + * * @param cookie Identifier of the package to be opened. * @param fileName Name of the asset to retrieve. */ @@ -452,7 +452,7 @@ public final class AssetManager implements AutoCloseable { /** * {@hide} * Open a non-asset in a specified package. Not for use by applications. - * + * * @param cookie Identifier of the package to be opened. * @param fileName Name of the asset to retrieve. * @param accessMode Desired access mode for retrieving the data. @@ -477,7 +477,7 @@ public final class AssetManager implements AutoCloseable { throws IOException { return openNonAssetFd(0, fileName); } - + public final AssetFileDescriptor openNonAssetFd(int cookie, String fileName) throws IOException { synchronized (this) { @@ -492,20 +492,20 @@ public final class AssetManager implements AutoCloseable { } throw new FileNotFoundException("Asset absolute file: " + fileName); } - + /** * Retrieve a parser for a compiled XML file. - * + * * @param fileName The name of the file to retrieve. */ public final XmlResourceParser openXmlResourceParser(String fileName) throws IOException { return openXmlResourceParser(0, fileName); } - + /** * Retrieve a parser for a compiled XML file. - * + * * @param cookie Identifier of the package to be opened. * @param fileName The name of the file to retrieve. */ @@ -521,7 +521,7 @@ public final class AssetManager implements AutoCloseable { * {@hide} * Retrieve a non-asset as a compiled XML file. Not for use by * applications. - * + * * @param fileName The name of the file to retrieve. */ /*package*/ final XmlBlock openXmlBlockAsset(String fileName) @@ -533,7 +533,7 @@ public final class AssetManager implements AutoCloseable { * {@hide} * Retrieve a non-asset as a compiled XML file. Not for use by * applications. - * + * * @param cookie Identifier of the package to be opened. * @param fileName Name of the asset to retrieve. */ @@ -588,12 +588,18 @@ public final class AssetManager implements AutoCloseable { } } } - destroy(); + + synchronized (this) { + if (mObject != 0) { + destroy(); + mObject = 0; + } + } } finally { super.finalize(); } } - + public final class AssetInputStream extends InputStream { /** * @hide @@ -796,7 +802,7 @@ public final class AssetManager implements AutoCloseable { /*package*/ native final String getResourcePackageName(int resid); /*package*/ native final String getResourceTypeName(int resid); /*package*/ native final String getResourceEntryName(int resid); - + private native final long openAsset(String fileName, int accessMode); private final native ParcelFileDescriptor openAssetFd(String fileName, long[] outOffsets) throws IOException; @@ -856,17 +862,17 @@ public final class AssetManager implements AutoCloseable { * {@hide} */ public native static final int getGlobalAssetCount(); - + /** * {@hide} */ public native static final String getAssetAllocations(); - + /** * {@hide} */ public native static final int getGlobalAssetManagerCount(); - + private native final long newTheme(); private native final void deleteTheme(long theme); /*package*/ native static final void applyThemeStyle(long theme, int styleRes, boolean force); @@ -899,7 +905,7 @@ public final class AssetManager implements AutoCloseable { } mNumRefs++; } - + private final void decRefsLocked(long id) { if (DEBUG_REFS && mRefStacks != null) { mRefStacks.remove(id); @@ -907,8 +913,9 @@ public final class AssetManager implements AutoCloseable { mNumRefs--; //System.out.println("Dec streams: mNumRefs=" + mNumRefs // + " mReleased=" + mReleased); - if (mNumRefs == 0) { + if (mNumRefs == 0 && mObject != 0) { destroy(); + mObject = 0; } } } |