Add Dawn Wire Server LPM Fuzzer [3/N]

Add ability to define custom protobuf structures for commands that
need to be hand written.

Bug: chromium:1374747
Change-Id: I69d5c55d69c3544835a23e4e0360900b991ccbd3
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/114643
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Brendon Tiszka <tiszka@chromium.org>
This commit is contained in:
Brendon Tiszka 2023-05-02 21:41:22 +00:00 committed by Dawn LUCI CQ
parent ebafab6556
commit 1f8413f50a
8 changed files with 106 additions and 48 deletions

View File

@ -580,12 +580,12 @@ def compute_lpm_params(api_and_wire_params, lpm_json):
# Start with all commands in dawn.json and dawn_wire.json
lpm_params = api_and_wire_params.copy()
# Commands that are built through generation
proto_generated_commands = []
# Commands that are built through codegen
generated_commands = []
# All commands, including hand written commands that we can't generate
# through codegen
proto_all_commands = []
all_commands = []
# Remove blocklisted commands from protobuf generation params
blocklisted_cmds_proto = lpm_json.get('blocklisted_cmds')
@ -594,13 +594,17 @@ def compute_lpm_params(api_and_wire_params, lpm_json):
blocklisted = command.name.get() in blocklisted_cmds_proto
custom = command.name.get() in custom_cmds_proto
if not blocklisted and not custom:
proto_generated_commands.append(command)
proto_all_commands.append(command)
if blocklisted:
continue
if not custom:
generated_commands.append(command)
all_commands.append(command)
lpm_params['cmd_records'] = {
'proto_generated_commands': proto_generated_commands,
'proto_all_commands': proto_all_commands,
'proto_generated_commands': generated_commands,
'proto_all_commands': all_commands,
'cpp_generated_commands': generated_commands
}
return lpm_params
@ -1132,6 +1136,12 @@ class MultiGeneratorFromDawnJSON(Generator):
'src/dawn/fuzzers/lpmfuzz/dawn_lpm_autogen.proto',
lpm_params))
renders.append(
FileRender(
'dawn/fuzzers/lpmfuzz/dawn_object_types_lpm.proto',
'src/dawn/fuzzers/lpmfuzz/dawn_object_types_lpm_autogen.proto',
lpm_params))
if 'dawn_lpmfuzz_cpp' in targets:
params_dawn_wire = parse_json(loaded_json,
enabled_tags=['dawn', 'deprecated'],
@ -1139,8 +1149,11 @@ class MultiGeneratorFromDawnJSON(Generator):
api_and_wire_params = compute_wire_params(params_dawn_wire,
wire_json)
fuzzer_params = compute_lpm_params(api_and_wire_params, lpm_json)
lpm_params = [
RENDER_PARAMS_BASE, params_dawn_wire, {}, api_and_wire_params
RENDER_PARAMS_BASE, params_dawn_wire, {}, api_and_wire_params,
fuzzer_params
]
renders.append(

View File

@ -30,7 +30,7 @@ void SerializedData(const fuzzing::Program& program, dawn::wire::ChunkedCommandS
for (const fuzzing::Command& command : program.commands()) {
switch (command.command_case()) {
{% for command in cmd_records["command"] %}
{% for command in cmd_records["cpp_generated_commands"] %}
case fuzzing::Command::k{{command.name.CamelCase()}}: {
{{ command.name.CamelCase() }}Cmd {{ 'cmd' }};
// TODO(chromium:1374747): Populate command buffer with serialized code from generated

View File

@ -15,6 +15,7 @@
syntax = "proto2";
package fuzzing;
import "third_party/dawn/src/dawn/fuzzers/lpmfuzz/dawn_custom_lpm.proto";
{% for type in by_category["enum"] %}
enum {{as_cppType(type.name)}} {
@ -129,16 +130,12 @@ package fuzzing;
{% endfor %}
{% for command in cmd_records["proto_all_commands"] %}
{% if command not in cmd_records["proto_generated_commands"] %}
message {{command.name.CamelCase()}} {}
{% else %}
message {{command.name.CamelCase()}} {
{{ lift_proto_members_helper(command, command.name, command.members) }}
}
{% endif %}
{% endfor %}
{% for command in cmd_records["proto_generated_commands"] %}
message {{command.name.CamelCase()}} {
{{ lift_proto_members_helper(command, command.name, command.members) }}
}
{% endfor %}
message Command {
oneof command {

View File

@ -0,0 +1,22 @@
// Copyright 2023 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto2";
package fuzzing;
enum ObjectType {
{% for type in by_category["object"] %}
{{ type.name.CamelCase() }} = {{ loop.index - 1}};
{% endfor %}
};

View File

@ -128,26 +128,42 @@ if (is_dawn_lpm_fuzzer && build_with_chromium && dawn_use_swiftshader) {
dawn_json_lpm_generator("dawn_lpmfuzz_proto") {
target = "dawn_lpmfuzz_proto"
outputs = [ "src/dawn/fuzzers/lpmfuzz/dawn_lpm_autogen.proto" ]
outputs = [
"src/dawn/fuzzers/lpmfuzz/dawn_lpm_autogen.proto",
"src/dawn/fuzzers/lpmfuzz/dawn_object_types_lpm_autogen.proto",
]
}
copy("copy_dawn_custom_lpms") {
# Hardcoded paths because we can't get_target_outputs from a proto_library
# TODO(tiszka): crbug.com/1410213
sources = [ "${dawn_root}/src/dawn/fuzzers/lpmfuzz/dawn_custom_lpm.proto" ]
outputs = [ "$root_out_dir/gen/third_party/dawn/src/dawn/fuzzers/lpmfuzz/dawn_custom_lpm.proto" ]
}
proto_library("dawn_lpm_proto") {
proto_in_dir = "//"
proto_in_dir = "$root_out_dir/gen"
sources = get_target_outputs(":dawn_lpmfuzz_proto")
sources += get_target_outputs(":copy_dawn_custom_lpms")
use_protobuf_full = true
deps = [
":copy_dawn_custom_lpms",
":dawn_lpmfuzz_proto",
"//third_party/protobuf:protobuf_full",
]
}
copy("copy_dawn_lpm_proto_outputs") {
# Hardcoded filenames because we can't get_target_outputs from a proto_library
# Hardcoded paths because we can't get_target_outputs from a proto_library
# TODO(tiszka): crbug.com/1410213
sources = [
"$root_out_dir/gen/$root_out_dir/gen/third_party/dawn/src/dawn/fuzzers/lpmfuzz/dawn_custom_lpm.pb.cc",
"$root_out_dir/gen/$root_out_dir/gen/third_party/dawn/src/dawn/fuzzers/lpmfuzz/dawn_custom_lpm.pb.h",
"$root_out_dir/gen/$root_out_dir/gen/third_party/dawn/src/dawn/fuzzers/lpmfuzz/dawn_lpm_autogen.pb.cc",
"$root_out_dir/gen/$root_out_dir/gen/third_party/dawn/src/dawn/fuzzers/lpmfuzz/dawn_lpm_autogen.pb.h",
"$root_out_dir/gen/$root_out_dir/gen/third_party/dawn/src/dawn/fuzzers/lpmfuzz/dawn_object_types_lpm_autogen.pb.cc",
"$root_out_dir/gen/$root_out_dir/gen/third_party/dawn/src/dawn/fuzzers/lpmfuzz/dawn_object_types_lpm_autogen.pb.h",
]
outputs = [ "$root_out_dir/gen/third_party/dawn/src/dawn/fuzzers/lpmfuzz/{{source_file_part}}" ]
deps = [ ":dawn_lpm_proto" ]

View File

@ -54,18 +54,8 @@ class DevNull : public dawn::wire::CommandSerializer {
};
std::unique_ptr<dawn::native::Instance> sInstance;
WGPUProcDeviceCreateSwapChain sOriginalDeviceCreateSwapChain = nullptr;
static bool (*sAdapterSupported)(const dawn::native::Adapter&) = nullptr;
WGPUSwapChain ErrorDeviceCreateSwapChain(WGPUDevice device,
WGPUSurface surface,
const WGPUSwapChainDescriptor*) {
WGPUSwapChainDescriptor desc = {};
// A 0 implementation will trigger a swapchain creation error.
desc.implementation = 0;
return sOriginalDeviceCreateSwapChain(device, surface, &desc);
}
} // namespace
namespace DawnLPMFuzzer {
@ -85,13 +75,6 @@ int Run(const fuzzing::Program& program, bool (*AdapterSupported)(const dawn::na
DawnProcTable procs = dawn::native::GetProcs();
// Swapchains receive a pointer to an implementation. The fuzzer will pass garbage in so we
// intercept calls to create swapchains and make sure they always return error swapchains.
// This is ok for fuzzing because embedders of dawn_wire would always define their own
// swapchain handling.
sOriginalDeviceCreateSwapChain = procs.deviceCreateSwapChain;
procs.deviceCreateSwapChain = ErrorDeviceCreateSwapChain;
// Override requestAdapter to find an adapter that the fuzzer supports.
procs.instanceRequestAdapter = [](WGPUInstance cInstance,
const WGPURequestAdapterOptions* options,

View File

@ -0,0 +1,27 @@
// Copyright 2023 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto2";
package fuzzing;
import "third_party/dawn/src/dawn/fuzzers/lpmfuzz/dawn_object_types_lpm_autogen.proto";
message DeviceCreateShaderModule {
required uint32 self = 1;
}
message DestroyObject {
required ObjectType objectType = 1;
required uint32 objectId = 2;
}

View File

@ -17,16 +17,16 @@
"_doc": "See docs/dawn/codegen.md",
"custom_cmds": [],
"blocklisted_cmds": [
"surface descriptor from windows core window",
"surface descriptor from windows swap chain panel",
"surface descriptor from canvas html selector",
"device create render pipeline",
"device create render pipeline async",
"custom_cmds": [
"device create shader module",
"destroy object"
]
],
"blocklisted_cmds": [
"device create render pipeline",
"device create render pipeline async",
"surface descriptor from windows core window",
"surface descriptor from windows swap chain panel",
"surface descriptor from canvas html selector"
]
}