xref: /aosp_15_r20/external/cronet/testing/libfuzzer/libprotobuf-mutator.md (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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