From 1c6965f10699077ac6e6eb006714431d6d87ac20 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 16 Jan 2017 16:41:39 -0500 Subject: [PATCH] Implemented validation for the texture module --- .../renderer_opengl/gl_rasterizer_cache.cpp | 37 +++++++++++++------ src/video_core/texture/codec.cpp | 35 +++++++++++++++--- src/video_core/texture/codec.h | 5 ++- 3 files changed, 58 insertions(+), 19 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 618a4e1f7..ac029b48f 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -309,17 +309,24 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo codec->configTiling(true, 8); // change 8 for 32 in case the mage is tiled // on blocks of 32x32 codec->configRGBATransform(!native_format[(unsigned int)params.pixel_format]); - codec->decode(); - std::unique_ptr decoded_texture = codec->transferInternalBuffer(); - u32 bytes = codec->getInternalBytesPerPixel(); - if (bytes == 3) - bytes = 1; - else if (bytes != 2) - bytes = 4; - glPixelStorei(GL_UNPACK_ALIGNMENT, bytes); - glTexImage2D(GL_TEXTURE_2D, 0, tuple.internal_format, params.width, params.height, 0, - tuple.format, tuple.type, decoded_texture.get()); - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + codec->validate(); + if (!codec->invalid()) { + codec->decode(); + std::unique_ptr decoded_texture = codec->transferInternalBuffer(); + u32 bytes = codec->getInternalBytesPerPixel(); + if (bytes == 3) + bytes = 1; + else if (bytes != 2) + bytes = 4; + glPixelStorei(GL_UNPACK_ALIGNMENT, bytes); + glTexImage2D(GL_TEXTURE_2D, 0, tuple.internal_format, params.width, params.height, + 0, tuple.format, tuple.type, decoded_texture.get()); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + } else { + LOG_WARNING(Render_OpenGL, + "Invalid texture sent to renderer; width: %d height %d type: %d", + params.width, params.height, (unsigned int)params.pixel_format); + } } // If not 1x scale, blit 1x texture to a new scaled texture and replace texture in surface if (new_surface->res_scale_width != 1.f || new_surface->res_scale_height != 1.f) { @@ -662,7 +669,13 @@ void RasterizerCacheOpenGL::FlushSurface(CachedSurface* surface) { codec->configRGBATransform(!native_format[(u32)surface->pixel_format]); codec->configPreConvertedRGBA(!native_format[(u32)surface->pixel_format]); codec->setExternalBuffer(dst_buffer); - codec->encode(); + codec->validate(); + if (!codec->invalid()) + codec->encode(); + else + LOG_WARNING(Render_OpenGL, + "Invalid texture sent to renderer; width: %d height %d type: %d", + surface->width, surface->height, (unsigned int)surface->pixel_format); } surface->dirty = false; diff --git a/src/video_core/texture/codec.cpp b/src/video_core/texture/codec.cpp index f63aa29ff..42f39c23f 100644 --- a/src/video_core/texture/codec.cpp +++ b/src/video_core/texture/codec.cpp @@ -13,13 +13,13 @@ void Codec::decode() { this->init(true); if (this->morton) this->decode_morton_pass(); -}; +} void Codec::encode() { this->init(false); if (this->morton) this->encode_morton_pass(); -}; +} void Codec::configTiling(bool active, u32 tiling) { this->morton = true; @@ -66,14 +66,39 @@ void Codec::init(bool decode) { if (!this->raw_RGBA) this->expected_nibbles_size = this->start_nibbles_size; } - if (!this->external_result_buffer) { + this->validate(); + if (!this->external_result_buffer || !this->invalid()) { size_t buff_size = this->width * this->height * this->expected_nibbles_size / 2; this->internal_buffer = std::make_unique(buff_size); this->passing_buffer = this->internal_buffer.get(); } } -void Codec::decode_morton_pass() { +void Codec::validate() { + if (this->width < 8) { + this->invalid_state = true; + return; + } + if (this->height < 8) { + this->invalid_state = true; + return; + } + if (this->target_buffer == nullptr) { + this->invalid_state = true; + return; + } + if (this->external_result_buffer && this->passing_buffer == nullptr) { + this->invalid_state = true; + return; + } + if (this->morton && this->morton_pass_tiling != 8 && this->morton_pass_tiling != 32) { + this->invalid_state = true; + return; + } + this->invalid_state = false; +} + +inline void Codec::decode_morton_pass() { if (this->morton_pass_tiling == 8) Decoders::Morton_8x8(this->target_buffer, this->passing_buffer, this->width, this->height, this->start_nibbles_size * 4); @@ -82,7 +107,7 @@ void Codec::decode_morton_pass() { this->start_nibbles_size * 4); } -void Codec::encode_morton_pass() { +inline void Codec::encode_morton_pass() { if (this->morton_pass_tiling == 8) Encoders::Morton_8x8(this->target_buffer, this->passing_buffer, this->width, this->height, this->start_nibbles_size * 4); diff --git a/src/video_core/texture/codec.h b/src/video_core/texture/codec.h index 1c0a6b1d9..5bcd653dc 100644 --- a/src/video_core/texture/codec.h +++ b/src/video_core/texture/codec.h @@ -43,6 +43,7 @@ public: void setExternalBuffer(u8* external); std::unique_ptr transferInternalBuffer(); + virtual void validate(); bool invalid(); protected: @@ -74,8 +75,8 @@ protected: typedef Codec super; - void decode_morton_pass(); - void encode_morton_pass(); + inline void decode_morton_pass(); + inline void encode_morton_pass(); }; namespace CodecFactory {