Commit ae582206 authored by Antoine Labour's avatar Antoine Labour Committed by Commit Bot

Harden gpu::SizedResult against overflow

Use CheckedNumerics to prevent silent uint32_t overflow.

Bug: 905336, 905459
Change-Id: Ie518def9063143ef2393be566419a209f68f0dce
Reviewed-on: https://chromium-review.googlesource.com/c/1336083Reviewed-by: default avatarKenneth Russell <kbr@chromium.org>
Reviewed-by: default avatarAbhishek Arya <inferno@chromium.org>
Commit-Queue: Antoine Labour <piman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#608184}
parent f92523f1
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <string.h> #include <string.h>
#include "base/atomicops.h" #include "base/atomicops.h"
#include "base/numerics/checked_math.h"
#include "gpu/command_buffer/common/cmd_buffer_common.h" #include "gpu/command_buffer/common/cmd_buffer_common.h"
namespace gpu { namespace gpu {
...@@ -33,25 +34,38 @@ struct SizedResult { ...@@ -33,25 +34,38 @@ struct SizedResult {
// Returns the total size in bytes of the SizedResult for a given number of // Returns the total size in bytes of the SizedResult for a given number of
// results including the size field. // results including the size field.
static size_t ComputeSize(size_t num_results) { static uint32_t ComputeSize(base::CheckedNumeric<uint32_t> num_results) {
return sizeof(T) * num_results + sizeof(uint32_t); // NOLINT base::CheckedNumeric<uint32_t> size = num_results;
size *= sizeof(T);
size += sizeof(uint32_t);
return size.ValueOrDie();
} }
// Returns the maximum number of results for a given buffer size. // Returns the maximum number of results for a given buffer size.
static uint32_t ComputeMaxResults(size_t size_of_buffer) { static uint32_t ComputeMaxResults(size_t size_of_buffer) {
return (size_of_buffer >= sizeof(uint32_t)) base::CheckedNumeric<uint32_t> max_results = 0;
? ((size_of_buffer - sizeof(uint32_t)) / sizeof(T)) if (size_of_buffer >= sizeof(uint32_t)) {
: 0; // NOLINT max_results = size_of_buffer;
max_results -= sizeof(uint32_t);
max_results /= sizeof(T);
}
return max_results.ValueOrDefault(0);
} }
// Set the size for a given number of results. // Set the size for a given number of results.
void SetNumResults(size_t num_results) { void SetNumResults(base::CheckedNumeric<uint32_t> num_results) {
size = sizeof(T) * num_results; // NOLINT base::CheckedNumeric<uint32_t> bytes = num_results;
bytes *= sizeof(T);
size = bytes.ValueOrDie();
} }
// Get the number of elements in the result // Get the number of elements in the result
int32_t GetNumResults() const { int32_t GetNumResults() const {
return size / sizeof(T); // NOLINT // TODO(piman): return uint32_t here to remove the need for checked
// numerics.
base::CheckedNumeric<uint32_t> num_results = size;
num_results /= sizeof(T);
return num_results.ValueOrDie<int32_t>();
} }
// Copy the result. // Copy the result.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment