Add Dawn Wire Server LPM Fuzzer [2/N]
Add generators for protobuf files. This CL contains the basic logic required to generate the protobuf files from dawn.json and the newly added dawn_lpm.json for libprotobuf-mutator. Bug: chromium:1374747 Change-Id: I5dd207ed94ecdac365306c26e79b6cc18d3978f6 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/114640 Reviewed-by: Austin Eng <enga@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Brendon Tiszka <tiszka@chromium.org>
This commit is contained in:
parent
73570d8f48
commit
a045643361
|
@ -566,6 +566,76 @@ def compute_wire_params(api_params, wire_json):
|
||||||
|
|
||||||
return wire_params
|
return wire_params
|
||||||
|
|
||||||
|
############################################################
|
||||||
|
# DAWN LPM FUZZ STUFF
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
|
||||||
|
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 = []
|
||||||
|
|
||||||
|
# All commands, including hand written commands that we can't generate
|
||||||
|
# through codegen
|
||||||
|
proto_all_commands = []
|
||||||
|
|
||||||
|
# Remove blocklisted commands from protobuf generation params
|
||||||
|
blocklisted_cmds_proto = lpm_json.get('blocklisted_cmds')
|
||||||
|
custom_cmds_proto = lpm_json.get('custom_cmds')
|
||||||
|
for command in lpm_params['cmd_records']['command']:
|
||||||
|
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)
|
||||||
|
|
||||||
|
lpm_params['cmd_records'] = {
|
||||||
|
'proto_generated_commands': proto_generated_commands,
|
||||||
|
'proto_all_commands': proto_all_commands,
|
||||||
|
}
|
||||||
|
|
||||||
|
return lpm_params
|
||||||
|
|
||||||
|
|
||||||
|
def as_protobufTypeLPM(member):
|
||||||
|
assert 'type' in member.json_data
|
||||||
|
|
||||||
|
if member.type.name.native:
|
||||||
|
typ = member.json_data['type']
|
||||||
|
cpp_to_protobuf_type = {
|
||||||
|
"bool": "bool",
|
||||||
|
"float": "float",
|
||||||
|
"double": "double",
|
||||||
|
"int8_t": "int32",
|
||||||
|
"int16_t": "int32",
|
||||||
|
"int32_t": "int32",
|
||||||
|
"int64_t": "int64",
|
||||||
|
"uint8_t": "uint32",
|
||||||
|
"uint16_t": "uint32",
|
||||||
|
"uint32_t": "uint32",
|
||||||
|
"uint64_t": "uint64",
|
||||||
|
}
|
||||||
|
|
||||||
|
assert typ in cpp_to_protobuf_type
|
||||||
|
|
||||||
|
return cpp_to_protobuf_type[typ]
|
||||||
|
|
||||||
|
return member.type.name.CamelCase()
|
||||||
|
|
||||||
|
|
||||||
|
def as_protobufNameLPM(*names):
|
||||||
|
# `descriptor` is a reserved keyword in lpm
|
||||||
|
if (names[0].concatcase() == "descriptor"):
|
||||||
|
return "desc"
|
||||||
|
return as_varName(*names)
|
||||||
|
|
||||||
|
|
||||||
|
def unreachable_code():
|
||||||
|
assert False
|
||||||
|
|
||||||
#############################################################
|
#############################################################
|
||||||
# Generator
|
# Generator
|
||||||
|
@ -1039,11 +1109,17 @@ class MultiGeneratorFromDawnJSON(Generator):
|
||||||
params_dawn_wire = parse_json(loaded_json,
|
params_dawn_wire = parse_json(loaded_json,
|
||||||
enabled_tags=['dawn', 'deprecated'],
|
enabled_tags=['dawn', 'deprecated'],
|
||||||
disabled_tags=['native'])
|
disabled_tags=['native'])
|
||||||
additional_params = compute_wire_params(params_dawn_wire,
|
api_and_wire_params = compute_wire_params(params_dawn_wire,
|
||||||
wire_json)
|
wire_json)
|
||||||
|
|
||||||
|
fuzzer_params = compute_lpm_params(api_and_wire_params, lpm_json)
|
||||||
|
|
||||||
lpm_params = [
|
lpm_params = [
|
||||||
RENDER_PARAMS_BASE, params_dawn_wire, {}, additional_params
|
RENDER_PARAMS_BASE, params_dawn_wire, {
|
||||||
|
'as_protobufTypeLPM': as_protobufTypeLPM,
|
||||||
|
'as_protobufNameLPM': as_protobufNameLPM,
|
||||||
|
'unreachable': unreachable_code
|
||||||
|
}, api_and_wire_params, fuzzer_params
|
||||||
]
|
]
|
||||||
|
|
||||||
renders.append(
|
renders.append(
|
||||||
|
@ -1055,11 +1131,11 @@ class MultiGeneratorFromDawnJSON(Generator):
|
||||||
params_dawn_wire = parse_json(loaded_json,
|
params_dawn_wire = parse_json(loaded_json,
|
||||||
enabled_tags=['dawn', 'deprecated'],
|
enabled_tags=['dawn', 'deprecated'],
|
||||||
disabled_tags=['native'])
|
disabled_tags=['native'])
|
||||||
additional_params = compute_wire_params(params_dawn_wire,
|
api_and_wire_params = compute_wire_params(params_dawn_wire,
|
||||||
wire_json)
|
wire_json)
|
||||||
|
|
||||||
lpm_params = [
|
lpm_params = [
|
||||||
RENDER_PARAMS_BASE, params_dawn_wire, {}, additional_params
|
RENDER_PARAMS_BASE, params_dawn_wire, {}, api_and_wire_params
|
||||||
]
|
]
|
||||||
|
|
||||||
renders.append(
|
renders.append(
|
||||||
|
@ -1074,6 +1150,12 @@ class MultiGeneratorFromDawnJSON(Generator):
|
||||||
'src/dawn/fuzzers/lpmfuzz/DawnLPMSerializer_autogen.h',
|
'src/dawn/fuzzers/lpmfuzz/DawnLPMSerializer_autogen.h',
|
||||||
lpm_params))
|
lpm_params))
|
||||||
|
|
||||||
|
renders.append(
|
||||||
|
FileRender(
|
||||||
|
'dawn/fuzzers/lpmfuzz/DawnLPMConstants.h',
|
||||||
|
'src/dawn/fuzzers/lpmfuzz/DawnLPMConstants_autogen.h',
|
||||||
|
lpm_params))
|
||||||
|
|
||||||
return renders
|
return renders
|
||||||
|
|
||||||
def get_dependencies(self, args):
|
def get_dependencies(self, args):
|
||||||
|
|
|
@ -12,4 +12,8 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#define INSTANCE_OBJECT_ID 1
|
namespace DawnLPMFuzzer {
|
||||||
|
|
||||||
|
static constexpr int kInstanceObjectId = 1;
|
||||||
|
|
||||||
|
} // namespace DawnLPMFuzzer
|
|
@ -15,13 +15,134 @@
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
package fuzzing;
|
package fuzzing;
|
||||||
|
|
||||||
{% for command in cmd_records["command"] %}
|
|
||||||
message {{command.name.CamelCase()}} {}
|
{% for type in by_category["enum"] %}
|
||||||
|
enum {{as_cppType(type.name)}} {
|
||||||
|
{% for value in type.values %}
|
||||||
|
{{ as_cppType(type.name) }}{{as_cppEnum(value.name)}} = {{ value.value }};
|
||||||
|
{% endfor %}
|
||||||
|
};
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
{% for type in by_category["bitmask"] %}
|
||||||
|
enum {{as_cppType(type.name)}} {
|
||||||
|
{% for value in type.values %}
|
||||||
|
{{ as_cppType(type.name) }}{{as_cppEnum(value.name)}} = {{ value.value }};
|
||||||
|
{% endfor %}
|
||||||
|
};
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
{% macro lift_string_proto_member(member, count) -%}
|
||||||
|
required string {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
|
||||||
|
{% set count.value = count.value + 1 %}
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{% macro lift_float_array_proto_member(member, count) -%}
|
||||||
|
repeated float {{ as_varName(member.name) }} = {{ count.value }};
|
||||||
|
{% set count.value = count.value + 1 %}
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
|
||||||
|
{% macro lift_varlength_proto_member(member, count) -%}
|
||||||
|
{% if member.type in by_category["object"] %}
|
||||||
|
repeated uint32 {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
|
||||||
|
{% set count.value = count.value + 1 %}
|
||||||
|
{% elif member.type.name.get() == "object id" %}
|
||||||
|
repeated uint32 {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
|
||||||
|
{% set count.value = count.value + 1 %}
|
||||||
|
{% elif member.type.name.get() == "uint8_t" %}
|
||||||
|
// Skip over byte arrays in protobuf, handled by DawnSerializer
|
||||||
|
{% else %}
|
||||||
|
repeated {{ as_protobufTypeLPM(member) }} {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
|
||||||
|
{% set count.value = count.value + 1 %}
|
||||||
|
{% endif %}
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
|
||||||
|
{% macro lift_dawn_member_pass_by_value(record, name, member, count) %}
|
||||||
|
{% if member.type in by_category["structure"] %}
|
||||||
|
required {{ as_protobufTypeLPM(member) }} {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
|
||||||
|
{% set count.value = count.value + 1 %}
|
||||||
|
{% elif member.type in by_category["bitmask"] %}
|
||||||
|
repeated {{ as_protobufTypeLPM(member) }} {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
|
||||||
|
{% set count.value = count.value + 1 %}
|
||||||
|
{% elif member.type in by_category["enum"] %}
|
||||||
|
required {{ as_protobufTypeLPM(member) }} {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
|
||||||
|
{% set count.value = count.value + 1 %}
|
||||||
|
{% elif member.type in by_category["object"] %}
|
||||||
|
required uint32 {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
|
||||||
|
{% set count.value = count.value + 1 %}
|
||||||
|
{% elif member.type.name.get() == "ObjectId" %}
|
||||||
|
required uint32 {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
|
||||||
|
{% set count.value = count.value + 1 %}
|
||||||
|
{% elif member.type.name.get() == "ObjectHandle" %}
|
||||||
|
// Skips object handles while lifting dawn.json to protobuf because
|
||||||
|
// ObjectHandles are created and managed in DawnLPMSerializer. Passing
|
||||||
|
// arbitrary ObjectHandles from the fuzzer's bytestream isn't the
|
||||||
|
// strategy for this fuzzer.
|
||||||
|
{% else %}
|
||||||
|
required {{ as_protobufTypeLPM(member) }} {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
|
||||||
|
{% set count.value = count.value + 1 %}
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro lift_dawn_member_pass_by_pointer(record, name, member, count) %}
|
||||||
|
{% if member.type in by_category["structure"] and member.length == "constant" and member.constant_length == 1 %}
|
||||||
|
required {{ as_protobufTypeLPM(member) }} {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
|
||||||
|
{% set count.value = count.value + 1 %}
|
||||||
|
{% elif member.type.name.get() == "char" and member.length == 'strlen' %}
|
||||||
|
{{ lift_string_proto_member(member, count) }}
|
||||||
|
{% elif member.type.name.get() == "float" %}
|
||||||
|
{{ lift_float_array_proto_member(member, count) }}
|
||||||
|
{% elif member.type.name.get() == "uint8_t" %}
|
||||||
|
// Skip over byte arrays in protobuf, handled by DawnLPMSerializer
|
||||||
|
// with a hardcoded bytes and length.
|
||||||
|
{% elif member.length != 'constant' %}
|
||||||
|
{{ lift_varlength_proto_member(member, count) }}
|
||||||
|
{% else %}
|
||||||
|
// There shouldn't be any other pass-by-pointer types in
|
||||||
|
// dawn*.json, if any are added we would like to know at compile time
|
||||||
|
{{ unreachable_code }}
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro lift_proto_members_helper(record, name, members) %}
|
||||||
|
{% set count = namespace(value=1) %}
|
||||||
|
{% for member in members %}
|
||||||
|
{% if member.skip_serialize == True %}
|
||||||
|
// {{ member.name.camelCase()}}.skip_serialize
|
||||||
|
{% elif member.annotation == 'value' %}
|
||||||
|
{{ lift_dawn_member_pass_by_value(record, name, member, count) }}
|
||||||
|
{% elif member.annotation == 'const*' %}
|
||||||
|
{{ lift_dawn_member_pass_by_pointer(record, name, member, count) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
|
||||||
|
{% for structure in by_category["structure"] %}
|
||||||
|
message {{structure.name.CamelCase()}} {
|
||||||
|
{{ lift_proto_members_helper(structure, structure.name, structure.members) }}
|
||||||
|
}
|
||||||
|
{% 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 %}
|
||||||
|
|
||||||
|
|
||||||
message Command {
|
message Command {
|
||||||
oneof command {
|
oneof command {
|
||||||
{% for command in cmd_records["command"] %}
|
{% for command in cmd_records["proto_all_commands"] %}
|
||||||
{{command.name.CamelCase()}} {{command.name.camelCase()}} = {{ loop.index }};
|
{{command.name.CamelCase()}} {{command.name.camelCase()}} = {{ loop.index }};
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,6 +122,7 @@ if (is_dawn_lpm_fuzzer && build_with_chromium && dawn_use_swiftshader) {
|
||||||
outputs = [
|
outputs = [
|
||||||
"src/dawn/fuzzers/lpmfuzz/DawnLPMSerializer_autogen.cpp",
|
"src/dawn/fuzzers/lpmfuzz/DawnLPMSerializer_autogen.cpp",
|
||||||
"src/dawn/fuzzers/lpmfuzz/DawnLPMSerializer_autogen.h",
|
"src/dawn/fuzzers/lpmfuzz/DawnLPMSerializer_autogen.h",
|
||||||
|
"src/dawn/fuzzers/lpmfuzz/DawnLPMConstants_autogen.h",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "dawn/common/Log.h"
|
#include "dawn/common/Log.h"
|
||||||
#include "dawn/common/SystemUtils.h"
|
#include "dawn/common/SystemUtils.h"
|
||||||
#include "dawn/dawn_proc.h"
|
#include "dawn/dawn_proc.h"
|
||||||
#include "dawn/fuzzers/lpmfuzz/DawnLPMConstants.h"
|
#include "dawn/fuzzers/lpmfuzz/DawnLPMConstants_autogen.h"
|
||||||
#include "dawn/fuzzers/lpmfuzz/DawnLPMFuzzer.h"
|
#include "dawn/fuzzers/lpmfuzz/DawnLPMFuzzer.h"
|
||||||
#include "dawn/fuzzers/lpmfuzz/DawnLPMSerializer_autogen.h"
|
#include "dawn/fuzzers/lpmfuzz/DawnLPMSerializer_autogen.h"
|
||||||
#include "dawn/fuzzers/lpmfuzz/dawn_lpm_autogen.pb.h"
|
#include "dawn/fuzzers/lpmfuzz/dawn_lpm_autogen.pb.h"
|
||||||
|
@ -68,7 +68,9 @@ WGPUSwapChain ErrorDeviceCreateSwapChain(WGPUDevice device,
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
int DawnLPMFuzzer::Initialize(int* argc, char*** argv) {
|
namespace DawnLPMFuzzer {
|
||||||
|
|
||||||
|
int Initialize(int* argc, char*** argv) {
|
||||||
// TODO(crbug.com/1038952): The Instance must be static because destructing the vkInstance with
|
// TODO(crbug.com/1038952): The Instance must be static because destructing the vkInstance with
|
||||||
// Swiftshader crashes libFuzzer. When this is fixed, move this into Run so that error injection
|
// Swiftshader crashes libFuzzer. When this is fixed, move this into Run so that error injection
|
||||||
// for adapter discovery can be fuzzed.
|
// for adapter discovery can be fuzzed.
|
||||||
|
@ -78,8 +80,7 @@ int DawnLPMFuzzer::Initialize(int* argc, char*** argv) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DawnLPMFuzzer::Run(const fuzzing::Program& program,
|
int Run(const fuzzing::Program& program, bool (*AdapterSupported)(const dawn::native::Adapter&)) {
|
||||||
bool (*AdapterSupported)(const dawn::native::Adapter&)) {
|
|
||||||
sAdapterSupported = AdapterSupported;
|
sAdapterSupported = AdapterSupported;
|
||||||
|
|
||||||
DawnProcTable procs = dawn::native::GetProcs();
|
DawnProcTable procs = dawn::native::GetProcs();
|
||||||
|
@ -115,7 +116,7 @@ int DawnLPMFuzzer::Run(const fuzzing::Program& program,
|
||||||
serverDesc.serializer = &devNull;
|
serverDesc.serializer = &devNull;
|
||||||
|
|
||||||
std::unique_ptr<dawn::wire::WireServer> wireServer(new dawn_wire::WireServer(serverDesc));
|
std::unique_ptr<dawn::wire::WireServer> wireServer(new dawn_wire::WireServer(serverDesc));
|
||||||
wireServer->InjectInstance(sInstance->Get(), INSTANCE_OBJECT_ID, 0);
|
wireServer->InjectInstance(sInstance->Get(), kInstanceObjectId, 0);
|
||||||
|
|
||||||
static utils::TerribleCommandBuffer* mCommandBuffer = new utils::TerribleCommandBuffer();
|
static utils::TerribleCommandBuffer* mCommandBuffer = new utils::TerribleCommandBuffer();
|
||||||
static dawn::wire::ChunkedCommandSerializer mSerializer =
|
static dawn::wire::ChunkedCommandSerializer mSerializer =
|
||||||
|
@ -131,3 +132,5 @@ int DawnLPMFuzzer::Run(const fuzzing::Program& program,
|
||||||
wireServer = nullptr;
|
wireServer = nullptr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace DawnLPMFuzzer
|
||||||
|
|
|
@ -15,5 +15,18 @@
|
||||||
"limitations under the License."
|
"limitations under the License."
|
||||||
],
|
],
|
||||||
|
|
||||||
"_doc": "See docs/dawn/codegen.md"
|
"_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",
|
||||||
|
"device create shader module",
|
||||||
|
"destroy object"
|
||||||
|
]
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue