Commit b346beb3 authored by Adrienne Walker's avatar Adrienne Walker Committed by Commit Bot

oop: Add transfer cache deserialization fuzzer

Bug: 804301
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: I3b063e13c7b08b28d3973d1b16a2633101135fa6
Reviewed-on: https://chromium-review.googlesource.com/947046Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Reviewed-by: default avatarEric Karl <ericrk@chromium.org>
Reviewed-by: default avatarKhushal <khushalsagar@chromium.org>
Commit-Queue: enne <enne@chromium.org>
Cr-Commit-Position: refs/heads/master@{#541286}
parent 69c09e03
...@@ -134,3 +134,17 @@ fuzzer_test("paint_op_buffer_eq_fuzzer") { ...@@ -134,3 +134,17 @@ fuzzer_test("paint_op_buffer_eq_fuzzer") {
"//cc/paint", "//cc/paint",
] ]
} }
fuzzer_test("transfer_cache_fuzzer") {
sources = [
"transfer_cache_fuzzer.cc",
]
libfuzzer_options = [ "max_len=4096" ]
deps = [
"//cc:test_support",
"//cc/paint",
"//components/viz/test:test_support",
]
}
...@@ -2,4 +2,7 @@ specific_include_rules = { ...@@ -2,4 +2,7 @@ specific_include_rules = {
"paint_op_buffer_fuzzer.cc": [ "paint_op_buffer_fuzzer.cc": [
"+components/viz/test", "+components/viz/test",
], ],
"transfer_cache_fuzzer.cc": [
"+components/viz/test",
],
} }
...@@ -46,8 +46,8 @@ size_t ServiceColorSpaceTransferCacheEntry::CachedSize() const { ...@@ -46,8 +46,8 @@ size_t ServiceColorSpaceTransferCacheEntry::CachedSize() const {
bool ServiceColorSpaceTransferCacheEntry::Deserialize( bool ServiceColorSpaceTransferCacheEntry::Deserialize(
GrContext* context, GrContext* context,
base::span<uint8_t> data) { base::span<const uint8_t> data) {
base::Pickle pickle(reinterpret_cast<char*>(data.data()), data.size()); base::Pickle pickle(reinterpret_cast<const char*>(data.data()), data.size());
base::PickleIterator iterator(pickle); base::PickleIterator iterator(pickle);
if (!IPC::ParamTraits<gfx::ColorSpace>::Read(&pickle, &iterator, if (!IPC::ParamTraits<gfx::ColorSpace>::Read(&pickle, &iterator,
&color_space_)) &color_space_))
......
...@@ -44,7 +44,7 @@ class CC_PAINT_EXPORT ServiceColorSpaceTransferCacheEntry final ...@@ -44,7 +44,7 @@ class CC_PAINT_EXPORT ServiceColorSpaceTransferCacheEntry final
ServiceColorSpaceTransferCacheEntry(); ServiceColorSpaceTransferCacheEntry();
~ServiceColorSpaceTransferCacheEntry() override; ~ServiceColorSpaceTransferCacheEntry() override;
size_t CachedSize() const override; size_t CachedSize() const override;
bool Deserialize(GrContext* context, base::span<uint8_t> data) override; bool Deserialize(GrContext* context, base::span<const uint8_t> data) override;
const gfx::ColorSpace& color_space() const { return color_space_; } const gfx::ColorSpace& color_space() const { return color_space_; }
......
...@@ -87,8 +87,9 @@ size_t ServiceImageTransferCacheEntry::CachedSize() const { ...@@ -87,8 +87,9 @@ size_t ServiceImageTransferCacheEntry::CachedSize() const {
return size_; return size_;
} }
bool ServiceImageTransferCacheEntry::Deserialize(GrContext* context, bool ServiceImageTransferCacheEntry::Deserialize(
base::span<uint8_t> data) { GrContext* context,
base::span<const uint8_t> data) {
PaintOpReader reader(data.data(), data.size(), nullptr); PaintOpReader reader(data.data(), data.size(), nullptr);
SkColorType color_type; SkColorType color_type;
reader.Read(&color_type); reader.Read(&color_type);
...@@ -109,6 +110,8 @@ bool ServiceImageTransferCacheEntry::Deserialize(GrContext* context, ...@@ -109,6 +110,8 @@ bool ServiceImageTransferCacheEntry::Deserialize(GrContext* context,
SkImageInfo image_info = SkImageInfo::Make( SkImageInfo image_info = SkImageInfo::Make(
width, height, color_type, kPremul_SkAlphaType, pixmap_color_space); width, height, color_type, kPremul_SkAlphaType, pixmap_color_space);
if (image_info.computeMinByteSize() > pixel_size)
return false;
const volatile void* pixel_data = reader.ExtractReadableMemory(pixel_size); const volatile void* pixel_data = reader.ExtractReadableMemory(pixel_size);
if (!reader.valid()) if (!reader.valid())
return false; return false;
......
...@@ -54,7 +54,7 @@ class CC_PAINT_EXPORT ServiceImageTransferCacheEntry ...@@ -54,7 +54,7 @@ class CC_PAINT_EXPORT ServiceImageTransferCacheEntry
// ServiceTransferCacheEntry implementation: // ServiceTransferCacheEntry implementation:
size_t CachedSize() const final; size_t CachedSize() const final;
bool Deserialize(GrContext* context, base::span<uint8_t> data) final; bool Deserialize(GrContext* context, base::span<const uint8_t> data) final;
void set_image_for_testing(sk_sp<SkImage> image) { void set_image_for_testing(sk_sp<SkImage> image) {
image_ = std::move(image); image_ = std::move(image);
......
...@@ -118,7 +118,7 @@ size_t ServicePaintTypefaceTransferCacheEntry::CachedSize() const { ...@@ -118,7 +118,7 @@ size_t ServicePaintTypefaceTransferCacheEntry::CachedSize() const {
bool ServicePaintTypefaceTransferCacheEntry::Deserialize( bool ServicePaintTypefaceTransferCacheEntry::Deserialize(
GrContext* context, GrContext* context,
base::span<uint8_t> data) { base::span<const uint8_t> data) {
data_ = data; data_ = data;
size_t initial_size = data_.size(); size_t initial_size = data_.size();
...@@ -208,7 +208,7 @@ void ServicePaintTypefaceTransferCacheEntry::ReadSimple(T* val) { ...@@ -208,7 +208,7 @@ void ServicePaintTypefaceTransferCacheEntry::ReadSimple(T* val) {
valid_ = false; valid_ = false;
if (!valid_) if (!valid_)
return; return;
*val = *reinterpret_cast<T*>(data_.data()); *val = *reinterpret_cast<const T*>(data_.data());
data_ = data_.subspan(sizeof(T)); data_ = data_.subspan(sizeof(T));
} }
......
...@@ -37,7 +37,7 @@ class CC_PAINT_EXPORT ServicePaintTypefaceTransferCacheEntry ...@@ -37,7 +37,7 @@ class CC_PAINT_EXPORT ServicePaintTypefaceTransferCacheEntry
ServicePaintTypefaceTransferCacheEntry(); ServicePaintTypefaceTransferCacheEntry();
~ServicePaintTypefaceTransferCacheEntry() final; ~ServicePaintTypefaceTransferCacheEntry() final;
size_t CachedSize() const final; size_t CachedSize() const final;
bool Deserialize(GrContext* context, base::span<uint8_t> data) final; bool Deserialize(GrContext* context, base::span<const uint8_t> data) final;
const PaintTypeface& typeface() const { return typeface_; } const PaintTypeface& typeface() const { return typeface_; }
...@@ -50,7 +50,9 @@ class CC_PAINT_EXPORT ServicePaintTypefaceTransferCacheEntry ...@@ -50,7 +50,9 @@ class CC_PAINT_EXPORT ServicePaintTypefaceTransferCacheEntry
PaintTypeface typeface_; PaintTypeface typeface_;
size_t size_ = 0; size_t size_ = 0;
bool valid_ = true; bool valid_ = true;
base::span<uint8_t> data_; // TODO(enne): this transient value shouldn't be a member and should just be
// passed around internally to functions that need it.
base::span<const uint8_t> data_;
}; };
} // namespace cc } // namespace cc
......
...@@ -43,8 +43,9 @@ size_t ServiceRawMemoryTransferCacheEntry::CachedSize() const { ...@@ -43,8 +43,9 @@ size_t ServiceRawMemoryTransferCacheEntry::CachedSize() const {
return data_.size(); return data_.size();
} }
bool ServiceRawMemoryTransferCacheEntry::Deserialize(GrContext* context, bool ServiceRawMemoryTransferCacheEntry::Deserialize(
base::span<uint8_t> data) { GrContext* context,
base::span<const uint8_t> data) {
data_ = std::vector<uint8_t>(data.begin(), data.end()); data_ = std::vector<uint8_t>(data.begin(), data.end());
return true; return true;
} }
......
...@@ -37,7 +37,7 @@ class CC_PAINT_EXPORT ServiceRawMemoryTransferCacheEntry ...@@ -37,7 +37,7 @@ class CC_PAINT_EXPORT ServiceRawMemoryTransferCacheEntry
ServiceRawMemoryTransferCacheEntry(); ServiceRawMemoryTransferCacheEntry();
~ServiceRawMemoryTransferCacheEntry() final; ~ServiceRawMemoryTransferCacheEntry() final;
size_t CachedSize() const final; size_t CachedSize() const final;
bool Deserialize(GrContext* context, base::span<uint8_t> data) final; bool Deserialize(GrContext* context, base::span<const uint8_t> data) final;
const std::vector<uint8_t>& data() { return data_; } const std::vector<uint8_t>& data() { return data_; }
private: private:
......
...@@ -27,7 +27,6 @@ std::unique_ptr<ServiceTransferCacheEntry> ServiceTransferCacheEntry::Create( ...@@ -27,7 +27,6 @@ std::unique_ptr<ServiceTransferCacheEntry> ServiceTransferCacheEntry::Create(
return std::make_unique<ServiceColorSpaceTransferCacheEntry>(); return std::make_unique<ServiceColorSpaceTransferCacheEntry>();
} }
NOTREACHED();
return nullptr; return nullptr;
} }
......
...@@ -82,7 +82,8 @@ class CC_PAINT_EXPORT ServiceTransferCacheEntry { ...@@ -82,7 +82,8 @@ class CC_PAINT_EXPORT ServiceTransferCacheEntry {
// Deserialize the cache entry from the given span of memory with the given // Deserialize the cache entry from the given span of memory with the given
// context. // context.
virtual bool Deserialize(GrContext* context, base::span<uint8_t> data) = 0; virtual bool Deserialize(GrContext* context,
base::span<const uint8_t> data) = 0;
}; };
// Helpers to simplify subclassing. // Helpers to simplify subclassing.
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stddef.h>
#include <stdint.h>
#include "cc/paint/paint_op_buffer.h"
#include "cc/paint/raw_memory_transfer_cache_entry.h"
#include "cc/test/transfer_cache_test_helper.h"
#include "components/viz/test/test_context_provider.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrContext.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size < 4)
return 0;
scoped_refptr<viz::TestContextProvider> context_provider =
viz::TestContextProvider::Create();
context_provider->BindToCurrentThread();
cc::TransferCacheEntryType entry_type =
static_cast<cc::TransferCacheEntryType>(data[0]);
std::unique_ptr<cc::ServiceTransferCacheEntry> entry =
cc::ServiceTransferCacheEntry::Create(entry_type);
if (!entry)
return 0;
// Align data.
base::span<const uint8_t> span(&data[4], size - 4);
if (!entry->Deserialize(context_provider->GrContext(), span))
return 0;
// TODO(enne): consider running Serialize() here to fuzz that codepath
// for bugs. However, that requires setting up a real context with
// a raster interface that supports gl operations and that has a
// TransferCacheTestHelper in it so the innards of client and service
// are accessible.
return 0;
}
...@@ -46,16 +46,17 @@ bool ServiceTransferCache::CreateLockedEntry( ...@@ -46,16 +46,17 @@ bool ServiceTransferCache::CreateLockedEntry(
base::span<uint8_t> data) { base::span<uint8_t> data) {
auto key = std::make_pair(entry_type, entry_id); auto key = std::make_pair(entry_type, entry_id);
auto found = entries_.Peek(key); auto found = entries_.Peek(key);
if (found != entries_.end()) { if (found != entries_.end())
return false; return false;
}
std::unique_ptr<cc::ServiceTransferCacheEntry> entry = std::unique_ptr<cc::ServiceTransferCacheEntry> entry =
cc::ServiceTransferCacheEntry::Create(entry_type); cc::ServiceTransferCacheEntry::Create(entry_type);
if (!entry) if (!entry)
return false; return false;
entry->Deserialize(context, data); if (!entry->Deserialize(context, data))
return false;
total_size_ += entry->CachedSize(); total_size_ += entry->CachedSize();
entries_.Put(key, CacheEntryInternal(handle, std::move(entry))); entries_.Put(key, CacheEntryInternal(handle, std::move(entry)));
EnforceLimits(); EnforceLimits();
......
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