paint_op_buffer_fuzzer.cc 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <stddef.h>
  5. #include <stdint.h>
  6. #include "base/command_line.h"
  7. #include "base/logging.h"
  8. #include "base/process/memory.h"
  9. #include "base/test/test_discardable_memory_allocator.h"
  10. #include "cc/paint/paint_cache.h"
  11. #include "cc/paint/paint_op_buffer.h"
  12. #include "cc/paint/paint_op_writer.h"
  13. #include "cc/test/transfer_cache_test_helper.h"
  14. #include "components/viz/test/test_context_provider.h"
  15. #include "gpu/command_buffer/common/buffer.h"
  16. #include "gpu/command_buffer/service/service_font_manager.h"
  17. #include "third_party/skia/include/core/SkSurface.h"
  18. #include "third_party/skia/include/gpu/GrDirectContext.h"
  19. struct Environment {
  20. Environment() {
  21. // Disable noisy logging as per "libFuzzer in Chrome" documentation:
  22. // testing/libfuzzer/getting_started.md#Disable-noisy-error-message-logging.
  23. logging::SetMinLogLevel(logging::LOG_FATAL);
  24. base::EnableTerminationOnOutOfMemory();
  25. base::DiscardableMemoryAllocator::SetInstance(
  26. &discardable_memory_allocator);
  27. }
  28. ~Environment() { base::DiscardableMemoryAllocator::SetInstance(nullptr); }
  29. private:
  30. base::TestDiscardableMemoryAllocator discardable_memory_allocator;
  31. };
  32. class FontSupport : public gpu::ServiceFontManager::Client {
  33. public:
  34. FontSupport() = default;
  35. ~FontSupport() override = default;
  36. // gpu::ServiceFontManager::Client implementation.
  37. scoped_refptr<gpu::Buffer> GetShmBuffer(uint32_t shm_id) override {
  38. auto it = buffers_.find(shm_id);
  39. if (it != buffers_.end())
  40. return it->second;
  41. return CreateBuffer(shm_id);
  42. }
  43. void ReportProgress() override {}
  44. private:
  45. scoped_refptr<gpu::Buffer> CreateBuffer(uint32_t shm_id) {
  46. static const size_t kBufferSize = 2048u;
  47. base::UnsafeSharedMemoryRegion shared_memory =
  48. base::UnsafeSharedMemoryRegion::Create(kBufferSize);
  49. base::WritableSharedMemoryMapping mapping = shared_memory.Map();
  50. auto buffer = gpu::MakeBufferFromSharedMemory(std::move(shared_memory),
  51. std::move(mapping));
  52. buffers_[shm_id] = buffer;
  53. return buffer;
  54. }
  55. base::flat_map<uint32_t, scoped_refptr<gpu::Buffer>> buffers_;
  56. };
  57. void Raster(scoped_refptr<viz::TestContextProvider> context_provider,
  58. SkStrikeClient* strike_client,
  59. cc::ServicePaintCache* paint_cache,
  60. const uint8_t* data,
  61. size_t size) {
  62. const size_t kRasterDimension = 32;
  63. const size_t kMaxSerializedSize = 1000000;
  64. SkImageInfo image_info = SkImageInfo::MakeN32(
  65. kRasterDimension, kRasterDimension, kOpaque_SkAlphaType);
  66. context_provider->BindToCurrentThread();
  67. sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(
  68. context_provider->GrContext(), SkBudgeted::kYes, image_info);
  69. SkCanvas* canvas = surface->getCanvas();
  70. cc::PlaybackParams params(nullptr, canvas->getLocalToDevice());
  71. cc::TransferCacheTestHelper transfer_cache_helper;
  72. std::vector<uint8_t> scratch_buffer;
  73. cc::PaintOp::DeserializeOptions deserialize_options(
  74. &transfer_cache_helper, paint_cache, strike_client, &scratch_buffer,
  75. true /* is_privileged */, nullptr /* shared_image_provider */);
  76. // Need 4 bytes to be able to read the type/skip.
  77. while (size >= 4) {
  78. const cc::PaintOp* serialized = reinterpret_cast<const cc::PaintOp*>(data);
  79. if (serialized->skip > kMaxSerializedSize)
  80. break;
  81. std::unique_ptr<char, base::AlignedFreeDeleter> deserialized(
  82. static_cast<char*>(base::AlignedAlloc(
  83. sizeof(cc::LargestPaintOp), cc::PaintOpBuffer::PaintOpAlign)));
  84. size_t bytes_read = 0;
  85. cc::PaintOp* deserialized_op = cc::PaintOp::Deserialize(
  86. data, size, deserialized.get(), sizeof(cc::LargestPaintOp), &bytes_read,
  87. deserialize_options);
  88. if (!deserialized_op)
  89. break;
  90. deserialized_op->Raster(canvas, params);
  91. deserialized_op->DestroyThis();
  92. if (serialized->skip >= size)
  93. break;
  94. size -= bytes_read;
  95. data += bytes_read;
  96. }
  97. }
  98. // Deserialize an arbitrary number of cc::PaintOps and raster them
  99. // using gpu raster into an SkCanvas.
  100. extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  101. if (size <= sizeof(size_t))
  102. return 0;
  103. [[maybe_unused]] static Environment* env = new Environment();
  104. base::CommandLine::Init(0, nullptr);
  105. // Partition the data to use some bytes for populating the font cache.
  106. uint32_t bytes_for_fonts = data[0];
  107. if (bytes_for_fonts > size)
  108. bytes_for_fonts = size / 2;
  109. // PaintOpBuffer only accepts 4 bytes aligned buffer.
  110. bytes_for_fonts = base::bits::AlignDown(
  111. bytes_for_fonts,
  112. base::checked_cast<uint32_t>(cc::PaintOpWriter::Alignment()));
  113. FontSupport font_support;
  114. scoped_refptr<gpu::ServiceFontManager> font_manager(
  115. new gpu::ServiceFontManager(&font_support,
  116. false /* disable_oopr_debug_crash_dump */));
  117. cc::ServicePaintCache paint_cache;
  118. std::vector<SkDiscardableHandleId> locked_handles;
  119. if (bytes_for_fonts > 0u) {
  120. font_manager->Deserialize(reinterpret_cast<const char*>(data),
  121. bytes_for_fonts, &locked_handles);
  122. data += bytes_for_fonts;
  123. size -= bytes_for_fonts;
  124. }
  125. auto context_provider_no_support = viz::TestContextProvider::Create();
  126. context_provider_no_support->BindToCurrentThread();
  127. CHECK(!context_provider_no_support->GrContext()->supportsDistanceFieldText());
  128. Raster(context_provider_no_support, font_manager->strike_client(),
  129. &paint_cache, data, size);
  130. auto context_provider_with_support = viz::TestContextProvider::Create(
  131. std::string("GL_OES_standard_derivatives"));
  132. context_provider_with_support->BindToCurrentThread();
  133. CHECK(
  134. context_provider_with_support->GrContext()->supportsDistanceFieldText());
  135. Raster(context_provider_with_support, font_manager->strike_client(),
  136. &paint_cache, data, size);
  137. font_manager->Unlock(locked_handles);
  138. font_manager->Destroy();
  139. return 0;
  140. }