pidgin/pidgin

Add fuzzing support for some libpurple features
release-2.x.y
2021-06-24, Jordy Zomer <>
97c51d97d375
Add fuzzing support for some libpurple features

Testing Done:
Hi!

I built and tested all of these fuzzers for libpurple.

You can build them by first building pidgin/libpurple with `--enable-fuzzing` then going into `libpurple/tests` and run `make check`. After that you can run these fuzzers. With a dictionary if you want :)

for example:
```bash
$ ./fuzz_markup_strip_html -dict=dictionaries/html.dict
Dictionary: 465 entries
INFO: Seed: 2274862685
INFO: Loaded 1 modules (3 inline 8-bit counters): 3 [0x5a4ec0, 0x5a4ec3),
INFO: Loaded 1 PC tables (3 PCs): 3 [0x568ee8,0x568f18),
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: A corpus is not provided, starting from an empty corpus
#2 INITED cov: 2 ft: 2 corp: 1/1b exec/s: 0 rss: 30Mb
#1048576 pulse cov: 2 ft: 2 corp: 1/1b lim: 4096 exec/s: 524288 rss: 789Mb
#2097152 pulse cov: 2 ft: 2 corp: 1/1b lim: 4096 exec/s: 524288 rss: 792Mb
```

Best Regards,

Jordy Zomer

Reviewed at https://reviews.imfreedom.org/r/760/
# Introduction and setup
Pidgin has fuzzing support for libpurple. Libfuzzer (https://llvm.org/docs/LibFuzzer.html) is used for this.
There are currently a few fuzzers mentioned in libpurple/tests/fuzz *.c. You can build the fuzzers by following the usual build process and adding `--enable-fuzzing` to `./configure`, for this you'll need to set CC to `clang`, once you've done this you can go to `libpurple/tests` and run `make check` this will build the fuzzers for you.
Example:
```bash
$ CC=clang ./configure --enable-fuzzing --disable-cyrus-sasl --disable-gtkui --disable-gstreamer --disable-vv --disable-idn --disable-meanwhile --disable-avahi --disable-libgadu --disable-dbus --disable-libsecret --disable-gnome-keyring --disable-kwallet --disable-plugin
# This will configure build system
# The next step would be actually building pidgin and it's libraries.
# -j $(nproc) is optional, this build it with all available cores
$ make -j $(nproc)
# Now pidgin is actually built, we can build the fuzzers
$ cd libpurple/tests
$ make check
# Now the fuzzers should be built and can be run
# The -dict= paramater can be used to define a dictionary to be used by fuzzing
# For fuzzing common formats like xml you could for example use the xml dict, this is optional
$ ./fuzz_xmlnode -dict=dictionaries/xml.dict
```
# Useful options
Because Libfuzzer is a sophisticated program, here are some handy options:
```
help -> Print help.
jobs -> Number of jobs to run. If jobs >= 1 we spawn this number of jobs in separate worker processes with stdout/stderr redirected to fuzz-JOB.log.
workers -> Number of simultaneous worker processes to run the jobs. If zero, "min(jobs,NumberOfCpuCores()/2)" is used.
max_len -> Maximum length of the test input. If 0, libFuzzer tries to guess a good value based on the corpus and reports it.
```
You can also show the help with:
`./fuzz_html_to_xhtml -help=1`
This will show you all the options you can give to your fuzzer.
In addition, if you're new to fuzzing with libfuzzer, https://github.com/google/fuzzing/blob/master/tutorial/libFuzzerTutorial.md is a fantastic place to start.
# Adding more fuzzers
Of course, having more fuzzers and covering more areas of the code used in libpurple is always a good thing. It's simple to incorporate a fuzzer into the current build system!
If you open the `Makefile.am` file in `libpurple/tests` you'll see a `fuzz_programs` variable, you have to add the name to your new fuzzing harness in there.
Example:
```
fuzz_programs=\
fuzz_html_to_xhtml \
fuzz_jabber_caps \
fuzz_jabber_id_new \
fuzz_markup_strip_html \
fuzz_mime \
fuzz_xmlnode \
fuzz_newfuzzer # This is the newly added fuzzer
```
We'll also need to define the sources, which we can do by copying and changing the lines from an existing fuzzer.
For example we have a `fuzz_xmlnode.c` fuzzer, these are the lines that define the sources and the flags:
```
fuzz_xmlnode_SOURCES=fuzz_xmlnode.c
fuzz_xmlnode_LDADD=$(check_libpurple_LDADD)
fuzz_xmlnode_CFLAGS=-fsanitize=fuzzer,address $(check_libpurple_CFLAGS)
```
We'll need to change the names of these to match the name of our new fuzzer and add any necessary flags:
```
fuzz_new_SOURCES=fuzz_new.c
fuzz_new_LDADD=$(check_libpurple_LDADD)
fuzz_new_CFLAGS=-fsanitize=fuzzer,address $(check_libpurple_CFLAGS)
```
Now you must include your harness in `fuzz_new.c`, an example of a new harness could be as follows:
```C
#include <glib.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <purple.h>
#include "../util.h"
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
char *malicious_input = g_new0(char, size + 1);
memcpy(malicious_input, data, size);
malicious_input[size] = '\0';
function_you_want_to_fuzz(malicious_input);
g_free(malicious_input);
return 0;
}
```
Make sure to include the relevant includes, and then run `./configure` again in the repository's root directory, after that run `make check` in `libpurple/tests` to create your new fuzzer. Then, by executing this binary, you can run it.