1*6777b538SAndroid Build Coastguard Worker# Getting Started with libprotobuf-mutator (LPM) in Chromium 2*6777b538SAndroid Build Coastguard Worker 3*6777b538SAndroid Build Coastguard Worker*** note 4*6777b538SAndroid Build Coastguard Worker**Note:** Writing grammar fuzzers with libprotobuf-mutator requires greater 5*6777b538SAndroid Build Coastguard Workereffort than writing fuzzers with libFuzzer alone. If you run into problems, send 6*6777b538SAndroid Build Coastguard Workeran email to [[email protected]] for help. 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker**Prerequisites:** Knowledge of [libFuzzer in Chromium] and basic understanding 9*6777b538SAndroid Build Coastguard Workerof [Protocol Buffers]. 10*6777b538SAndroid Build Coastguard Worker*** 11*6777b538SAndroid Build Coastguard Worker 12*6777b538SAndroid Build Coastguard WorkerThis document will walk you through: 13*6777b538SAndroid Build Coastguard Worker 14*6777b538SAndroid Build Coastguard Worker* An overview of libprotobuf-mutator and how it's used. 15*6777b538SAndroid Build Coastguard Worker* Writing and building your first fuzzer using libprotobuf-mutator. 16*6777b538SAndroid Build Coastguard Worker 17*6777b538SAndroid Build Coastguard Worker[TOC] 18*6777b538SAndroid Build Coastguard Worker 19*6777b538SAndroid Build Coastguard Worker## Overview of libprotobuf-mutator 20*6777b538SAndroid Build Coastguard Workerlibprotobuf-mutator is a package that allows libFuzzer’s mutation engine to 21*6777b538SAndroid Build Coastguard Workermanipulate protobufs. This allows libFuzzer's mutations to be more specific 22*6777b538SAndroid Build Coastguard Workerto the format it is fuzzing and less arbitrary. Below are some good use cases 23*6777b538SAndroid Build Coastguard Workerfor libprotobuf-mutator: 24*6777b538SAndroid Build Coastguard Worker 25*6777b538SAndroid Build Coastguard Worker* Fuzzing targets that accept Protocol Buffers as input. See the next section 26*6777b538SAndroid Build Coastguard Workerfor how to do this. 27*6777b538SAndroid Build Coastguard Worker* Fuzzing targets that accept input defined by a grammar. To do this you 28*6777b538SAndroid Build Coastguard Workermust write code that converts data from a protobuf-based format that represents 29*6777b538SAndroid Build Coastguard Workerthe grammar to a format the target accepts. url_parse_proto_fuzzer is a working 30*6777b538SAndroid Build Coastguard Workerexample of this and is commented extensively. Readers may wish to consult its 31*6777b538SAndroid Build Coastguard Workercode, which is located in `testing/libfuzzer/fuzzers/url_parse_proto_fuzzer.cc` 32*6777b538SAndroid Build Coastguard Workerand `testing/libfuzzer/proto/url.proto`. Its build configuration can be found 33*6777b538SAndroid Build Coastguard Workerin `testing/libfuzzer/fuzzers/BUILD.gn` and `testing/libfuzzer/proto/BUILD.gn`. 34*6777b538SAndroid Build Coastguard WorkerWe also provide a walkthrough on how to do this in the section after the next. 35*6777b538SAndroid Build Coastguard Worker* Fuzzing targets that accept more than one argument (such as data and flags). 36*6777b538SAndroid Build Coastguard WorkerIn this case, you can define each argument as its own field in your protobuf 37*6777b538SAndroid Build Coastguard Workerdefinition. 38*6777b538SAndroid Build Coastguard Worker 39*6777b538SAndroid Build Coastguard WorkerIn the next section, we discuss building a fuzzer that targets code that accepts 40*6777b538SAndroid Build Coastguard Workeran already existing protobuf definition. In the section after that, we discuss 41*6777b538SAndroid Build Coastguard Workerhow to write and build grammar-based fuzzers using libprotobuf-mutator. 42*6777b538SAndroid Build Coastguard WorkerInterested readers may also want to look at [this] example of a 43*6777b538SAndroid Build Coastguard Workerlibprotobuf-mutator fuzzer that is even more trivial than 44*6777b538SAndroid Build Coastguard Workerurl_parse_proto_fuzzer. 45*6777b538SAndroid Build Coastguard Worker 46*6777b538SAndroid Build Coastguard Worker## Write a fuzz target for code that accepts protobufs 47*6777b538SAndroid Build Coastguard Worker 48*6777b538SAndroid Build Coastguard WorkerThis is almost as easy as writing a standard libFuzzer-based fuzzer. You can 49*6777b538SAndroid Build Coastguard Workerlook at [lpm_test_fuzzer] for an example of a working example of this (don't 50*6777b538SAndroid Build Coastguard Workercopy the line adding "//testing/libfuzzer:no_clusterfuzz" to 51*6777b538SAndroid Build Coastguard Workeradditional_configs). Or you can follow this walkthrough: 52*6777b538SAndroid Build Coastguard Worker 53*6777b538SAndroid Build Coastguard WorkerStart by creating a fuzz target. This is what the .cc file will look like: 54*6777b538SAndroid Build Coastguard Worker 55*6777b538SAndroid Build Coastguard Worker```c++ 56*6777b538SAndroid Build Coastguard Worker// my_fuzzer.cc 57*6777b538SAndroid Build Coastguard Worker 58*6777b538SAndroid Build Coastguard Worker#include "testing/libfuzzer/proto/lpm_interface.h" 59*6777b538SAndroid Build Coastguard Worker 60*6777b538SAndroid Build Coastguard Worker// Assuming the .proto file is path/to/your/proto_file/my_proto.proto. 61*6777b538SAndroid Build Coastguard Worker#include "path/to/your/proto_file/my_proto.pb.h" 62*6777b538SAndroid Build Coastguard Worker 63*6777b538SAndroid Build Coastguard WorkerDEFINE_PROTO_FUZZER( 64*6777b538SAndroid Build Coastguard Worker const my_proto::MyProtoMessage& my_proto_message) { 65*6777b538SAndroid Build Coastguard Worker targeted_function(my_proto_message); 66*6777b538SAndroid Build Coastguard Worker} 67*6777b538SAndroid Build Coastguard Worker``` 68*6777b538SAndroid Build Coastguard Worker 69*6777b538SAndroid Build Coastguard WorkerThe BUILD.gn definition for this target will be very similar to regular 70*6777b538SAndroid Build Coastguard WorkerlibFuzzer-based fuzzer_test. However it will also have libprotobuf-mutator in 71*6777b538SAndroid Build Coastguard Workerits deps. This is an example of what it will look like: 72*6777b538SAndroid Build Coastguard Worker 73*6777b538SAndroid Build Coastguard Worker```python 74*6777b538SAndroid Build Coastguard Worker// You must wrap the target in "use_fuzzing_engine_with_lpm" since trying to compile the 75*6777b538SAndroid Build Coastguard Worker// target without a suitable fuzzing engine will fail (for reasons alluded to in the next 76*6777b538SAndroid Build Coastguard Worker// step), which the commit queue will try. 77*6777b538SAndroid Build Coastguard Workerif (use_fuzzing_engine_with_lpm) { 78*6777b538SAndroid Build Coastguard Worker fuzzer_test("my_fuzzer") { 79*6777b538SAndroid Build Coastguard Worker sources = [ "my_fuzzer.cc" ] 80*6777b538SAndroid Build Coastguard Worker deps = [ 81*6777b538SAndroid Build Coastguard Worker // The proto library defining the message accepted by 82*6777b538SAndroid Build Coastguard Worker // DEFINE_PROTO_FUZZER(). 83*6777b538SAndroid Build Coastguard Worker ":my_proto", 84*6777b538SAndroid Build Coastguard Worker 85*6777b538SAndroid Build Coastguard Worker "//third_party/libprotobuf-mutator", 86*6777b538SAndroid Build Coastguard Worker ... 87*6777b538SAndroid Build Coastguard Worker ] 88*6777b538SAndroid Build Coastguard Worker } 89*6777b538SAndroid Build Coastguard Worker} 90*6777b538SAndroid Build Coastguard Worker``` 91*6777b538SAndroid Build Coastguard Worker 92*6777b538SAndroid Build Coastguard WorkerThere's one more step however. Because Chromium doesn't want to ship to users 93*6777b538SAndroid Build Coastguard Workerthe full protobuf library, all `.proto` files in Chromium that are used in 94*6777b538SAndroid Build Coastguard Workerproduction contain this line: `option optimize_for = LITE_RUNTIME` But this 95*6777b538SAndroid Build Coastguard Workerline is incompatible with libprotobuf-mutator. Thus, we need to modify the 96*6777b538SAndroid Build Coastguard Worker`proto_library` build target so that builds when fuzzing are compatible with 97*6777b538SAndroid Build Coastguard Workerlibprotobuf-mutator. To do this, change your `proto_library` to 98*6777b538SAndroid Build Coastguard Worker`fuzzable_proto_library` (don't worry, this works just like `proto_library` when 99*6777b538SAndroid Build Coastguard Worker`use_fuzzing_engine_with_lpm` is `false`) like so: 100*6777b538SAndroid Build Coastguard Worker 101*6777b538SAndroid Build Coastguard Worker```python 102*6777b538SAndroid Build Coastguard Workerimport("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni") 103*6777b538SAndroid Build Coastguard Worker 104*6777b538SAndroid Build Coastguard Workerfuzzable_proto_library("my_proto") { 105*6777b538SAndroid Build Coastguard Worker ... 106*6777b538SAndroid Build Coastguard Worker} 107*6777b538SAndroid Build Coastguard Worker``` 108*6777b538SAndroid Build Coastguard Worker 109*6777b538SAndroid Build Coastguard WorkerAnd with that we have completed writing a libprotobuf-mutator fuzz target for 110*6777b538SAndroid Build Coastguard WorkerChromium code that accepts protobufs. 111*6777b538SAndroid Build Coastguard Worker 112*6777b538SAndroid Build Coastguard Worker 113*6777b538SAndroid Build Coastguard Worker## Write a grammar-based fuzzer with libprotobuf-mutator 114*6777b538SAndroid Build Coastguard Worker 115*6777b538SAndroid Build Coastguard WorkerOnce you have in mind the code you want to fuzz and the format it accepts, you 116*6777b538SAndroid Build Coastguard Workerare ready to start writing a libprotobuf-mutator fuzzer. Writing the fuzzer 117*6777b538SAndroid Build Coastguard Workerwill have three steps: 118*6777b538SAndroid Build Coastguard Worker 119*6777b538SAndroid Build Coastguard Worker* Define the fuzzed format (not required for protobuf formats, unless the 120*6777b538SAndroid Build Coastguard Workeroriginal definition is optimized for `LITE_RUNTIME`). 121*6777b538SAndroid Build Coastguard Worker* Write the fuzz target and conversion code (for non-protobuf formats). 122*6777b538SAndroid Build Coastguard Worker* Define the GN target 123*6777b538SAndroid Build Coastguard Worker 124*6777b538SAndroid Build Coastguard Worker### Define the Fuzzed Format 125*6777b538SAndroid Build Coastguard WorkerCreate a new .proto using `proto2` or `proto3` syntax and define a message that 126*6777b538SAndroid Build Coastguard Workeryou want libFuzzer to mutate. 127*6777b538SAndroid Build Coastguard Worker 128*6777b538SAndroid Build Coastguard Worker``` protocol-buffer 129*6777b538SAndroid Build Coastguard Workersyntax = "proto2"; 130*6777b538SAndroid Build Coastguard Worker 131*6777b538SAndroid Build Coastguard Workerpackage my_fuzzer; 132*6777b538SAndroid Build Coastguard Worker 133*6777b538SAndroid Build Coastguard Workermessage MyProtoFormat { 134*6777b538SAndroid Build Coastguard Worker // Define a format for libFuzzer to mutate here. 135*6777b538SAndroid Build Coastguard Worker} 136*6777b538SAndroid Build Coastguard Worker``` 137*6777b538SAndroid Build Coastguard Worker 138*6777b538SAndroid Build Coastguard WorkerSee `testing/libfuzzer/proto/url.proto` for an example of this in practice. 139*6777b538SAndroid Build Coastguard WorkerThat example has extensive comments on URL syntax and how that influenced 140*6777b538SAndroid Build Coastguard Workerthe definition of the Url message. 141*6777b538SAndroid Build Coastguard Worker 142*6777b538SAndroid Build Coastguard Worker### Write the Fuzz Target and Conversion Code 143*6777b538SAndroid Build Coastguard WorkerCreate a new .cc and write a `DEFINE_PROTO_FUZZER` function: 144*6777b538SAndroid Build Coastguard Worker 145*6777b538SAndroid Build Coastguard Worker```c++ 146*6777b538SAndroid Build Coastguard Worker// Needed since we use getenv(). 147*6777b538SAndroid Build Coastguard Worker#include <stdlib.h> 148*6777b538SAndroid Build Coastguard Worker 149*6777b538SAndroid Build Coastguard Worker// Needed since we use std::cout. 150*6777b538SAndroid Build Coastguard Worker#include <iostream> 151*6777b538SAndroid Build Coastguard Worker 152*6777b538SAndroid Build Coastguard Worker#include "testing/libfuzzer/proto/lpm_interface.h" 153*6777b538SAndroid Build Coastguard Worker 154*6777b538SAndroid Build Coastguard Worker// Assuming the .proto file is path/to/your/proto_file/my_format.proto. 155*6777b538SAndroid Build Coastguard Worker#include "path/to/your/proto_file/my_format.pb.h" 156*6777b538SAndroid Build Coastguard Worker 157*6777b538SAndroid Build Coastguard Worker// Put your conversion code here (if needed) and then pass the result to 158*6777b538SAndroid Build Coastguard Worker// your fuzzing code (or just pass "my_format", if your target accepts 159*6777b538SAndroid Build Coastguard Worker// protobufs). 160*6777b538SAndroid Build Coastguard Worker 161*6777b538SAndroid Build Coastguard WorkerDEFINE_PROTO_FUZZER(const my_fuzzer::MyFormat& my_proto_format) { 162*6777b538SAndroid Build Coastguard Worker // Convert your protobuf to whatever format your targeted code accepts 163*6777b538SAndroid Build Coastguard Worker // if it doesn't accept protobufs. 164*6777b538SAndroid Build Coastguard Worker std::string native_input = convert_to_native_input(my_proto_format); 165*6777b538SAndroid Build Coastguard Worker 166*6777b538SAndroid Build Coastguard Worker // You should provide a way to easily retrieve the native input for 167*6777b538SAndroid Build Coastguard Worker // a given protobuf input. This is useful for debugging and for seeing 168*6777b538SAndroid Build Coastguard Worker // the inputs that cause targeted_function to crash (which is the reason we 169*6777b538SAndroid Build Coastguard Worker // are here!). Note how this is done before targeted_function is called 170*6777b538SAndroid Build Coastguard Worker // since we can't print after the program has crashed. 171*6777b538SAndroid Build Coastguard Worker if (getenv("LPM_DUMP_NATIVE_INPUT")) 172*6777b538SAndroid Build Coastguard Worker std::cout << native_input << std::endl; 173*6777b538SAndroid Build Coastguard Worker 174*6777b538SAndroid Build Coastguard Worker // Now test your targeted code using the converted protobuf input. 175*6777b538SAndroid Build Coastguard Worker targeted_function(native_input); 176*6777b538SAndroid Build Coastguard Worker} 177*6777b538SAndroid Build Coastguard Worker``` 178*6777b538SAndroid Build Coastguard Worker 179*6777b538SAndroid Build Coastguard WorkerThis is very similar to the same step in writing a standard libFuzzer fuzzer. 180*6777b538SAndroid Build Coastguard WorkerThe only real differences are accepting protobufs rather than raw data and 181*6777b538SAndroid Build Coastguard Workerconverting them to the desired format. Conversion code can't really be 182*6777b538SAndroid Build Coastguard Workerexplored in this guide since it is format-specific. However, a good example 183*6777b538SAndroid Build Coastguard Workerof conversion code (and a fuzz target) can be found in 184*6777b538SAndroid Build Coastguard Worker`testing/libfuzzer/fuzzers/url_parse_proto_fuzzer.cc`. That example 185*6777b538SAndroid Build Coastguard Workerthoroughly documents how it converts the Url protobuf message into a real URL 186*6777b538SAndroid Build Coastguard Workerstring. A good convention is printing the native input when the 187*6777b538SAndroid Build Coastguard Worker`LPM_DUMP_NATIVE_INPUT` env variable is set. This will make it easy to 188*6777b538SAndroid Build Coastguard Workerretrieve the actual input that causes the code to crash instead of the 189*6777b538SAndroid Build Coastguard Workerprotobuf version of it (e.g. you can get the URL string that causes an input 190*6777b538SAndroid Build Coastguard Workerto crash rather than a protobuf). Since it is only a convention it is 191*6777b538SAndroid Build Coastguard Workerstrongly recommended even though it isn't necessary. You don't need to do 192*6777b538SAndroid Build Coastguard Workerthis if the native input of targeted_function is protobufs. Beware that 193*6777b538SAndroid Build Coastguard Workerprinting a newline can make the output invalid for some formats. In this case 194*6777b538SAndroid Build Coastguard Workeryou should use `fflush(0)` since otherwise the program may crash before 195*6777b538SAndroid Build Coastguard Workernative_input is actually printed. 196*6777b538SAndroid Build Coastguard Worker 197*6777b538SAndroid Build Coastguard Worker 198*6777b538SAndroid Build Coastguard Worker### Define the GN Target 199*6777b538SAndroid Build Coastguard WorkerDefine a fuzzer_test target and include your protobuf definition and 200*6777b538SAndroid Build Coastguard Workerlibprotobuf-mutator as dependencies. 201*6777b538SAndroid Build Coastguard Worker 202*6777b538SAndroid Build Coastguard Worker```python 203*6777b538SAndroid Build Coastguard Workerimport("//testing/libfuzzer/fuzzer_test.gni") 204*6777b538SAndroid Build Coastguard Workerimport("//third_party/protobuf/proto_library.gni") 205*6777b538SAndroid Build Coastguard Worker 206*6777b538SAndroid Build Coastguard Workerfuzzer_test("my_fuzzer") { 207*6777b538SAndroid Build Coastguard Worker sources = [ "my_fuzzer.cc" ] 208*6777b538SAndroid Build Coastguard Worker deps = [ 209*6777b538SAndroid Build Coastguard Worker ":my_format_proto", 210*6777b538SAndroid Build Coastguard Worker "//third_party/libprotobuf-mutator" 211*6777b538SAndroid Build Coastguard Worker ... 212*6777b538SAndroid Build Coastguard Worker ] 213*6777b538SAndroid Build Coastguard Worker} 214*6777b538SAndroid Build Coastguard Worker 215*6777b538SAndroid Build Coastguard Workerproto_library("my_format_proto") { 216*6777b538SAndroid Build Coastguard Worker sources = [ "my_format.proto" ] 217*6777b538SAndroid Build Coastguard Worker} 218*6777b538SAndroid Build Coastguard Worker``` 219*6777b538SAndroid Build Coastguard Worker 220*6777b538SAndroid Build Coastguard WorkerSee `testing/libfuzzer/fuzzers/BUILD.gn` for an example of this in practice. 221*6777b538SAndroid Build Coastguard Worker 222*6777b538SAndroid Build Coastguard Worker### Tips For Grammar Based Fuzzers 223*6777b538SAndroid Build Coastguard Worker* If you have messages that are defined recursively (eg: message `Foo` has a 224*6777b538SAndroid Build Coastguard Workerfield of type `Foo`), make sure to bound recursive calls to code converting 225*6777b538SAndroid Build Coastguard Workeryour message into native input. Otherwise you will (probably) end up with an 226*6777b538SAndroid Build Coastguard Workerout of memory error. The code coverage benefits of allowing unlimited 227*6777b538SAndroid Build Coastguard Workerrecursion in a message are probably fairly low for most targets anyway. 228*6777b538SAndroid Build Coastguard Worker 229*6777b538SAndroid Build Coastguard Worker* Remember that proto definitions can be changed in ways that are backwards 230*6777b538SAndroid Build Coastguard Workercompatible (such as adding explicit values to an `enum`). This means that you 231*6777b538SAndroid Build Coastguard Workercan make changes to your definitions while preserving the usefulness of your 232*6777b538SAndroid Build Coastguard Workercorpus. In general adding fields will be backwards compatible but removing them 233*6777b538SAndroid Build Coastguard Worker(particulary if they are `required`) is not. 234*6777b538SAndroid Build Coastguard Worker 235*6777b538SAndroid Build Coastguard Worker* Make sure you understand the meaning of the different protobuf modifiers such 236*6777b538SAndroid Build Coastguard Workeras `oneof` and `repeated` as they can be counter-intuitive. `oneof` means "At 237*6777b538SAndroid Build Coastguard Workermost one of" while `repeated` means "At least zero". You can hack around these 238*6777b538SAndroid Build Coastguard Workermeanings if you need "at least one of" or "exactly one of" something. For 239*6777b538SAndroid Build Coastguard Workerexample, this is the proto code for exactly one of: `MessageA` or `MessageB` or 240*6777b538SAndroid Build Coastguard Worker`MessageC`: 241*6777b538SAndroid Build Coastguard Worker 242*6777b538SAndroid Build Coastguard Worker```protocol-buffer 243*6777b538SAndroid Build Coastguard Workermessage MyFormat { 244*6777b538SAndroid Build Coastguard Worker oneof a_or_b { 245*6777b538SAndroid Build Coastguard Worker MessageA message_a = 1; 246*6777b538SAndroid Build Coastguard Worker MessageB message_b = 2; 247*6777b538SAndroid Build Coastguard Worker } 248*6777b538SAndroid Build Coastguard Worker required MessageC message_c = 3; 249*6777b538SAndroid Build Coastguard Worker} 250*6777b538SAndroid Build Coastguard Worker``` 251*6777b538SAndroid Build Coastguard Worker 252*6777b538SAndroid Build Coastguard WorkerAnd here is the C++ code that converts it. 253*6777b538SAndroid Build Coastguard Worker 254*6777b538SAndroid Build Coastguard Worker```c++ 255*6777b538SAndroid Build Coastguard Workerstd::string Convert(const MyFormat& my_format) { 256*6777b538SAndroid Build Coastguard Worker if (my_format.has_message_a()) 257*6777b538SAndroid Build Coastguard Worker return ConvertMessageA(my_format.message_a()); 258*6777b538SAndroid Build Coastguard Worker else if (my_format.has_message_b()) 259*6777b538SAndroid Build Coastguard Worker return ConvertMessageB(my_format.message_b()); 260*6777b538SAndroid Build Coastguard Worker else // Fall through to the default case, message_c. 261*6777b538SAndroid Build Coastguard Worker return ConvertMessageC(my_format.message_c()); 262*6777b538SAndroid Build Coastguard Worker} 263*6777b538SAndroid Build Coastguard Worker``` 264*6777b538SAndroid Build Coastguard Worker 265*6777b538SAndroid Build Coastguard Worker* libprotobuf-mutator supports both proto2 and proto3 syntax. Be aware though 266*6777b538SAndroid Build Coastguard Workerthat it handles strings differently in each because of differences in the way 267*6777b538SAndroid Build Coastguard Workerthe proto library handles strings in each syntax (in short, proto3 strings must 268*6777b538SAndroid Build Coastguard Workeractually be UTF-8 while in proto2 they do not). See [here] for more details. 269*6777b538SAndroid Build Coastguard Worker 270*6777b538SAndroid Build Coastguard Worker## Write a fuzz target for code that accepts multiple inputs 271*6777b538SAndroid Build Coastguard WorkerLPM makes it straightforward to write a fuzzer for code that needs multiple 272*6777b538SAndroid Build Coastguard Workerinputs. The steps for doing this are similar to those of writing a grammar based 273*6777b538SAndroid Build Coastguard Workerfuzzer, except in this case the grammar is very simple. Thus instructions for 274*6777b538SAndroid Build Coastguard Workerthis use case are given below. 275*6777b538SAndroid Build Coastguard WorkerStart by creating the proto file which will define the inputs you want: 276*6777b538SAndroid Build Coastguard Worker 277*6777b538SAndroid Build Coastguard Worker```protocol-buffer 278*6777b538SAndroid Build Coastguard Worker// my_fuzzer_input.proto 279*6777b538SAndroid Build Coastguard Worker 280*6777b538SAndroid Build Coastguard Workersyntax = "proto2"; 281*6777b538SAndroid Build Coastguard Worker 282*6777b538SAndroid Build Coastguard Workerpackage my_fuzzer; 283*6777b538SAndroid Build Coastguard Worker 284*6777b538SAndroid Build Coastguard Workermessage FuzzerInput { 285*6777b538SAndroid Build Coastguard Worker required bool arg1 = 1; 286*6777b538SAndroid Build Coastguard Worker required string arg2 = 2; 287*6777b538SAndroid Build Coastguard Worker optional int arg3 = 1; 288*6777b538SAndroid Build Coastguard Worker} 289*6777b538SAndroid Build Coastguard Worker 290*6777b538SAndroid Build Coastguard Worker``` 291*6777b538SAndroid Build Coastguard Worker 292*6777b538SAndroid Build Coastguard WorkerIn this example, the function we are fuzzing requires a `bool` and a `string` 293*6777b538SAndroid Build Coastguard Workerand takes an `int` as an optional argument. Let's define our fuzzer harness: 294*6777b538SAndroid Build Coastguard Worker 295*6777b538SAndroid Build Coastguard Worker```c++ 296*6777b538SAndroid Build Coastguard Worker// my_fuzzer.cc 297*6777b538SAndroid Build Coastguard Worker 298*6777b538SAndroid Build Coastguard Worker#include "testing/libfuzzer/proto/lpm_interface.h" 299*6777b538SAndroid Build Coastguard Worker 300*6777b538SAndroid Build Coastguard Worker// Assuming the .proto file is path/to/your/proto_file/my_fuzzer_input.proto. 301*6777b538SAndroid Build Coastguard Worker#include "path/to/your/proto_file/my_proto.pb.h" 302*6777b538SAndroid Build Coastguard Worker 303*6777b538SAndroid Build Coastguard WorkerDEFINE_PROTO_FUZZER( 304*6777b538SAndroid Build Coastguard Worker const my_proto::FuzzerInput& fuzzer_input) { 305*6777b538SAndroid Build Coastguard Worker if (fuzzer_input.has_arg3()) 306*6777b538SAndroid Build Coastguard Worker targeted_function_1(fuzzer_input.arg1(), fuzzer_input.arg2(), fuzzer_input.arg3()); 307*6777b538SAndroid Build Coastguard Worker else 308*6777b538SAndroid Build Coastguard Worker targeted_function_2(fuzzer_input.arg1(), fuzzer_input.arg2()); 309*6777b538SAndroid Build Coastguard Worker} 310*6777b538SAndroid Build Coastguard Worker``` 311*6777b538SAndroid Build Coastguard Worker 312*6777b538SAndroid Build Coastguard WorkerThen you must define build targets for your fuzzer harness and proto format in 313*6777b538SAndroid Build Coastguard WorkerGN, like so: 314*6777b538SAndroid Build Coastguard Worker```python 315*6777b538SAndroid Build Coastguard Workerimport("//testing/libfuzzer/fuzzer_test.gni") 316*6777b538SAndroid Build Coastguard Workerimport("//third_party/protobuf/proto_library.gni") 317*6777b538SAndroid Build Coastguard Worker 318*6777b538SAndroid Build Coastguard Workerfuzzer_test("my_fuzzer") { 319*6777b538SAndroid Build Coastguard Worker sources = [ "my_fuzzer.cc" ] 320*6777b538SAndroid Build Coastguard Worker deps = [ 321*6777b538SAndroid Build Coastguard Worker ":my_fuzzer_input", 322*6777b538SAndroid Build Coastguard Worker "//third_party/libprotobuf-mutator" 323*6777b538SAndroid Build Coastguard Worker ... 324*6777b538SAndroid Build Coastguard Worker ] 325*6777b538SAndroid Build Coastguard Worker} 326*6777b538SAndroid Build Coastguard Worker 327*6777b538SAndroid Build Coastguard Workerproto_library("my_fuzzer_input") { 328*6777b538SAndroid Build Coastguard Worker sources = [ "my_fuzzer_input.proto" ] 329*6777b538SAndroid Build Coastguard Worker} 330*6777b538SAndroid Build Coastguard Worker``` 331*6777b538SAndroid Build Coastguard Worker 332*6777b538SAndroid Build Coastguard Worker### Tips for fuzz targets that accept multiple inputs 333*6777b538SAndroid Build Coastguard WorkerProtobuf has a field rule `repeated` that is useful when a fuzzer needs to 334*6777b538SAndroid Build Coastguard Workeraccept a non-fixed number of inputs (see [mojo_parse_messages_proto_fuzzer], 335*6777b538SAndroid Build Coastguard Workerwhich accepts an unbounded number of mojo messages as an example). 336*6777b538SAndroid Build Coastguard WorkerProtobuf version 2 also has `optional` and `required` field rules that some may 337*6777b538SAndroid Build Coastguard Workerfind useful. 338*6777b538SAndroid Build Coastguard Worker 339*6777b538SAndroid Build Coastguard Worker 340*6777b538SAndroid Build Coastguard Worker## Wrapping Up 341*6777b538SAndroid Build Coastguard WorkerOnce you have written a fuzzer with libprotobuf-mutator, building and running 342*6777b538SAndroid Build Coastguard Workerit is pretty much the same as if the fuzzer were a [standard libFuzzer-based 343*6777b538SAndroid Build Coastguard Workerfuzzer] (with minor exceptions, like your seed corpus must be in protobuf 344*6777b538SAndroid Build Coastguard Workerformat). 345*6777b538SAndroid Build Coastguard Worker 346*6777b538SAndroid Build Coastguard Worker## General Tips 347*6777b538SAndroid Build Coastguard Worker* Check out some of the [existing proto fuzzers]. Not only will they be helpful 348*6777b538SAndroid Build Coastguard Workerexamples, it is possible that format you want to fuzz is already defined or 349*6777b538SAndroid Build Coastguard Workerpartially defined by an existing proto definition (if you are writing a grammar 350*6777b538SAndroid Build Coastguard Workerfuzzer). 351*6777b538SAndroid Build Coastguard Worker 352*6777b538SAndroid Build Coastguard Worker* `DEFINE_BINARY_PROTO_FUZZER` can be used instead of `DEFINE_PROTO_FUZZER` (or 353*6777b538SAndroid Build Coastguard Worker `DEFINE_TEXT_PROTO_FUZZER`) to use protobuf's binary format for the corpus. 354*6777b538SAndroid Build Coastguard Worker This will make it hard/impossible to modify the corpus manually (i.e. when not 355*6777b538SAndroid Build Coastguard Worker fuzzing). However, protobuf's text format (and by extension 356*6777b538SAndroid Build Coastguard Worker `DEFINE_PROTO_FUZZER`) is believed by some to come with a performance penalty 357*6777b538SAndroid Build Coastguard Worker compared to the binary format. We've never seen a case where this penalty 358*6777b538SAndroid Build Coastguard Worker was important, but if profiling reveals that protobuf deserialization is the 359*6777b538SAndroid Build Coastguard Worker bottleneck in your fuzzer, you may want to consider using the binary format. 360*6777b538SAndroid Build Coastguard Worker This will probably not be the case. 361*6777b538SAndroid Build Coastguard Worker 362*6777b538SAndroid Build Coastguard Worker[libfuzzer in Chromium]: getting_started.md 363*6777b538SAndroid Build Coastguard Worker[Protocol Buffers]: https://developers.google.com/protocol-buffers/docs/cpptutorial 364*6777b538SAndroid Build Coastguard Worker[[email protected]]: mailto:[email protected] 365*6777b538SAndroid Build Coastguard Worker[this]: https://github.com/google/libprotobuf-mutator/tree/master/examples/libfuzzer/libfuzzer_example.cc 366*6777b538SAndroid Build Coastguard Worker[existing proto fuzzers]: https://cs.chromium.org/search/?q=DEFINE_(BINARY_%7CTEXT_)?PROTO_FUZZER+-file:src/third_party/libprotobuf-mutator/src/src/libfuzzer/libfuzzer_macro.h+lang:cpp&sq=package:chromium&type=cs 367*6777b538SAndroid Build Coastguard Worker[here]: https://github.com/google/libprotobuf-mutator/blob/master/README.md#utf-8-strings 368*6777b538SAndroid Build Coastguard Worker[lpm_test_fuzzer]: https://cs.chromium.org/#search&q=lpm_test_fuzzer+file:%5Esrc/third_party/libprotobuf-mutator/BUILD.gn 369*6777b538SAndroid Build Coastguard Worker[mojo_parse_messages_proto_fuzzer]: https://cs.chromium.org/chromium/src/mojo/public/tools/fuzzers/mojo_parse_message_proto_fuzzer.cc?l=25 370*6777b538SAndroid Build Coastguard Worker[standard libFuzzer-based fuzzer]:getting_started_with_libfuzzer.md 371