summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael BrĂ¼ning <michael.bruning@qt.io>2019-03-22 11:33:47 +0100
committerMichael BrĂ¼ning <michael.bruning@qt.io>2019-03-27 16:13:13 +0000
commitec503eae3ed49c7f87b01b723c706b2783037a73 (patch)
treeb33e0d148157763ccc111349f280c1f1e8a80a72
parentf2dfd87785ada8c5fe579886481cc41be6c36b05 (diff)
downloadqtwebengine-chromium-ec503eae3ed49c7f87b01b723c706b2783037a73.tar.gz
[Backport] Security bug 905509 (8/13)
Backport of original patch by: Antoine Labour <piman@chromium.org>: Audit use of size_t in GLES2Implementation and ProgramInfoManager - use uint32_t where appropriate. - refactor logic around GetActiveAttrib / GetActiveUniform / GetActiveUniformBlockName / GetTransformFeedbackVarying to avoid underflow. Bug: 905509 Change-Id: Ic173134db48bf667152cbfb7449fda10f98af813 Reviewed-on: https://chromium-review.googlesource.com/c/1401459 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-rw-r--r--chromium/gpu/command_buffer/client/gles2_implementation.cc167
-rw-r--r--chromium/gpu/command_buffer/client/gles2_implementation.h10
-rw-r--r--chromium/gpu/command_buffer/client/implementation_base.cc4
-rw-r--r--chromium/gpu/command_buffer/client/implementation_base.h4
-rw-r--r--chromium/gpu/command_buffer/client/program_info_manager.cc86
5 files changed, 104 insertions, 167 deletions
diff --git a/chromium/gpu/command_buffer/client/gles2_implementation.cc b/chromium/gpu/command_buffer/client/gles2_implementation.cc
index b1c20ac07fc..511e087d5da 100644
--- a/chromium/gpu/command_buffer/client/gles2_implementation.cc
+++ b/chromium/gpu/command_buffer/client/gles2_implementation.cc
@@ -3225,6 +3225,28 @@ void GLES2Implementation::TexSubImage3DImpl(GLenum target,
}
}
+void GLES2Implementation::GetResultNameHelper(GLsizei bufsize,
+ GLsizei* length,
+ char* name) {
+ // Length of string (without final \0) that we will write to the buffer.
+ GLsizei max_length = 0;
+ if (name && (bufsize > 0)) {
+ std::vector<int8_t> str;
+ GetBucketContents(kResultBucketId, &str);
+ if (!str.empty()) {
+ DCHECK_LE(str.size(), static_cast<size_t>(INT_MAX));
+ // Note: both bufsize and str.size() count/include the terminating \0.
+ max_length = std::min(bufsize, static_cast<GLsizei>(str.size())) - 1;
+ }
+ memcpy(name, str.data(), max_length);
+ name[max_length] = '\0';
+ }
+ if (length) {
+ *length = max_length;
+ }
+}
+
+
bool GLES2Implementation::GetActiveAttribHelper(
GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size,
GLenum* type, char* name) {
@@ -3248,21 +3270,8 @@ bool GLES2Implementation::GetActiveAttribHelper(
if (type) {
*type = result->type;
}
- if (length || name) {
- std::vector<int8_t> str;
- // Note: this can invalidate |result|.
- GetBucketContents(kResultBucketId, &str);
- GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1,
- std::max(static_cast<size_t>(0),
- str.size() - 1));
- if (length) {
- *length = max_size;
- }
- if (name && bufsize > 0) {
- memcpy(name, &str[0], max_size);
- name[max_size] = '\0';
- }
- }
+ // Note: this can invalidate |result|.
+ GetResultNameHelper(bufsize, length, name);
}
return success;
}
@@ -3313,29 +3322,18 @@ bool GLES2Implementation::GetActiveUniformHelper(
helper_->GetActiveUniform(program, index, kResultBucketId,
GetResultShmId(), GetResultShmOffset());
WaitForCmd();
- if (result->success) {
+ bool success = !!result->success;
+ if (success) {
if (size) {
*size = result->size;
}
if (type) {
*type = result->type;
}
- if (length || name) {
- std::vector<int8_t> str;
- GetBucketContents(kResultBucketId, &str);
- GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1,
- std::max(static_cast<size_t>(0),
- str.size() - 1));
- if (length) {
- *length = max_size;
- }
- if (name && bufsize > 0) {
- memcpy(name, &str[0], max_size);
- name[max_size] = '\0';
- }
- }
+ // Note: this can invalidate |result|.
+ GetResultNameHelper(bufsize, length, name);
}
- return result->success != 0;
+ return success;
}
void GLES2Implementation::GetActiveUniform(
@@ -3385,27 +3383,12 @@ bool GLES2Implementation::GetActiveUniformBlockNameHelper(
helper_->GetActiveUniformBlockName(program, index, kResultBucketId,
GetResultShmId(), GetResultShmOffset());
WaitForCmd();
- if (*result) {
- if (bufsize == 0) {
- if (length) {
- *length = 0;
- }
- } else if (length || name) {
- std::vector<int8_t> str;
- GetBucketContents(kResultBucketId, &str);
- DCHECK_GT(str.size(), 0u);
- GLsizei max_size =
- std::min(bufsize, static_cast<GLsizei>(str.size())) - 1;
- if (length) {
- *length = max_size;
- }
- if (name) {
- memcpy(name, &str[0], max_size);
- name[max_size] = '\0';
- }
- }
+ bool success = !!result;
+ if (success) {
+ // Note: this can invalidate |result|.
+ GetResultNameHelper(bufsize, length, name);
}
- return *result != 0;
+ return success;
}
void GLES2Implementation::GetActiveUniformBlockName(
@@ -3720,25 +3703,8 @@ bool GLES2Implementation::GetTransformFeedbackVaryingHelper(
if (type) {
*type = result->type;
}
- if (length || name) {
- std::vector<int8_t> str;
- GetBucketContents(kResultBucketId, &str);
- GLsizei max_size = std::min(bufsize, static_cast<GLsizei>(str.size()));
- if (max_size > 0) {
- --max_size;
- }
- if (length) {
- *length = max_size;
- }
- if (name) {
- if (max_size > 0) {
- memcpy(name, &str[0], max_size);
- name[max_size] = '\0';
- } else if (bufsize > 0) {
- name[0] = '\0';
- }
- }
- }
+ // Note: this can invalidate |result|.
+ GetResultNameHelper(bufsize, length, name);
}
return result->success != 0;
}
@@ -4827,7 +4793,7 @@ void GLES2Implementation::ScheduleCALayerSharedStateCHROMIUM(
const GLfloat* clip_rect,
GLint sorting_context_id,
const GLfloat* transform) {
- size_t shm_size = 20 * sizeof(GLfloat);
+ uint32_t shm_size = 20 * sizeof(GLfloat);
ScopedTransferBufferPtr buffer(shm_size, helper_, transfer_buffer_);
if (!buffer.valid() || buffer.size() < shm_size) {
SetGLError(GL_OUT_OF_MEMORY, "GLES2::ScheduleCALayerSharedStateCHROMIUM",
@@ -4848,7 +4814,7 @@ void GLES2Implementation::ScheduleCALayerCHROMIUM(GLuint contents_texture_id,
GLuint edge_aa_mask,
const GLfloat* bounds_rect,
GLuint filter) {
- size_t shm_size = 8 * sizeof(GLfloat);
+ uint32_t shm_size = 8 * sizeof(GLfloat);
ScopedTransferBufferPtr buffer(shm_size, helper_, transfer_buffer_);
if (!buffer.valid() || buffer.size() < shm_size) {
SetGLError(GL_OUT_OF_MEMORY, "GLES2::ScheduleCALayerCHROMIUM",
@@ -6353,11 +6319,11 @@ bool GLES2Implementation::PackStringsToBucket(GLsizei count,
base::CheckedNumeric<uint32_t> total_size = count;
total_size += 1;
total_size *= sizeof(GLint);
- if (!total_size.IsValid()) {
+ uint32_t header_size = 0;
+ if (!total_size.AssignIfValid(&header_size)) {
SetGLError(GL_INVALID_VALUE, func_name, "overflow");
return false;
}
- size_t header_size = total_size.ValueOrDefault(0);
std::vector<GLint> header(count + 1);
header[0] = static_cast<GLint>(count);
for (GLsizei ii = 0; ii < count; ++ii) {
@@ -6369,35 +6335,30 @@ bool GLES2Implementation::PackStringsToBucket(GLsizei count,
}
total_size += len;
total_size += 1; // NULL at the end of each char array.
- if (!total_size.IsValid()) {
- SetGLError(GL_INVALID_VALUE, func_name, "overflow");
- return false;
- }
header[ii + 1] = len;
}
// Pack data into a bucket on the service.
- helper_->SetBucketSize(kResultBucketId, total_size.ValueOrDefault(0));
- size_t offset = 0;
+ uint32_t validated_size = 0;
+ if (!total_size.AssignIfValid(&validated_size)) {
+ SetGLError(GL_INVALID_VALUE, func_name, "overflow");
+ return false;
+ }
+ helper_->SetBucketSize(kResultBucketId, validated_size);
+ uint32_t offset = 0;
for (GLsizei ii = 0; ii <= count; ++ii) {
const char* src =
(ii == 0) ? reinterpret_cast<const char*>(&header[0]) : str[ii - 1];
- base::CheckedNumeric<size_t> checked_size =
- (ii == 0) ? header_size : static_cast<size_t>(header[ii]);
+ uint32_t size = (ii == 0) ? header_size : header[ii];
if (ii > 0) {
- checked_size += 1; // NULL in the end.
- }
- if (!checked_size.IsValid()) {
- SetGLError(GL_INVALID_VALUE, func_name, "overflow");
- return false;
+ size += 1; // NULL in the end.
}
- size_t size = checked_size.ValueOrDefault(0);
while (size) {
ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_);
if (!buffer.valid() || buffer.size() == 0) {
SetGLError(GL_OUT_OF_MEMORY, func_name, "too large");
return false;
}
- size_t copy_size = buffer.size();
+ uint32_t copy_size = buffer.size();
if (ii > 0 && buffer.size() == size)
--copy_size;
if (copy_size)
@@ -6702,9 +6663,9 @@ bool GLES2Implementation::PrepareInstancedPathCommand(
const GLfloat* transform_values,
ScopedTransferBufferPtr* buffer,
uint32_t* out_paths_shm_id,
- size_t* out_paths_offset,
+ uint32_t* out_paths_offset,
uint32_t* out_transforms_shm_id,
- size_t* out_transforms_offset) {
+ uint32_t* out_transforms_offset) {
if (num_paths < 0) {
SetGLError(GL_INVALID_VALUE, function_name, "numPaths < 0");
return false;
@@ -6818,9 +6779,9 @@ void GLES2Implementation::StencilFillPathInstancedCHROMIUM(
ScopedTransferBufferPtr buffer(helper_, transfer_buffer_);
uint32_t paths_shm_id = 0;
- size_t paths_offset = 0;
+ uint32_t paths_offset = 0;
uint32_t transforms_shm_id = 0;
- size_t transforms_offset = 0;
+ uint32_t transforms_offset = 0;
if (!PrepareInstancedPathCommand(
"glStencilFillPathInstancedCHROMIUM", num_paths, path_name_type,
paths, transform_type, transform_values, &buffer, &paths_shm_id,
@@ -6853,9 +6814,9 @@ void GLES2Implementation::StencilStrokePathInstancedCHROMIUM(
ScopedTransferBufferPtr buffer(helper_, transfer_buffer_);
uint32_t paths_shm_id = 0;
- size_t paths_offset = 0;
+ uint32_t paths_offset = 0;
uint32_t transforms_shm_id = 0;
- size_t transforms_offset = 0;
+ uint32_t transforms_offset = 0;
if (!PrepareInstancedPathCommand(
"glStencilStrokePathInstancedCHROMIUM", num_paths, path_name_type,
paths, transform_type, transform_values, &buffer, &paths_shm_id,
@@ -6886,9 +6847,9 @@ void GLES2Implementation::CoverFillPathInstancedCHROMIUM(
ScopedTransferBufferPtr buffer(helper_, transfer_buffer_);
uint32_t paths_shm_id = 0;
- size_t paths_offset = 0;
+ uint32_t paths_offset = 0;
uint32_t transforms_shm_id = 0;
- size_t transforms_offset = 0;
+ uint32_t transforms_offset = 0;
if (!PrepareInstancedPathCommand(
"glCoverFillPathInstancedCHROMIUM", num_paths, path_name_type, paths,
transform_type, transform_values, &buffer, &paths_shm_id,
@@ -6920,9 +6881,9 @@ void GLES2Implementation::CoverStrokePathInstancedCHROMIUM(
ScopedTransferBufferPtr buffer(helper_, transfer_buffer_);
uint32_t paths_shm_id = 0;
- size_t paths_offset = 0;
+ uint32_t paths_offset = 0;
uint32_t transforms_shm_id = 0;
- size_t transforms_offset = 0;
+ uint32_t transforms_offset = 0;
if (!PrepareInstancedPathCommand(
"glCoverStrokePathInstancedCHROMIUM", num_paths, path_name_type,
paths, transform_type, transform_values, &buffer, &paths_shm_id,
@@ -6956,9 +6917,9 @@ void GLES2Implementation::StencilThenCoverFillPathInstancedCHROMIUM(
ScopedTransferBufferPtr buffer(helper_, transfer_buffer_);
uint32_t paths_shm_id = 0;
- size_t paths_offset = 0;
+ uint32_t paths_offset = 0;
uint32_t transforms_shm_id = 0;
- size_t transforms_offset = 0;
+ uint32_t transforms_offset = 0;
if (!PrepareInstancedPathCommand(
"glStencilThenCoverFillPathInstancedCHROMIUM", num_paths,
path_name_type, paths, transform_type, transform_values, &buffer,
@@ -6995,9 +6956,9 @@ void GLES2Implementation::StencilThenCoverStrokePathInstancedCHROMIUM(
ScopedTransferBufferPtr buffer(helper_, transfer_buffer_);
uint32_t paths_shm_id = 0;
- size_t paths_offset = 0;
+ uint32_t paths_offset = 0;
uint32_t transforms_shm_id = 0;
- size_t transforms_offset = 0;
+ uint32_t transforms_offset = 0;
if (!PrepareInstancedPathCommand(
"glStencilThenCoverStrokePathInstancedCHROMIUM", num_paths,
path_name_type, paths, transform_type, transform_values, &buffer,
diff --git a/chromium/gpu/command_buffer/client/gles2_implementation.h b/chromium/gpu/command_buffer/client/gles2_implementation.h
index 6e108466561..151e1a28b1f 100644
--- a/chromium/gpu/command_buffer/client/gles2_implementation.h
+++ b/chromium/gpu/command_buffer/client/gles2_implementation.h
@@ -148,6 +148,12 @@ class GLES2_IMPL_EXPORT GLES2Implementation : public GLES2Interface,
GLint GetUniformLocationHelper(GLuint program, const char* name);
GLint GetFragDataIndexEXTHelper(GLuint program, const char* name);
GLint GetFragDataLocationHelper(GLuint program, const char* name);
+
+ // Writes the result bucket into a buffer pointed by name and of maximum size
+ // buffsize. If length is !null, it receives the number of characters written
+ // (excluding the final \0). This is a helper function for GetActive*Helper
+ // functions that return names.
+ void GetResultNameHelper(GLsizei bufsize, GLsizei* length, char* name);
bool GetActiveAttribHelper(
GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
GLint* size, GLenum* type, char* name);
@@ -602,9 +608,9 @@ class GLES2_IMPL_EXPORT GLES2Implementation : public GLES2Interface,
const GLfloat* transform_values,
ScopedTransferBufferPtr* buffer,
uint32_t* out_paths_shm_id,
- size_t* out_paths_offset,
+ uint32_t* out_paths_offset,
uint32_t* out_transforms_shm_id,
- size_t* out_transforms_offset);
+ uint32_t* out_transforms_offset);
// Set to 1 to have the client fail when a GL error is generated.
// This helps find bugs in the renderer since the debugger stops on the error.
diff --git a/chromium/gpu/command_buffer/client/implementation_base.cc b/chromium/gpu/command_buffer/client/implementation_base.cc
index 5714213c399..59ca1c5c92f 100644
--- a/chromium/gpu/command_buffer/client/implementation_base.cc
+++ b/chromium/gpu/command_buffer/client/implementation_base.cc
@@ -19,8 +19,8 @@
namespace gpu {
#if !defined(_MSC_VER)
-const size_t ImplementationBase::kMaxSizeOfSimpleResult;
-const unsigned int ImplementationBase::kStartingOffset;
+const uint32_t ImplementationBase::kMaxSizeOfSimpleResult;
+const uint32_t ImplementationBase::kStartingOffset;
#endif
ImplementationBase::ImplementationBase(CommandBufferHelper* helper,
diff --git a/chromium/gpu/command_buffer/client/implementation_base.h b/chromium/gpu/command_buffer/client/implementation_base.h
index 58c33f9b4ec..71d912954f4 100644
--- a/chromium/gpu/command_buffer/client/implementation_base.h
+++ b/chromium/gpu/command_buffer/client/implementation_base.h
@@ -45,11 +45,11 @@ class GLES2_IMPL_EXPORT ImplementationBase
public GpuControlClient {
public:
// The maximum result size from simple GL get commands.
- static const size_t kMaxSizeOfSimpleResult =
+ static const uint32_t kMaxSizeOfSimpleResult =
16 * sizeof(uint32_t); // NOLINT.
// used for testing only. If more things are reseved add them here.
- static const unsigned int kStartingOffset = kMaxSizeOfSimpleResult;
+ static const uint32_t kStartingOffset = kMaxSizeOfSimpleResult;
// Alignment of allocations.
static const unsigned int kAlignment = 16;
diff --git a/chromium/gpu/command_buffer/client/program_info_manager.cc b/chromium/gpu/command_buffer/client/program_info_manager.cc
index bc15d41b10e..55d062b531a 100644
--- a/chromium/gpu/command_buffer/client/program_info_manager.cc
+++ b/chromium/gpu/command_buffer/client/program_info_manager.cc
@@ -13,14 +13,33 @@ template <typename T>
static T LocalGetAs(const std::vector<int8_t>& data,
uint32_t offset,
size_t size) {
- const int8_t* p = &data[0] + offset;
- if (offset + size > data.size()) {
- NOTREACHED();
- return NULL;
- }
+ const int8_t* p = data.data() + offset;
+ DCHECK_LE(offset + size, data.size());
return static_cast<T>(static_cast<const void*>(p));
}
+// Writes the strimg pointed by name and of maximum size buffsize. If length is
+// !null, it receives the number of characters written (excluding the final \0).
+// This is a helper function for GetActive*Helper functions that return names.
+void FillNameAndLength(GLsizei bufsize,
+ GLsizei* length,
+ char* name,
+ const std::string& string) {
+ // Length of string (without final \0) that we will write to the
+ // buffer.
+ GLsizei max_length = 0;
+ if (name && (bufsize > 0)) {
+ DCHECK_LE(string.size(), static_cast<size_t>(INT_MAX));
+ // Note: bufsize counts the terminating \0, but not string.size().
+ max_length = std::min(bufsize - 1, static_cast<GLsizei>(string.size()));
+ memcpy(name, string.data(), max_length);
+ name[max_length] = '\0';
+ }
+ if (length) {
+ *length = max_length;
+ }
+}
+
} // namespace
namespace gpu {
@@ -809,18 +828,7 @@ bool ProgramInfoManager::GetActiveAttrib(
if (type) {
*type = attrib_info->type;
}
- if (length || name) {
- GLsizei max_size = std::min(
- static_cast<size_t>(bufsize) - 1,
- std::max(static_cast<size_t>(0), attrib_info->name.size()));
- if (length) {
- *length = max_size;
- }
- if (name && bufsize > 0) {
- memcpy(name, attrib_info->name.c_str(), max_size);
- name[max_size] = '\0';
- }
- }
+ FillNameAndLength(bufsize, length, name, attrib_info->name);
return true;
}
}
@@ -845,18 +853,7 @@ bool ProgramInfoManager::GetActiveUniform(
if (type) {
*type = uniform_info->type;
}
- if (length || name) {
- GLsizei max_size = std::min(
- static_cast<size_t>(bufsize) - 1,
- std::max(static_cast<size_t>(0), uniform_info->name.size()));
- if (length) {
- *length = max_size;
- }
- if (name && bufsize > 0) {
- memcpy(name, uniform_info->name.c_str(), max_size);
- name[max_size] = '\0';
- }
- }
+ FillNameAndLength(bufsize, length, name, uniform_info->name);
return true;
}
}
@@ -881,30 +878,13 @@ bool ProgramInfoManager::GetActiveUniformBlockName(
GLES2Implementation* gl, GLuint program, GLuint index,
GLsizei buf_size, GLsizei* length, char* name) {
DCHECK_LE(0, buf_size);
- if (!name) {
- buf_size = 0;
- }
{
base::AutoLock auto_lock(lock_);
Program* info = GetProgramInfo(gl, program, kES3UniformBlocks);
if (info) {
const Program::UniformBlock* uniform_block = info->GetUniformBlock(index);
if (uniform_block) {
- if (buf_size == 0) {
- if (length) {
- *length = 0;
- }
- } else if (length || name) {
- GLsizei max_size = std::min(
- buf_size - 1, static_cast<GLsizei>(uniform_block->name.size()));
- if (length) {
- *length = max_size;
- }
- if (name) {
- memcpy(name, uniform_block->name.data(), max_size);
- name[max_size] = '\0';
- }
- }
+ FillNameAndLength(buf_size, length, name, uniform_block->name);
return true;
}
}
@@ -1006,17 +986,7 @@ bool ProgramInfoManager::GetTransformFeedbackVarying(
if (type) {
*type = varying->type;
}
- if (length || name) {
- GLsizei max_size = std::min(
- bufsize - 1, static_cast<GLsizei>(varying->name.size()));
- if (length) {
- *length = static_cast<GLsizei>(max_size);
- }
- if (name && bufsize > 0) {
- memcpy(name, varying->name.c_str(), max_size);
- name[max_size] = '\0';
- }
- }
+ FillNameAndLength(bufsize, length, name, varying->name);
return true;
}
}