diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -61,6 +61,7 @@
 libpurple/dbus-types.h
 libpurple/example/nullclient
 libpurple/data/gconf/purple.schemas$
+libpurple/fuzzers/fuzz_.*
 libpurple/marshallers.[ch]
 libpurple/plugins/dbus-example-bindings.c
 libpurple/plugins/perl/common/Makefile.PL$
@@ -74,6 +75,7 @@
 libpurple/purple.h$
 libpurple/tests/check_libpurple
 libpurple/tests/libpurple..
+libpurple/tests/test-suite\.log
 libpurple/version.h$
 libpurple/win32/libpurplerc.rc$
 libtool
diff --git a/COPYRIGHT b/COPYRIGHT
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -655,4 +655,5 @@
 Tom Zickel
 Marco Ziech
 Piotr Zielinski
+Jordy Zomer
 Jeroen Zwartepoorte
diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -15,8 +15,10 @@
 	  Kramlich)
 
 	libpurple:
-	* added support for the no_proxy environment variable. (PIDGIN-17518)
+	* Added support for the no_proxy environment variable. (PIDGIN-17518)
 	  (RR #667) (Alynx Zhou and Gary Kramlich)
+	* Added infrastructure for fuzzing as well as some initial fuzzers.
+	  (RR #760) (Jordy Zomer)
 
 	XMPP:
 	* Enable session management after binding a resource. (PIDGIN-17520) (RR
diff --git a/FUZZING b/FUZZING
--- a/FUZZING
+++ b/FUZZING
@@ -1,84 +1,98 @@
 # 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.
+Pidgin has fuzzing support for libpurple via
+[Libfuzzer](https://llvm.org/docs/LibFuzzer.html). If you're new to fuzzing with
+libfuzzer, there is a fantastic tutorial available
+[here](https://github.com/google/fuzzing/blob/master/tutorial/libFuzzerTutorial.md).
+
+The fuzzers reside in libpurples/fuzzers. To build them, you'll need to specify
+`clang` as your C compiler as well as pass `--enable-fuzzing` to `./configure`.
+Once this is done you can `cd libpurple/fuzzers` and run `make check` to build
+the fuzzers.
 
 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
+Now that the build system has been configured, you need to build everything.
+You can do this with the following command. Note that the `-j $(nproc)` is
+tells make to build with all available cores and is recommended but optional.
 
+```bash
 $ make -j $(nproc)
+```
 
-# Now pidgin is actually built, we can build the fuzzers
+Now that everything needed for the fuzzers is build we can build the fuzzers.
 
-$ cd libpurple/tests
+```bash
+$ cd libpurple/fuzzers
 $ 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
+Now that the fuzzers are built, you can run them by directly. There is also an
+optional `-dict` paramter that can be used to specify a dictionary to be used
+during the process.
 
-$ ./fuzz_xmlnode -dict=dictionaries/xml.dict 
-``` 
+```bash
+$ ./fuzz_xmlnode -dict=dictionaries/xml.dict
+```
 
 # Useful options
 
-Because Libfuzzer is a sophisticated program, here are some handy options:
+Because Libfuzzer is a sophisticated program, here are some handy options that
+are available in all fuzzers.
 
-```
-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.
+ * **-help=1** Print help.
+ * **-jobs=1** Number of jobs to run. If jobs >= 1 this will spawn that many jobs in separate worker processes with stdout/stderr redirected to fuzz-JOB.log.
+ * **-workers=0** Number of simultaneous worker processes to run the jobs. If zero, `min(jobs,NumberOfCpuCores()/2)` is used.
+ * **-max_len=0** Maximum length of the test input. If 0, libFuzzer tries to guess a good value based on the corpus and reports it.
 
 # 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.
+Of course, having more fuzzers and covering more areas of the code base 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/fuzzers` you'll see a
+`check_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_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.
+You'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: 
+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:
+You'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)
+fuzz_new_LDADD=$(common_LDADD)
+fuzz_new_CFLAGS=-fsanitize=fuzzer,address $(common_CFLAGS)
 ```
 
-Now you must include your harness in `fuzz_new.c`, an example of a new harness could be as follows:
+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>
@@ -92,7 +106,7 @@
 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);
+        gchar *malicious_input = g_new0(char, size + 1);
 
         memcpy(malicious_input, data, size);
         malicious_input[size] = '\0';
@@ -105,4 +119,8 @@
 }
 ```
 
-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.
+Make sure to include the relevant headers and then run `make`. This will force
+and update of the build system for the new target and build all of the default
+targets. After that run `make check` in `libpurple/fuzzers` to build your new
+fuzzer and if everything built fine you can now run it!
+
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -2586,6 +2586,7 @@
 		   libpurple/data/purple-2-uninstalled.pc
 		   libpurple/ciphers/Makefile
 		   libpurple/example/Makefile
+		   libpurple/fuzzers/Makefile
 		   libpurple/plugins/Makefile
 		   libpurple/plugins/mono/Makefile
 		   libpurple/plugins/mono/api/Makefile
diff --git a/libpurple/Makefile.am b/libpurple/Makefile.am
--- a/libpurple/Makefile.am
+++ b/libpurple/Makefile.am
@@ -29,7 +29,7 @@
 GCONF_DIR=data/gconf
 endif
 
-SUBDIRS = $(GCONF_DIR) plugins protocols ciphers . tests example
+SUBDIRS = $(GCONF_DIR) plugins protocols ciphers . fuzzers tests example
 
 purple_coresources = \
 	account.c \
diff --git a/libpurple/fuzzers/Makefile.am b/libpurple/fuzzers/Makefile.am
new file mode 100644
--- /dev/null
+++ b/libpurple/fuzzers/Makefile.am
@@ -0,0 +1,47 @@
+if FUZZ
+check_PROGRAMS=\
+	fuzz_html_to_xhtml \
+	fuzz_jabber_caps \
+	fuzz_jabber_id_new \
+	fuzz_markup_strip_html \
+	fuzz_mime \
+	fuzz_xmlnode
+
+common_CFLAGS=\
+	$(GLIB_CFLAGS) \
+	$(DEBUG_CFLAGS) \
+	$(LIBXML_CFLAGS) \
+	-I.. \
+	-I$(top_srcdir)/libpurple \
+	-DBUILDDIR=\"$(top_builddir)\"
+
+common_LDADD=\
+	$(top_builddir)/libpurple/protocols/jabber/libjabber.la \
+	$(top_builddir)/libpurple/libpurple.la \
+	$(GLIB_LIBS)
+
+fuzz_xmlnode_SOURCES=fuzz_xmlnode.c
+fuzz_xmlnode_LDADD=$(common_LDADD)
+fuzz_xmlnode_CFLAGS=-fsanitize=fuzzer,address $(common_CFLAGS)
+
+fuzz_jabber_id_new_SOURCES=fuzz_jabber_id_new.c
+fuzz_jabber_id_new_LDADD=$(common_LDADD)
+fuzz_jabber_id_new_CFLAGS=-fsanitize=fuzzer,address $(common_CFLAGS)
+
+fuzz_jabber_caps_SOURCES=fuzz_jabber_caps.c
+fuzz_jabber_caps_LDADD=$(common_LDADD)
+fuzz_jabber_caps_CFLAGS=-fsanitize=fuzzer,address $(common_CFLAGS)
+
+fuzz_mime_SOURCES=fuzz_mime.c
+fuzz_mime_LDADD=$(common_LDADD)
+fuzz_mime_CFLAGS=-fsanitize=fuzzer,address $(common_CFLAGS)
+
+fuzz_html_to_xhtml_SOURCES=fuzz_html_to_xhtml.c
+fuzz_html_to_xhtml_LDADD=$(common_LDADD)
+fuzz_html_to_xhtml_CFLAGS=-fsanitize=fuzzer,address $(common_CFLAGS)
+
+fuzz_markup_strip_html_SOURCES=fuzz_markup_strip_html.c
+fuzz_markup_strip_html_LDADD=$(common_LDADD)
+fuzz_markup_strip_html_CFLAGS=-fsanitize=fuzzer,address $(common_CFLAGS)
+
+endif
diff --git a/libpurple/tests/Makefile.am b/libpurple/tests/Makefile.am
--- a/libpurple/tests/Makefile.am
+++ b/libpurple/tests/Makefile.am
@@ -7,18 +7,6 @@
 
 check_PROGRAMS=check_libpurple
 
-if FUZZ
-fuzz_programs=\
-	fuzz_html_to_xhtml \
-	fuzz_jabber_caps \
-	fuzz_jabber_id_new \
-	fuzz_markup_strip_html \
-	fuzz_mime \
-	fuzz_xmlnode
-check_PROGRAMS+=$(fuzz_programs)
-endif
-
-
 check_libpurple_SOURCES=\
         check_libpurple.c \
 	    tests.h \
@@ -46,31 +34,4 @@
         @CHECK_LIBS@ \
 		$(GLIB_LIBS)
 
-
-if FUZZ
-fuzz_xmlnode_SOURCES=fuzz_xmlnode.c
-fuzz_xmlnode_LDADD=$(check_libpurple_LDADD)
-fuzz_xmlnode_CFLAGS=-fsanitize=fuzzer,address $(check_libpurple_CFLAGS)
-
-fuzz_jabber_id_new_SOURCES=fuzz_jabber_id_new.c
-fuzz_jabber_id_new_LDADD=$(check_libpurple_LDADD)
-fuzz_jabber_id_new_CFLAGS=-fsanitize=fuzzer,address $(check_libpurple_CFLAGS)
-
-fuzz_jabber_caps_SOURCES=fuzz_jabber_caps.c
-fuzz_jabber_caps_LDADD=$(check_libpurple_LDADD)
-fuzz_jabber_caps_CFLAGS=-fsanitize=fuzzer,address $(check_libpurple_CFLAGS)
-
-fuzz_mime_SOURCES=fuzz_mime.c
-fuzz_mime_LDADD=$(check_libpurple_LDADD)
-fuzz_mime_CFLAGS=-fsanitize=fuzzer,address $(check_libpurple_CFLAGS)
-
-fuzz_html_to_xhtml_SOURCES=fuzz_html_to_xhtml.c
-fuzz_html_to_xhtml_LDADD=$(check_libpurple_LDADD)
-fuzz_html_to_xhtml_CFLAGS=-fsanitize=fuzzer,address $(check_libpurple_CFLAGS)
-
-fuzz_markup_strip_html_SOURCES=fuzz_markup_strip_html.c
-fuzz_markup_strip_html_LDADD=$(check_libpurple_LDADD)
-fuzz_markup_strip_html_CFLAGS=-fsanitize=fuzzer,address $(check_libpurple_CFLAGS)
 endif
-
-endif
diff --git a/libpurple/tests/dictionaries/html.dict b/libpurple/fuzzers/dictionaries/html.dict
rename from libpurple/tests/dictionaries/html.dict
rename to libpurple/fuzzers/dictionaries/html.dict
diff --git a/libpurple/tests/dictionaries/xml.dict b/libpurple/fuzzers/dictionaries/xml.dict
rename from libpurple/tests/dictionaries/xml.dict
rename to libpurple/fuzzers/dictionaries/xml.dict
diff --git a/libpurple/tests/fuzz_html_to_xhtml.c b/libpurple/fuzzers/fuzz_html_to_xhtml.c
rename from libpurple/tests/fuzz_html_to_xhtml.c
rename to libpurple/fuzzers/fuzz_html_to_xhtml.c
--- a/libpurple/tests/fuzz_html_to_xhtml.c
+++ b/libpurple/fuzzers/fuzz_html_to_xhtml.c
@@ -30,14 +30,14 @@
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
 
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-	char *malicious_html = g_new0(char, size + 1);
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+	gchar *xhtml = NULL, *plaintext = NULL;
+	gchar *malicious_html = g_new0(gchar, size + 1);
 
 	memcpy(malicious_html, data, size);
 	malicious_html[size] = '\0';
 
-	gchar *xhtml = NULL, *plaintext = NULL;
-
 	purple_markup_html_to_xhtml(malicious_html, &xhtml, &plaintext);
 
 	g_free(xhtml);
@@ -47,3 +47,4 @@
 
 	return 0;
 }
+
diff --git a/libpurple/tests/fuzz_jabber_caps.c b/libpurple/fuzzers/fuzz_jabber_caps.c
rename from libpurple/tests/fuzz_jabber_caps.c
rename to libpurple/fuzzers/fuzz_jabber_caps.c
--- a/libpurple/tests/fuzz_jabber_caps.c
+++ b/libpurple/fuzzers/fuzz_jabber_caps.c
@@ -30,9 +30,10 @@
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
 
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-	char *malicious_xml = g_new0(char, size + 1);
-        xmlnode *query;
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+	gchar *malicious_xml = g_new0(gchar, size + 1);
+	xmlnode *query;
 
 	memcpy(malicious_xml, data, size);
 	malicious_xml[size] = '\0';
@@ -42,16 +43,16 @@
 		return 0;
 	}
 
-        query = xmlnode_new(malicious_xml);
+	query = xmlnode_new(malicious_xml);
 
 	if (query == NULL) {
 		g_free(malicious_xml);
 		return 0;
 	}
 
-        jabber_caps_parse_client_info(query);
+	jabber_caps_parse_client_info(query);
 
-        xmlnode_free(query);
+	xmlnode_free(query);
 
 	g_free(malicious_xml);
 
diff --git a/libpurple/tests/fuzz_jabber_id_new.c b/libpurple/fuzzers/fuzz_jabber_id_new.c
rename from libpurple/tests/fuzz_jabber_id_new.c
rename to libpurple/fuzzers/fuzz_jabber_id_new.c
--- a/libpurple/tests/fuzz_jabber_id_new.c
+++ b/libpurple/fuzzers/fuzz_jabber_id_new.c
@@ -33,12 +33,13 @@
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-	char *malicious_jid = g_new0(char, size + 1);
+	JabberID *jid = NULL;
+	gchar *malicious_jid = g_new0(gchar, size + 1);
 
 	memcpy(malicious_jid, data, size);
 	malicious_jid[size] = '\0';
 
-	JabberID *jid = jabber_id_new(malicious_jid);
+	jid = jabber_id_new(malicious_jid);
 
 	jabber_id_free(jid);
 
diff --git a/libpurple/tests/fuzz_markup_strip_html.c b/libpurple/fuzzers/fuzz_markup_strip_html.c
rename from libpurple/tests/fuzz_markup_strip_html.c
rename to libpurple/fuzzers/fuzz_markup_strip_html.c
--- a/libpurple/tests/fuzz_markup_strip_html.c
+++ b/libpurple/fuzzers/fuzz_markup_strip_html.c
@@ -30,9 +30,10 @@
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
 
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-	char *malicious_html = g_new0(char, size + 1);
-	char *stripped;
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+	gchar *malicious_html = g_new0(gchar, size + 1);
+	gchar *stripped;
 
 	memcpy(malicious_html, data, size);
 	malicious_html[size] = '\0';
diff --git a/libpurple/tests/fuzz_mime.c b/libpurple/fuzzers/fuzz_mime.c
rename from libpurple/tests/fuzz_mime.c
rename to libpurple/fuzzers/fuzz_mime.c
--- a/libpurple/tests/fuzz_mime.c
+++ b/libpurple/fuzzers/fuzz_mime.c
@@ -30,16 +30,17 @@
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
 
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-	char *malicious_mime = g_new0(char, size + 1);
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+	gchar *malicious_mime = g_new0(gchar, size + 1);
+	gchar *result = NULL;
 
 	memcpy(malicious_mime, data, size);
 	malicious_mime[size] = '\0';
 
-	gchar *result = purple_mime_decode_field(malicious_mime);
+	result = purple_mime_decode_field(malicious_mime);
 	g_free(result);
 
-
 	g_free(malicious_mime);
 
 	return 0;
diff --git a/libpurple/tests/fuzz_xmlnode.c b/libpurple/fuzzers/fuzz_xmlnode.c
rename from libpurple/tests/fuzz_xmlnode.c
rename to libpurple/fuzzers/fuzz_xmlnode.c
--- a/libpurple/tests/fuzz_xmlnode.c
+++ b/libpurple/fuzzers/fuzz_xmlnode.c
@@ -29,30 +29,31 @@
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
 
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-	char *malicious_xml = g_new0(char, size + 1);
-	char *str;
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+	gchar *malicious_xml = g_new0(gchar, size + 1);
+	gchar *str;
 	xmlnode *xml;
 
 	memcpy(malicious_xml, data, size);
 	malicious_xml[size] = '\0';
 
 	xml = xmlnode_from_str(malicious_xml, -1);
+	if(xml == NULL) {
+		g_free(malicious_xml);
 
-	if (xml == NULL) {
-		g_free(malicious_xml);
 		return 0;
 	}
 
 	str = xmlnode_to_str(xml, NULL);
-
-	if (str == NULL) {
+	if(str == NULL) {
 		xmlnode_free(xml);
 		free(malicious_xml);
+
 		return 0;
 	}
 
-	if (strcmp(malicious_xml, str) != 0) {
+	if(strcmp(malicious_xml, str) != 0) {
 		g_free(str);
 		xmlnode_free(xml);
 		free(malicious_xml);
