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
|
||||
|
||||
############################################################
|
||||
# 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
|
||||
|
@ -1039,11 +1109,17 @@ class MultiGeneratorFromDawnJSON(Generator):
|
|||
params_dawn_wire = parse_json(loaded_json,
|
||||
enabled_tags=['dawn', 'deprecated'],
|
||||
disabled_tags=['native'])
|
||||
additional_params = compute_wire_params(params_dawn_wire,
|
||||
wire_json)
|
||||
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, {}, 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(
|
||||
|
@ -1055,11 +1131,11 @@ class MultiGeneratorFromDawnJSON(Generator):
|
|||
params_dawn_wire = parse_json(loaded_json,
|
||||
enabled_tags=['dawn', 'deprecated'],
|
||||
disabled_tags=['native'])
|
||||
additional_params = compute_wire_params(params_dawn_wire,
|
||||
wire_json)
|
||||
api_and_wire_params = compute_wire_params(params_dawn_wire,
|
||||
wire_json)
|
||||
|
||||
lpm_params = [
|
||||
RENDER_PARAMS_BASE, params_dawn_wire, {}, additional_params
|
||||
RENDER_PARAMS_BASE, params_dawn_wire, {}, api_and_wire_params
|
||||
]
|
||||
|
||||
renders.append(
|
||||
|
@ -1074,6 +1150,12 @@ class MultiGeneratorFromDawnJSON(Generator):
|
|||
'src/dawn/fuzzers/lpmfuzz/DawnLPMSerializer_autogen.h',
|
||||
lpm_params))
|
||||
|
||||
renders.append(
|
||||
FileRender(
|
||||
'dawn/fuzzers/lpmfuzz/DawnLPMConstants.h',
|
||||
'src/dawn/fuzzers/lpmfuzz/DawnLPMConstants_autogen.h',
|
||||
lpm_params))
|
||||
|
||||
return renders
|
||||
|
||||
def get_dependencies(self, args):
|
||||
|
|
|
@ -12,4 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#define INSTANCE_OBJECT_ID 1
|
||||
namespace DawnLPMFuzzer {
|
||||
|
||||
static constexpr int kInstanceObjectId = 1;
|
||||
|
||||
} // namespace DawnLPMFuzzer
|
|
@ -15,13 +15,134 @@
|
|||
syntax = "proto2";
|
||||
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 %}
|
||||
|
||||
|
||||
{% 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 {
|
||||
oneof command {
|
||||
{% for command in cmd_records["command"] %}
|
||||
{% for command in cmd_records["proto_all_commands"] %}
|
||||
{{command.name.CamelCase()}} {{command.name.camelCase()}} = {{ loop.index }};
|
||||
{% endfor %}
|
||||
}
|
||||
|
@ -29,4 +150,4 @@ message Command {
|
|||
|
||||
message Program {
|
||||
repeated Command commands = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,6 +122,7 @@ if (is_dawn_lpm_fuzzer && build_with_chromium && dawn_use_swiftshader) {
|
|||
outputs = [
|
||||
"src/dawn/fuzzers/lpmfuzz/DawnLPMSerializer_autogen.cpp",
|
||||
"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/SystemUtils.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/DawnLPMSerializer_autogen.h"
|
||||
#include "dawn/fuzzers/lpmfuzz/dawn_lpm_autogen.pb.h"
|
||||
|
@ -68,7 +68,9 @@ WGPUSwapChain ErrorDeviceCreateSwapChain(WGPUDevice device,
|
|||
|
||||
} // 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
|
||||
// Swiftshader crashes libFuzzer. When this is fixed, move this into Run so that error injection
|
||||
// for adapter discovery can be fuzzed.
|
||||
|
@ -78,8 +80,7 @@ int DawnLPMFuzzer::Initialize(int* argc, char*** argv) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int DawnLPMFuzzer::Run(const fuzzing::Program& program,
|
||||
bool (*AdapterSupported)(const dawn::native::Adapter&)) {
|
||||
int Run(const fuzzing::Program& program, bool (*AdapterSupported)(const dawn::native::Adapter&)) {
|
||||
sAdapterSupported = AdapterSupported;
|
||||
|
||||
DawnProcTable procs = dawn::native::GetProcs();
|
||||
|
@ -115,7 +116,7 @@ int DawnLPMFuzzer::Run(const fuzzing::Program& program,
|
|||
serverDesc.serializer = &devNull;
|
||||
|
||||
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 dawn::wire::ChunkedCommandSerializer mSerializer =
|
||||
|
@ -131,3 +132,5 @@ int DawnLPMFuzzer::Run(const fuzzing::Program& program,
|
|||
wireServer = nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace DawnLPMFuzzer
|
||||
|
|
|
@ -15,5 +15,18 @@
|
|||
"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