Commit 3e5db1a4 authored by Céline O'Neil's avatar Céline O'Neil Committed by Commit Bot

Fuzz multiple quads and SharedQuadState in CompositorFrame.

This CL adds the possibility of multiple SolidColorDrawQuads in the
fuzzed CompositorFrame RenderPass, and also introduces simple fuzzing
for the SharedQuadState associated with each quad.

One thing in particular to watch out for here is that a non-invertible
SharedQuadState Transform will get through message deserialization, but
likely cause DCHECKs to fail when drawing the RenderPass. I expect that
ClusterFuzz will find a few ways of triggering these checks with
different interesting values of |scale_x| and |scale_y|.

R=kylechar@chromium.org, riajiang@chromium.org

Bug: 923088
Change-Id: Ie51340c45c406d235047f6baabf24f947a51722b
Reviewed-on: https://chromium-review.googlesource.com/c/1496096Reviewed-by: default avatarRia Jiang <riajiang@chromium.org>
Reviewed-by: default avatarkylechar <kylechar@chromium.org>
Commit-Queue: Céline O'Neil <celineo@google.com>
Cr-Commit-Position: refs/heads/master@{#636965}
parent ba1a0e92
......@@ -28,6 +28,7 @@ action_foreach("generate_seed_corpus") {
input_dir = "text_format_seed_corpus"
sources = [
"$input_dir/1_quad_renderpass.asciipb",
"$input_dir/2_quad_renderpass.asciipb",
]
outputs = [
"$seed_corpus_dir/{{source_name_part}}.pb",
......
......@@ -9,14 +9,35 @@ package content.fuzzing.proto;
message RenderPass {
required Rect output_rect = 1;
required Rect damage_rect = 2;
required SolidColorDrawQuad draw_quad = 3;
repeated DrawQuad quad_list = 3;
}
message DrawQuad {
required SharedQuadState sqs = 1;
required Rect rect = 2;
required Rect visible_rect = 3;
required SolidColorDrawQuad quad = 4;
}
message SharedQuadState {
required Transform transform = 1;
required Rect layer_rect = 2;
required Rect visible_rect = 3;
required Rect clip_rect = 4;
required bool is_clipped = 5;
required bool are_contents_opaque = 6;
// Will be normalized to a float in [0,1].
required fixed32 opacity = 7 [default = 0xffffffff];
// TODO(celineo): add fuzzable SkBlendMode, crbug.com/923088
required sint32 sorting_context_id = 9;
}
message SolidColorDrawQuad {
required Rect rect = 1;
required Rect visible_rect = 2;
required fixed32 color = 3 [default = 0xffffffff];
required bool force_anti_aliasing_off = 4;
required fixed32 color = 1 [default = 0xffffffff];
required bool force_anti_aliasing_off = 2;
}
// Spec to initialize a gfx::Rect.
......@@ -28,4 +49,14 @@ message Rect {
required sint32 y = 2 [default = 0];
required sint32 width = 3 [default = 620];
required sint32 height = 4 [default = 400];
}
\ No newline at end of file
}
message Transform {
required double rotate = 1 [default = 0];
required float scale_x = 2 [default = 1];
required float scale_y = 3 [default = 1];
required float translate_x = 4 [default = 0];
required float translate_y = 5 [default = 0];
}
......@@ -4,6 +4,7 @@
#include "components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.h"
#include <limits>
#include <memory>
#include <utility>
......@@ -14,11 +15,42 @@ namespace viz {
namespace {
// Handles inf / NaN by setting to 0.
double MakeNormal(double x) {
return isnormal(x) ? x : 0;
}
float MakeNormal(float x) {
return isnormal(x) ? x : 0;
}
// Normalizes value to a float in [0, 1]. Use to convert a fuzzed
// uint32 into a percentage.
float Normalize(uint32_t x) {
return static_cast<float>(x) / std::numeric_limits<uint32_t>::max();
}
gfx::Rect GetRectFromProtobuf(const content::fuzzing::proto::Rect& proto_rect) {
return gfx::Rect(proto_rect.x(), proto_rect.y(), proto_rect.width(),
proto_rect.height());
}
gfx::Transform GetTransformFromProtobuf(
const content::fuzzing::proto::Transform& proto_transform) {
gfx::Transform transform = gfx::Transform();
// Note: There are no checks here that disallow a non-invertible transform
// (for instance, if |scale_x| or |scale_y| is 0).
transform.Scale(MakeNormal(proto_transform.scale_x()),
MakeNormal(proto_transform.scale_y()));
transform.Rotate(MakeNormal(proto_transform.rotate()));
transform.Translate(MakeNormal(proto_transform.translate_x()),
MakeNormal(proto_transform.translate_y()));
return transform;
}
// Mutates a gfx::Rect to ensure width and height are both at least min_size.
// Use in case e.g. a 0-width/height Rect would cause a validation error on
// deserialization.
......@@ -78,26 +110,30 @@ CompositorFrame GenerateFuzzedCompositorFrame(
pass->SetNew(1, rp_output_rect, rp_damage_rect, gfx::Transform());
content::fuzzing::proto::SolidColorDrawQuad quad_spec =
render_pass_spec.draw_quad();
gfx::Rect quad_rect = GetRectFromProtobuf(quad_spec.rect());
gfx::Rect quad_visible_rect = GetRectFromProtobuf(quad_spec.visible_rect());
// Handle constraints on DrawQuad:
// Ensure that |quad_rect| has non-zero area and that |quad_visible_rect| is
// contained in |quad_rect|.
ExpandToMinSize(&quad_rect, 1);
quad_visible_rect.AdjustToFit(quad_rect);
auto* shared_quad_state = pass->CreateAndAppendSharedQuadState();
shared_quad_state->SetAll(gfx::Transform(), gfx::Rect(quad_rect),
gfx::Rect(quad_rect), gfx::Rect(quad_rect),
/*is_clipped=*/false,
/*are_contents_opaque=*/false, 1,
SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
color_quad->SetNew(shared_quad_state, quad_rect, quad_visible_rect,
quad_spec.color(), quad_spec.force_anti_aliasing_off());
for (const auto& quad_spec : render_pass_spec.quad_list()) {
gfx::Rect quad_rect = GetRectFromProtobuf(quad_spec.rect());
gfx::Rect quad_visible_rect = GetRectFromProtobuf(quad_spec.visible_rect());
// Handle constraints on DrawQuad:
// Ensure that |quad_rect| has non-zero area and that |quad_visible_rect| is
// contained in |quad_rect|.
ExpandToMinSize(&quad_rect, 1);
quad_visible_rect.AdjustToFit(quad_rect);
auto* shared_quad_state = pass->CreateAndAppendSharedQuadState();
shared_quad_state->SetAll(
GetTransformFromProtobuf(quad_spec.sqs().transform()),
GetRectFromProtobuf(quad_spec.sqs().layer_rect()),
GetRectFromProtobuf(quad_spec.sqs().visible_rect()),
GetRectFromProtobuf(quad_spec.sqs().clip_rect()),
quad_spec.sqs().is_clipped(), quad_spec.sqs().are_contents_opaque(),
Normalize(quad_spec.sqs().opacity()), SkBlendMode::kSrcOver,
quad_spec.sqs().sorting_context_id());
auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
color_quad->SetNew(shared_quad_state, quad_rect, quad_visible_rect,
quad_spec.quad().color(),
quad_spec.quad().force_anti_aliasing_off());
}
frame.render_pass_list.push_back(std::move(pass));
return frame;
......
......@@ -10,19 +10,54 @@ damage_rect: {
width: 620
height: 400
}
draw_quad: {
rect: {
x: 0
y: 0
width: 620
height: 400
quad_list: [
{
rect: {
x: 0
y: 0
width: 620
height: 400
}
visible_rect: {
x: 0
y: 0
width: 620
height: 400
}
quad: {
color: 0xffffffff
force_anti_aliasing_off: false
}
sqs: {
transform: {
rotate: -90
scale_x: 0.5
scale_y: 1.5
translate_x: -50
translate_y: 10
}
layer_rect: {
x: 0
y: 0
width: 620
height: 400
}
visible_rect: {
x: 0
y: 0
width: 620
height: 400
}
clip_rect: {
x: 0
y: 0
width: 620
height: 400
}
is_clipped: false
are_contents_opaque: false
opacity: 0xffffffff
sorting_context_id: 0
}
}
visible_rect: {
x: 0
y: 0
width: 620
height: 400
}
color: 0xffffffff
force_anti_aliasing_off: false
}
]
output_rect: {
x: 0
y: 0
width: 620
height: 400
}
damage_rect: {
x: 0
y: 0
width: 620
height: 400
}
quad_list: [
{
rect: {
x: 0
y: 0
width: 620
height: 400
}
visible_rect: {
x: 0
y: 0
width: 620
height: 400
}
quad: {
color: 0xffffffff
force_anti_aliasing_off: false
}
sqs: {
transform: {
rotate: -90
scale_x: -0.5
scale_y: -1.5
translate_x: -50
translate_y: 10
}
layer_rect: {
x: 0
y: 0
width: 620
height: 400
}
visible_rect: {
x: 0
y: 0
width: 620
height: 400
}
clip_rect: {
x: 0
y: 0
width: 620
height: 400
}
is_clipped: true
are_contents_opaque: false
opacity: 0
sorting_context_id: 0
}
},
{
rect: {
x: 0
y: 0
width: 620
height: 400
}
visible_rect: {
x: 0
y: 0
width: 620
height: 400
}
quad: {
color: 0xff000000
force_anti_aliasing_off: true
}
sqs: {
transform: {
rotate: 90
scale_x: 0.5
scale_y: 1.5
translate_x: 50
translate_y: -10
}
layer_rect: {
x: 0
y: 0
width: 620
height: 400
}
visible_rect: {
x: 0
y: 0
width: 620
height: 400
}
clip_rect: {
x: 0
y: 0
width: 620
height: 400
}
is_clipped: false
are_contents_opaque: false
opacity: 0xffffffff
sorting_context_id: 1
}
}
]
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