1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
|
#include <protozero/pbf_reader.hpp>
// From Google Benchmark library.
// See https://github.com/google/benchmark/blob/main/LICENSE
template <class Tp>
inline __attribute__((always_inline)) void DoNotOptimize(Tp const& value) {
asm volatile("" : : "r,m"(value) : "memory");
}
template <typename T>
int read_packed(protozero::iterator_range<T> range) {
try {
for (const auto& item : range) {
DoNotOptimize(item);
}
} catch (const protozero::exception&) {
// no-op. This is probably not a packed field of that type.
}
return 0;
}
template <typename Fn>
void try_field(const protozero::pbf_reader& reader, Fn&& fn) {
try {
DoNotOptimize(fn(reader));
} catch (const protozero::exception&) {
// no-op. This is probably not a field of that type.
}
}
int try_message(protozero::pbf_reader reader) {
try {
while (reader.next()) {
if (reader.has_wire_type(protozero::pbf_wire_type::varint)) {
// Try to decode this field as any of the types that can be encoded as varint.
try_field(reader, [](protozero::pbf_reader r) { return r.get_bool(); });
try_field(reader, [](protozero::pbf_reader r) { return r.get_enum(); });
try_field(reader, [](protozero::pbf_reader r) { return r.get_int32(); });
try_field(reader, [](protozero::pbf_reader r) { return r.get_sint32(); });
try_field(reader, [](protozero::pbf_reader r) { return r.get_uint32(); });
try_field(reader, [](protozero::pbf_reader r) { return r.get_int64(); });
try_field(reader, [](protozero::pbf_reader r) { return r.get_sint64(); });
try_field(reader, [](protozero::pbf_reader r) { return r.get_uint64(); });
} else if (reader.has_wire_type(protozero::pbf_wire_type::length_delimited)) {
// Try to decode this field as any of the types that can be encoded as length-delimited.
try_field(reader, [](protozero::pbf_reader r) { return try_message(r.get_message()); });
try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_bool()); });
try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_double()); });
try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_enum()); });
try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_fixed32()); });
try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_fixed64()); });
try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_float()); });
try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_int32()); });
try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_int64()); });
try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_sfixed32()); });
try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_sfixed64()); });
try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_sint32()); });
try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_sint64()); });
try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_uint32()); });
try_field(reader, [](protozero::pbf_reader r) { return read_packed(r.get_packed_uint64()); });
} else if (reader.has_wire_type(protozero::pbf_wire_type::fixed64)) {
// Try to decode this field as any of the types that can be encoded as fixed64.
try_field(reader, [](protozero::pbf_reader r) { return r.get_double(); });
try_field(reader, [](protozero::pbf_reader r) { return r.get_fixed64(); });
try_field(reader, [](protozero::pbf_reader r) { return r.get_sfixed64(); });
} else if (reader.has_wire_type(protozero::pbf_wire_type::fixed32)) {
// Try to decode this field as any of the types that can be encoded as fixed32.
try_field(reader, [](protozero::pbf_reader r) { return r.get_float(); });
try_field(reader, [](protozero::pbf_reader r) { return r.get_fixed32(); });
try_field(reader, [](protozero::pbf_reader r) { return r.get_sfixed32(); });
}
reader.skip();
}
} catch (const protozero::exception&) {
// no-op. This is probably not a valid message.
}
return 0;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
try_message(protozero::pbf_reader{reinterpret_cast<const char*>(data), size});
return 0;
}
|