diff options
| author | 2024-11-27 14:13:35 -0800 | |
|---|---|---|
| committer | 2024-12-02 16:26:53 -0800 | |
| commit | 93ff40f24d4054bbbaa5375ff2eae5f38e284d73 (patch) | |
| tree | ca3e4cf392c2edef625a4ea2102c521a2a7c97f2 /libs/androidfw/include | |
| parent | ed6a189ec9abe44f4c15404dc236dec1c8a0b117 (diff) | |
[res] Make TargetResourcesContainer valid after an error
ApkResourcesContainer class has a variant that is either a zip
file object, or a full blown AssetManager with ApkAssets with
the same zip file inside. But if transition from one to the
other fails, it could end up in a state with neither, causing a
crash if the users try accessing it.
This change ensures that:
1. The zip file object is only moved into ApkAssets if the
loading succeeds
2. If any part of the further initialization of ResState fails,
we take the zip file out and put it back into the variant
+ Add unit tests for both ApkAssets and libidmap2 to ensure
they don't crash in any of those scenarios (they used to)
+ Enable root tests in libidmap2 as they were never running
Flag: EXEMPT bugfix
Bug: 381108280
Test: atest libandroidfw_tests idmap2_tests + boot
Change-Id: I8f4803fdf03a41ba7a6892e6aed07f04b77788ce
Diffstat (limited to 'libs/androidfw/include')
| -rw-r--r-- | libs/androidfw/include/androidfw/ApkAssets.h | 58 |
1 files changed, 47 insertions, 11 deletions
diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h index 1fa67528c78b..231808beb718 100644 --- a/libs/androidfw/include/androidfw/ApkAssets.h +++ b/libs/androidfw/include/androidfw/ApkAssets.h @@ -47,13 +47,37 @@ class ApkAssets : public RefBase { package_property_t flags = 0U, off64_t offset = 0, off64_t len = AssetsProvider::kUnknownLength); + // // Creates an ApkAssets from an AssetProvider. - // The ApkAssets will take care of destroying the AssetsProvider when it is destroyed. - static ApkAssetsPtr Load(std::unique_ptr<AssetsProvider> assets, package_property_t flags = 0U); + // The ApkAssets will take care of destroying the AssetsProvider when it is destroyed; + // the original argument is not moved from if loading fails. + // + // Note: this function takes care of the case when you pass a move(unique_ptr<Derived>) + // that would create a temporary unique_ptr<AssetsProvider> by moving your pointer into + // it before the function call, making it impossible to not move from the parameter + // on loading failure. The two overloads take care of moving the pointer back if needed. + // + + template <class T> + static ApkAssetsPtr Load(std::unique_ptr<T>&& assets, package_property_t flags = 0U) + requires(std::is_same_v<T, AssetsProvider>) { + return LoadImpl(std::move(assets), flags); + } + + template <class T> + static ApkAssetsPtr Load(std::unique_ptr<T>&& assets, package_property_t flags = 0U) + requires(!std::is_same_v<T, AssetsProvider> && std::is_base_of_v<AssetsProvider, T>) { + std::unique_ptr<AssetsProvider> base_assets(std::move(assets)); + auto res = LoadImpl(std::move(base_assets), flags); + if (!res) { + assets.reset(static_cast<T*>(base_assets.release())); + } + return res; + } // Creates an ApkAssets from the given asset file representing a resources.arsc. - static ApkAssetsPtr LoadTable(std::unique_ptr<Asset> resources_asset, - std::unique_ptr<AssetsProvider> assets, + static ApkAssetsPtr LoadTable(std::unique_ptr<Asset>&& resources_asset, + std::unique_ptr<AssetsProvider>&& assets, package_property_t flags = 0U); // Creates an ApkAssets from an IDMAP, which contains the original APK path, and the overlay @@ -94,17 +118,29 @@ class ApkAssets : public RefBase { bool IsUpToDate() const; + // DANGER! + // This is a destructive method that rips the assets provider out of ApkAssets object. + // It is only useful when one knows this assets object can't be used anymore, and they + // need the underlying assets provider back (e.g. when initialization fails for some + // reason). + std::unique_ptr<AssetsProvider> TakeAssetsProvider() && { + return std::move(assets_provider_); + } + private: - static ApkAssetsPtr LoadImpl(std::unique_ptr<AssetsProvider> assets, + static ApkAssetsPtr LoadImpl(std::unique_ptr<AssetsProvider>&& assets, package_property_t property_flags, - std::unique_ptr<Asset> idmap_asset, - std::unique_ptr<LoadedIdmap> loaded_idmap); + std::unique_ptr<Asset>&& idmap_asset, + std::unique_ptr<LoadedIdmap>&& loaded_idmap); - static ApkAssetsPtr LoadImpl(std::unique_ptr<Asset> resources_asset, - std::unique_ptr<AssetsProvider> assets, + static ApkAssetsPtr LoadImpl(std::unique_ptr<Asset>&& resources_asset, + std::unique_ptr<AssetsProvider>&& assets, package_property_t property_flags, - std::unique_ptr<Asset> idmap_asset, - std::unique_ptr<LoadedIdmap> loaded_idmap); + std::unique_ptr<Asset>&& idmap_asset, + std::unique_ptr<LoadedIdmap>&& loaded_idmap); + + static ApkAssetsPtr LoadImpl(std::unique_ptr<AssetsProvider>&& assets, + package_property_t flags = 0U); // Allows us to make it possible to call make_shared from inside the class but still keeps the // ctor 'private' for all means and purposes. |