Browse Source

chore: cherry-pick 6b4af5d82083 from chromium (#36444)

Co-authored-by: Adam Prasil <[email protected]>
ad0p 2 years ago
parent
commit
cb26b3689b
2 changed files with 293 additions and 0 deletions
  1. 1 0
      patches/chromium/.patches
  2. 292 0
      patches/chromium/cherry-pick-6b4af5d82083.patch

+ 1 - 0
patches/chromium/.patches

@@ -142,3 +142,4 @@ cherry-pick-a1cbf05b4163.patch
 cherry-pick-ac4785387fff.patch
 cherry-pick-81cb17c24788.patch
 cherry-pick-1894458e04a2.patch
+cherry-pick-6b4af5d82083.patch

+ 292 - 0
patches/chromium/cherry-pick-6b4af5d82083.patch

@@ -0,0 +1,292 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peng Huang <[email protected]>
+Date: Wed, 23 Nov 2022 00:16:49 +0000
+Subject: Fix potential OOB problem with validating command decoder
+
+Bug: 1392715
+Change-Id: If51b10cc08e5b3ca4b6012b97261347a5e4c134e
+Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4048203
+Auto-Submit: Peng Huang <[email protected]>
+Commit-Queue: Peng Huang <[email protected]>
+Reviewed-by: Geoff Lang <[email protected]>
+Cr-Commit-Position: refs/heads/main@{#1074966}
+
+diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
+index a36b9901b50cd99ac641d70d2f316362006e45e7..73148877e2b8b28374ffd32aa10361d21e4911e4 100644
+--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
++++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
+@@ -8595,10 +8595,18 @@ void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
+     service_id = texture_ref->service_id();
+   }
+ 
++  bool valid_target = false;
++  if (texture_ref) {
++    valid_target = texture_manager()->ValidForTextureTarget(
++        texture_ref->texture(), level, 0, 0, 1);
++  } else {
++    valid_target = texture_manager()->ValidForTarget(textarget, level, 0, 0, 1);
++  }
++
+   if ((level > 0 && !feature_info_->IsWebGL2OrES3Context() &&
+        !(fbo_render_mipmap_explicitly_enabled_ &&
+          feature_info_->feature_flags().oes_fbo_render_mipmap)) ||
+-      !texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
++      !valid_target) {
+     LOCAL_SET_GL_ERROR(
+         GL_INVALID_VALUE,
+         name, "level out of range");
+@@ -8670,8 +8678,8 @@ void GLES2DecoderImpl::DoFramebufferTextureLayer(
+             "texture is neither TEXTURE_3D nor TEXTURE_2D_ARRAY");
+         return;
+     }
+-    if (!texture_manager()->ValidForTarget(texture_target, level,
+-                                           0, 0, layer)) {
++    if (!texture_manager()->ValidForTextureTarget(texture_ref->texture(), level,
++                                                  0, 0, layer)) {
+       LOCAL_SET_GL_ERROR(
+           GL_INVALID_VALUE, function_name, "invalid level or layer");
+       return;
+@@ -14757,11 +14765,6 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage(
+     LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "imageSize < 0");
+     return error::kNoError;
+   }
+-  if (!texture_manager()->ValidForTarget(target, level, width, height, depth) ||
+-      border != 0) {
+-    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "dimensions out of range");
+-    return error::kNoError;
+-  }
+   TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
+       &state_, target);
+   if (!texture_ref) {
+@@ -14770,6 +14773,12 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage(
+     return error::kNoError;
+   }
+   Texture* texture = texture_ref->texture();
++  if (!texture_manager()->ValidForTextureTarget(texture, level, width, height,
++                                                depth) ||
++      border != 0) {
++    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "dimensions out of range");
++    return error::kNoError;
++  }
+   if (texture->IsImmutable()) {
+     LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, "texture is immutable");
+     return error::kNoError;
+@@ -15139,10 +15148,6 @@ error::Error GLES2DecoderImpl::DoCompressedTexSubImage(
+     LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "imageSize < 0");
+     return error::kNoError;
+   }
+-  if (!texture_manager()->ValidForTarget(target, level, width, height, depth)) {
+-    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "dimensions out of range");
+-    return error::kNoError;
+-  }
+   TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
+       &state_, target);
+   if (!texture_ref) {
+@@ -15150,7 +15155,14 @@ error::Error GLES2DecoderImpl::DoCompressedTexSubImage(
+         GL_INVALID_OPERATION, func_name, "no texture bound at target");
+     return error::kNoError;
+   }
++
+   Texture* texture = texture_ref->texture();
++  if (!texture_manager()->ValidForTextureTarget(texture, level, width, height,
++                                                depth)) {
++    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "dimensions out of range");
++    return error::kNoError;
++  }
++
+   GLenum type = 0;
+   GLenum internal_format = 0;
+   if (!texture->GetLevelType(target, level, &type, &internal_format)) {
+@@ -15275,7 +15287,8 @@ void GLES2DecoderImpl::DoCopyTexImage2D(
+         GL_INVALID_OPERATION, func_name, "texture is immutable");
+     return;
+   }
+-  if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
++  if (!texture_manager()->ValidForTextureTarget(texture, level, width, height,
++                                                1) ||
+       border != 0) {
+     LOCAL_SET_GL_ERROR(
+         GL_INVALID_VALUE, func_name, "dimensions out of range");
+@@ -17848,8 +17861,8 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
+     }
+ 
+     // Check that this type of texture is allowed.
+-    if (!texture_manager()->ValidForTarget(source_target, source_level,
+-                                           source_width, source_height, 1)) {
++    if (!texture_manager()->ValidForTextureTarget(
++            source_texture, source_level, source_width, source_height, 1)) {
+       LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "Bad dimensions");
+       return;
+     }
+@@ -18016,8 +18029,8 @@ void GLES2DecoderImpl::CopySubTextureHelper(const char* function_name,
+     }
+ 
+     // Check that this type of texture is allowed.
+-    if (!texture_manager()->ValidForTarget(source_target, source_level,
+-                                           source_width, source_height, 1)) {
++    if (!texture_manager()->ValidForTextureTarget(
++            source_texture, source_level, source_width, source_height, 1)) {
+       LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
+                          "source texture bad dimensions");
+       return;
+@@ -18257,11 +18270,20 @@ void GLES2DecoderImpl::TexStorageImpl(GLenum target,
+       return;
+     }
+   }
++  TextureRef* texture_ref =
++      texture_manager()->GetTextureInfoForTarget(&state_, target);
++  if (!texture_ref) {
++    LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
++                       "unknown texture for target");
++    return;
++  }
++  Texture* texture = texture_ref->texture();
+   // The glTexStorage entry points require width, height, and depth to be
+   // at least 1, but the other texture entry points (those which use
+-  // ValidForTarget) do not. So we have to add an extra check here.
++  // ValidForTextureTarget) do not. So we have to add an extra check here.
+   bool is_invalid_texstorage_size = width < 1 || height < 1 || depth < 1;
+-  if (!texture_manager()->ValidForTarget(target, 0, width, height, depth) ||
++  if (!texture_manager()->ValidForTextureTarget(texture, 0, width, height,
++                                                depth) ||
+       is_invalid_texstorage_size) {
+     LOCAL_SET_GL_ERROR(
+         GL_INVALID_VALUE, function_name, "dimensions out of range");
+@@ -18274,14 +18296,6 @@ void GLES2DecoderImpl::TexStorageImpl(GLenum target,
+     LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "too many levels");
+     return;
+   }
+-  TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
+-      &state_, target);
+-  if (!texture_ref) {
+-    LOCAL_SET_GL_ERROR(
+-        GL_INVALID_OPERATION, function_name, "unknown texture for target");
+-    return;
+-  }
+-  Texture* texture = texture_ref->texture();
+   if (texture->IsAttachedToFramebuffer()) {
+     framebuffer_state_.clear_state_dirty = true;
+   }
+diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
+index b20b875b6b37c36623b41e648e393ded96bae93b..f5df8270a8192d36b95e619248c128167455ef46 100644
+--- a/gpu/command_buffer/service/texture_manager.cc
++++ b/gpu/command_buffer/service/texture_manager.cc
+@@ -1641,7 +1641,7 @@ void Texture::Update() {
+     return;
+ 
+   if (face_infos_.empty() ||
+-      static_cast<size_t>(base_level_) >= face_infos_[0].level_infos.size()) {
++      static_cast<size_t>(base_level_) >= MaxValidMipLevel()) {
+     texture_complete_ = false;
+     cube_complete_ = false;
+     return;
+@@ -2028,8 +2028,7 @@ bool Texture::CanRenderTo(const FeatureInfo* feature_info, GLint level) const {
+   // the time.
+   if (face_infos_.size() == 6 && !cube_complete())
+     return false;
+-  DCHECK(level >= 0 &&
+-         level < static_cast<GLint>(face_infos_[0].level_infos.size()));
++  DCHECK(level >= 0 && level < static_cast<GLint>(MaxValidMipLevel()));
+   if (level > base_level_ && !texture_complete()) {
+     return false;
+   }
+@@ -2064,7 +2063,7 @@ void Texture::SetCompatibilitySwizzle(const CompatibilitySwizzle* swizzle) {
+ 
+ void Texture::ApplyFormatWorkarounds(const FeatureInfo* feature_info) {
+   if (feature_info->gl_version_info().NeedsLuminanceAlphaEmulation()) {
+-    if (static_cast<size_t>(base_level_) >= face_infos_[0].level_infos.size())
++    if (static_cast<size_t>(base_level_) >= MaxValidMipLevel())
+       return;
+     const Texture::LevelInfo& info = face_infos_[0].level_infos[base_level_];
+     SetCompatibilitySwizzle(GetCompatibilitySwizzleInternal(info.format));
+@@ -2298,8 +2297,11 @@ scoped_refptr<TextureRef>
+   return default_texture;
+ }
+ 
+-bool TextureManager::ValidForTarget(
+-    GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth) {
++bool TextureManager::ValidForTarget(GLenum target,
++                                    GLint level,
++                                    GLsizei width,
++                                    GLsizei height,
++                                    GLsizei depth) {
+   if (level < 0 || level >= MaxLevelsForTarget(target))
+     return false;
+   GLsizei max_size = MaxSizeForTarget(target) >> level;
+@@ -2319,6 +2321,18 @@ bool TextureManager::ValidForTarget(
+          (target != GL_TEXTURE_2D || (depth == 1));
+ }
+ 
++bool TextureManager::ValidForTextureTarget(const Texture* texture,
++                                           GLint level,
++                                           GLsizei width,
++                                           GLsizei height,
++                                           GLsizei depth) {
++  if (texture->target() == 0)
++    return false;
++  if (level < 0 || static_cast<size_t>(level) >= texture->MaxValidMipLevel())
++    return false;
++  return ValidForTarget(texture->target(), level, width, height, depth);
++}
++
+ void TextureManager::SetTarget(TextureRef* ref, GLenum target) {
+   DCHECK(ref);
+   ref->texture()->SetTarget(target, MaxLevelsForTarget(target));
+@@ -2802,14 +2816,6 @@ bool TextureManager::ValidateTexImage(ContextState* state,
+       args.internal_format, args.level)) {
+     return false;
+   }
+-  if (!ValidForTarget(args.target, args.level,
+-                      args.width, args.height, args.depth) ||
+-      args.border != 0) {
+-    ERRORSTATE_SET_GL_ERROR(
+-        error_state, GL_INVALID_VALUE, function_name,
+-        "dimensions out of range");
+-    return false;
+-  }
+   if ((GLES2Util::GetChannelsForFormat(args.format) &
+        (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && args.pixels
+       && !feature_info_->IsWebGL2OrES3Context()) {
+@@ -2832,7 +2838,13 @@ bool TextureManager::ValidateTexImage(ContextState* state,
+         "texture is immutable");
+     return false;
+   }
+-
++  if (!ValidForTextureTarget(local_texture_ref->texture(), args.level,
++                             args.width, args.height, args.depth) ||
++      args.border != 0) {
++    ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name,
++                            "dimensions out of range");
++    return false;
++  }
+   Buffer* buffer = state->bound_pixel_unpack_buffer.get();
+   if (buffer) {
+     if (buffer->GetMappedRange()) {
+diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h
+index c78c914cbad58abb17439354eeb9f77a9891f21d..8f68e70e6d1c9a4b75f6bec0df7179320bc167c0 100644
+--- a/gpu/command_buffer/service/texture_manager.h
++++ b/gpu/command_buffer/service/texture_manager.h
+@@ -470,6 +470,11 @@ class GPU_GLES2_EXPORT Texture final : public TextureBase {
+            sampler_state_.min_filter != GL_LINEAR;
+   }
+ 
++  size_t MaxValidMipLevel() const {
++    DCHECK(!face_infos_.empty());
++    return face_infos_[0].level_infos.size();
++  }
++
+  private:
+   friend class MailboxManagerTest;
+   friend class TextureManager;
+@@ -932,6 +937,11 @@ class GPU_GLES2_EXPORT TextureManager
+   bool ValidForTarget(
+       GLenum target, GLint level,
+       GLsizei width, GLsizei height, GLsizei depth);
++  bool ValidForTextureTarget(const Texture* texture,
++                             GLint level,
++                             GLsizei width,
++                             GLsizei height,
++                             GLsizei depth);
+ 
+   // True if this texture meets all the GLES2 criteria for rendering.
+   // See section 3.8.2 of the GLES2 spec.