From 7744e1a262175f15928cf44e3f1c6553c9a99343 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Tue, 24 Nov 2020 18:01:09 +0100 Subject: [PATCH] vk: use-after-free if inFlight texture is deleted or cache cleared --- core/rend/TexCache.h | 11 +++++++++-- core/rend/gles/gles.h | 4 ++-- core/rend/vulkan/texture.h | 13 +++++++++++-- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/core/rend/TexCache.h b/core/rend/TexCache.h index c74bf06cd..6f0073267 100644 --- a/core/rend/TexCache.h +++ b/core/rend/TexCache.h @@ -772,6 +772,8 @@ public: return texture; } + virtual ~BaseTextureCache() {} + void CollectCleanup() { std::vector list; @@ -789,7 +791,7 @@ public: for (u64 id : list) { - if (cache[id].Delete()) + if (clearTexture(&cache[id])) cache.erase(id); } } @@ -797,13 +799,18 @@ public: void Clear() { for (auto& pair : cache) - pair.second.Delete(); + clearTexture(&pair.second); cache.clear(); KillTex = false; INFO_LOG(RENDERER, "Texture cache cleared"); } +protected: + virtual bool clearTexture(Texture *tex) { + return tex->Delete(); + } + private: std::unordered_map cache; // Only use TexU and TexV from TSP in the cache key diff --git a/core/rend/gles/gles.h b/core/rend/gles/gles.h index 75a167f1c..8ce898d94 100755 --- a/core/rend/gles/gles.h +++ b/core/rend/gles/gles.h @@ -218,7 +218,7 @@ extern struct ShaderUniforms_t } ShaderUniforms; -class TextureCacheData : public BaseTextureCacheData +class TextureCacheData final : public BaseTextureCacheData { public: GLuint texID; //gl texture @@ -227,7 +227,7 @@ public: virtual bool Delete() override; }; -class TextureCache : public BaseTextureCache +class TextureCache final : public BaseTextureCache { }; extern TextureCache TexCache; diff --git a/core/rend/vulkan/texture.h b/core/rend/vulkan/texture.h index 692023661..42f9d6e7a 100644 --- a/core/rend/vulkan/texture.h +++ b/core/rend/vulkan/texture.h @@ -33,7 +33,7 @@ void setImageLayout(vk::CommandBuffer const& commandBuffer, vk::Image image, vk::Format format, u32 mipmapLevels, vk::ImageLayout oldImageLayout, vk::ImageLayout newImageLayout); -class Texture : public BaseTextureCacheData +class Texture final : public BaseTextureCacheData { public: void UploadToGPU(int width, int height, u8 *data, bool mipmapped, bool mipmapsIncluded = false) override; @@ -134,7 +134,7 @@ private: vk::Device device; }; -class TextureCache : public BaseTextureCache +class TextureCache final : public BaseTextureCache { public: void SetCurrentIndex(int index) { @@ -173,6 +173,15 @@ public: texture->format = vk::Format::eUndefined; } +protected: + virtual bool clearTexture(Texture *tex) override + { + std::for_each(inFlightTextures.begin(), inFlightTextures.end(), + [tex](std::unordered_set& set) { set.erase(tex); }); + + return BaseTextureCache::clearTexture(tex); + } + private: template void EmptyTrash(T& v)