[poppler] 10 commits - cpp/tests glib/tests qt5/tests

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Nov 27 13:12:39 UTC 2020


 cpp/tests/CMakeLists.txt                |    6 
 cpp/tests/fuzzing/FuzzedDataProvider.h  |  409 ++++++++++++++++++++++++++++++++
 cpp/tests/fuzzing/doc_fuzzer.cc         |   49 +++
 cpp/tests/fuzzing/fuzzer_temp_file.h    |   82 ++++++
 cpp/tests/fuzzing/page_label_fuzzer.cc  |   41 +++
 cpp/tests/fuzzing/page_search_fuzzer.cc |   33 +-
 cpp/tests/fuzzing/pdf_file_fuzzer.cc    |   37 ++
 cpp/tests/fuzzing/pdf_fuzzer.cc         |   37 ++
 glib/tests/CMakeLists.txt               |   18 +
 glib/tests/fuzzing/annot_fuzzer.cc      |   77 ++++++
 glib/tests/fuzzing/doc_attr_fuzzer.cc   |   33 ++
 glib/tests/fuzzing/find_text_fuzzer.cc  |   39 +++
 glib/tests/fuzzing/fuzzer_temp_file.h   |   82 ++++++
 glib/tests/fuzzing/label_fuzzer.cc      |   38 ++
 glib/tests/fuzzing/pdf_draw_fuzzer.cc   |   74 +++++
 glib/tests/fuzzing/util_fuzzer.cc       |   24 +
 qt5/tests/CMakeLists.txt                |   16 +
 qt5/tests/fuzzing/qt_annot_fuzzer.cc    |   46 +++
 qt5/tests/fuzzing/qt_label_fuzzer.cc    |   29 ++
 qt5/tests/fuzzing/qt_pdf_fuzzer.cc      |   27 ++
 qt5/tests/fuzzing/qt_search_fuzzer.cc   |   28 ++
 qt5/tests/fuzzing/qt_textbox_fuzzer.cc  |   32 ++
 22 files changed, 1236 insertions(+), 21 deletions(-)

New commits:
commit 8ea1bf3c1069530171493a6b2dd49ac1f20120fc
Author: Ceyhun Alp <ceyhunalp at google.com>
Date:   Thu Nov 26 15:59:51 2020 +0000

    Replace malloc with calloc

diff --git a/glib/tests/fuzzing/doc_attr_fuzzer.cc b/glib/tests/fuzzing/doc_attr_fuzzer.cc
index 55924154..18d3811f 100644
--- a/glib/tests/fuzzing/doc_attr_fuzzer.cc
+++ b/glib/tests/fuzzing/doc_attr_fuzzer.cc
@@ -17,7 +17,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
         return 0;
     }
 
-    buf = (char *)malloc(size + 1);
+    buf = (char *)calloc(size + 1, sizeof(char));
     memcpy(buf, data, size);
     buf[size] = '\0';
 
diff --git a/glib/tests/fuzzing/find_text_fuzzer.cc b/glib/tests/fuzzing/find_text_fuzzer.cc
index 2e84ac78..e7d0ba90 100644
--- a/glib/tests/fuzzing/find_text_fuzzer.cc
+++ b/glib/tests/fuzzing/find_text_fuzzer.cc
@@ -22,7 +22,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
         return 0;
     }
 
-    buf = (char *)malloc(size + 1);
+    buf = (char *)calloc(size + 1, sizeof(char));
     memcpy(buf, data, size);
     buf[size] = '\0';
 
diff --git a/glib/tests/fuzzing/label_fuzzer.cc b/glib/tests/fuzzing/label_fuzzer.cc
index a1ecfbd6..825a57aa 100644
--- a/glib/tests/fuzzing/label_fuzzer.cc
+++ b/glib/tests/fuzzing/label_fuzzer.cc
@@ -22,7 +22,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
         return 0;
     }
 
-    buf = (char *)malloc(size + 1);
+    buf = (char *)calloc(size + 1, sizeof(char));
     memcpy(buf, data, size);
     buf[size] = '\0';
 
diff --git a/glib/tests/fuzzing/util_fuzzer.cc b/glib/tests/fuzzing/util_fuzzer.cc
index a4c63252..6b6b10c3 100644
--- a/glib/tests/fuzzing/util_fuzzer.cc
+++ b/glib/tests/fuzzing/util_fuzzer.cc
@@ -10,7 +10,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     gsize length;
     guint8 *tmp_uint;
 
-    buf = (char *)malloc(size + 1);
+    buf = (char *)calloc(size + 1, sizeof(char));
     memcpy(buf, data, size);
     buf[size] = '\0';
 
commit e05e627a5f6e92cf1c1897c490851db176eb9999
Author: Ceyhun Alp <ceyhunalp at google.com>
Date:   Mon Nov 9 11:31:58 2020 +0000

    Clang format

diff --git a/glib/tests/fuzzing/annot_fuzzer.cc b/glib/tests/fuzzing/annot_fuzzer.cc
index f06d8d30..d36da68e 100644
--- a/glib/tests/fuzzing/annot_fuzzer.cc
+++ b/glib/tests/fuzzing/annot_fuzzer.cc
@@ -20,7 +20,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     cairo_surface_t *surface;
     cairo_status_t status;
 
-    doc = poppler_document_new_from_data((char*)data, size, NULL, &err);
+    doc = poppler_document_new_from_data((char *)data, size, NULL, &err);
     if (doc == NULL) {
         g_error_free(err);
         return 0;
diff --git a/glib/tests/fuzzing/doc_attr_fuzzer.cc b/glib/tests/fuzzing/doc_attr_fuzzer.cc
index c5816ea9..55924154 100644
--- a/glib/tests/fuzzing/doc_attr_fuzzer.cc
+++ b/glib/tests/fuzzing/doc_attr_fuzzer.cc
@@ -11,7 +11,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     char *buf;
     int npages, n;
 
-    doc = poppler_document_new_from_data((char*)data, size, NULL, &err);
+    doc = poppler_document_new_from_data((char *)data, size, NULL, &err);
     if (doc == NULL) {
         g_error_free(err);
         return 0;
diff --git a/glib/tests/fuzzing/find_text_fuzzer.cc b/glib/tests/fuzzing/find_text_fuzzer.cc
index 4567e26e..2e84ac78 100644
--- a/glib/tests/fuzzing/find_text_fuzzer.cc
+++ b/glib/tests/fuzzing/find_text_fuzzer.cc
@@ -11,7 +11,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     char *buf;
     int npages;
 
-    doc = poppler_document_new_from_data((char*)data, size, NULL, &err);
+    doc = poppler_document_new_from_data((char *)data, size, NULL, &err);
     if (doc == NULL) {
         g_error_free(err);
         return 0;
diff --git a/glib/tests/fuzzing/label_fuzzer.cc b/glib/tests/fuzzing/label_fuzzer.cc
index b5b2374c..a1ecfbd6 100644
--- a/glib/tests/fuzzing/label_fuzzer.cc
+++ b/glib/tests/fuzzing/label_fuzzer.cc
@@ -11,7 +11,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     char *buf;
     int npages;
 
-    doc = poppler_document_new_from_data((char*)data, size, NULL, &err);
+    doc = poppler_document_new_from_data((char *)data, size, NULL, &err);
     if (doc == NULL) {
         g_error_free(err);
         return 0;
diff --git a/glib/tests/fuzzing/pdf_draw_fuzzer.cc b/glib/tests/fuzzing/pdf_draw_fuzzer.cc
index 81277ee4..357fbf20 100644
--- a/glib/tests/fuzzing/pdf_draw_fuzzer.cc
+++ b/glib/tests/fuzzing/pdf_draw_fuzzer.cc
@@ -19,7 +19,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     cairo_surface_t *surface;
     cairo_status_t status;
 
-    doc = poppler_document_new_from_data((char*)data, size, NULL, &err);
+    doc = poppler_document_new_from_data((char *)data, size, NULL, &err);
     if (doc == NULL) {
         g_error_free(err);
         return 0;
diff --git a/glib/tests/fuzzing/util_fuzzer.cc b/glib/tests/fuzzing/util_fuzzer.cc
index b39a1b30..a4c63252 100644
--- a/glib/tests/fuzzing/util_fuzzer.cc
+++ b/glib/tests/fuzzing/util_fuzzer.cc
@@ -14,7 +14,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     memcpy(buf, data, size);
     buf[size] = '\0';
 
-    tmp_ch = poppler_named_dest_from_bytestring((const guint8*)buf, size);
+    tmp_ch = poppler_named_dest_from_bytestring((const guint8 *)buf, size);
     tmp_uint = poppler_named_dest_to_bytestring(buf, &length);
 
     g_free(tmp_ch);
commit e09a603e2ff08ce50fc5a71146101bb4ce40c467
Author: Ceyhun Alp <ceyhunalp at google.com>
Date:   Wed Nov 4 13:24:26 2020 +0000

    Changing glib fuzzers from C to CPP
    
    ...
    
    replace c with cc - glib
    
    missing includes

diff --git a/glib/tests/CMakeLists.txt b/glib/tests/CMakeLists.txt
index 12f933b6..a2259cbe 100644
--- a/glib/tests/CMakeLists.txt
+++ b/glib/tests/CMakeLists.txt
@@ -63,10 +63,10 @@ macro(GLIB_ADD_FUZZER exe)
 endmacro(GLIB_ADD_FUZZER)
 
 if(ENABLE_FUZZER)
-    glib_add_fuzzer(annot_fuzzer ./fuzzing/annot_fuzzer.c)
-    glib_add_fuzzer(doc_attr_fuzzer ./fuzzing/doc_attr_fuzzer.c)
-    glib_add_fuzzer(find_text_fuzzer ./fuzzing/find_text_fuzzer.c)
-    glib_add_fuzzer(util_fuzzer ./fuzzing/util_fuzzer.c)
-    glib_add_fuzzer(label_fuzzer ./fuzzing/label_fuzzer.c)
-    glib_add_fuzzer(pdf_draw_fuzzer ./fuzzing/pdf_draw_fuzzer.c)
+    glib_add_fuzzer(annot_fuzzer ./fuzzing/annot_fuzzer.cc)
+    glib_add_fuzzer(doc_attr_fuzzer ./fuzzing/doc_attr_fuzzer.cc)
+    glib_add_fuzzer(find_text_fuzzer ./fuzzing/find_text_fuzzer.cc)
+    glib_add_fuzzer(util_fuzzer ./fuzzing/util_fuzzer.cc)
+    glib_add_fuzzer(label_fuzzer ./fuzzing/label_fuzzer.cc)
+    glib_add_fuzzer(pdf_draw_fuzzer ./fuzzing/pdf_draw_fuzzer.cc)
 endif()
diff --git a/glib/tests/fuzzing/annot_fuzzer.c b/glib/tests/fuzzing/annot_fuzzer.cc
similarity index 92%
rename from glib/tests/fuzzing/annot_fuzzer.c
rename to glib/tests/fuzzing/annot_fuzzer.cc
index db9c033b..f06d8d30 100644
--- a/glib/tests/fuzzing/annot_fuzzer.c
+++ b/glib/tests/fuzzing/annot_fuzzer.cc
@@ -5,7 +5,7 @@
 
 #include "fuzzer_temp_file.h"
 
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
     GError *err = NULL;
     PopplerDocument *doc;
@@ -20,7 +20,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     cairo_surface_t *surface;
     cairo_status_t status;
 
-    doc = poppler_document_new_from_data(data, size, NULL, &err);
+    doc = poppler_document_new_from_data((char*)data, size, NULL, &err);
     if (doc == NULL) {
         g_error_free(err);
         return 0;
diff --git a/glib/tests/fuzzing/doc_attr_fuzzer.c b/glib/tests/fuzzing/doc_attr_fuzzer.cc
similarity index 76%
rename from glib/tests/fuzzing/doc_attr_fuzzer.c
rename to glib/tests/fuzzing/doc_attr_fuzzer.cc
index a20726aa..c5816ea9 100644
--- a/glib/tests/fuzzing/doc_attr_fuzzer.c
+++ b/glib/tests/fuzzing/doc_attr_fuzzer.cc
@@ -1,7 +1,9 @@
+#include <stdlib.h>
 #include <stdint.h>
+#include <string.h>
 #include <poppler.h>
 
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
     GError *err = NULL;
     PopplerDocument *doc;
@@ -9,7 +11,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     char *buf;
     int npages, n;
 
-    doc = poppler_document_new_from_data(data, size, NULL, &err);
+    doc = poppler_document_new_from_data((char*)data, size, NULL, &err);
     if (doc == NULL) {
         g_error_free(err);
         return 0;
diff --git a/glib/tests/fuzzing/find_text_fuzzer.c b/glib/tests/fuzzing/find_text_fuzzer.cc
similarity index 78%
rename from glib/tests/fuzzing/find_text_fuzzer.c
rename to glib/tests/fuzzing/find_text_fuzzer.cc
index 57707188..4567e26e 100644
--- a/glib/tests/fuzzing/find_text_fuzzer.c
+++ b/glib/tests/fuzzing/find_text_fuzzer.cc
@@ -1,7 +1,9 @@
+#include <stdlib.h>
 #include <stdint.h>
+#include <string.h>
 #include <poppler.h>
 
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
     GError *err = NULL;
     PopplerDocument *doc;
@@ -9,7 +11,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     char *buf;
     int npages;
 
-    doc = poppler_document_new_from_data(data, size, NULL, &err);
+    doc = poppler_document_new_from_data((char*)data, size, NULL, &err);
     if (doc == NULL) {
         g_error_free(err);
         return 0;
diff --git a/glib/tests/fuzzing/label_fuzzer.c b/glib/tests/fuzzing/label_fuzzer.cc
similarity index 77%
rename from glib/tests/fuzzing/label_fuzzer.c
rename to glib/tests/fuzzing/label_fuzzer.cc
index 87bfc6c8..b5b2374c 100644
--- a/glib/tests/fuzzing/label_fuzzer.c
+++ b/glib/tests/fuzzing/label_fuzzer.cc
@@ -1,7 +1,9 @@
+#include <stdlib.h>
 #include <stdint.h>
+#include <string.h>
 #include <poppler.h>
 
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
     GError *err = NULL;
     PopplerDocument *doc;
@@ -9,7 +11,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     char *buf;
     int npages;
 
-    doc = poppler_document_new_from_data(data, size, NULL, &err);
+    doc = poppler_document_new_from_data((char*)data, size, NULL, &err);
     if (doc == NULL) {
         g_error_free(err);
         return 0;
diff --git a/glib/tests/fuzzing/pdf_draw_fuzzer.c b/glib/tests/fuzzing/pdf_draw_fuzzer.cc
similarity index 92%
rename from glib/tests/fuzzing/pdf_draw_fuzzer.c
rename to glib/tests/fuzzing/pdf_draw_fuzzer.cc
index fffbdb20..81277ee4 100644
--- a/glib/tests/fuzzing/pdf_draw_fuzzer.c
+++ b/glib/tests/fuzzing/pdf_draw_fuzzer.cc
@@ -5,7 +5,7 @@
 
 #include "fuzzer_temp_file.h"
 
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
     GError *err = NULL;
     PopplerDocument *doc;
@@ -19,7 +19,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     cairo_surface_t *surface;
     cairo_status_t status;
 
-    doc = poppler_document_new_from_data(data, size, NULL, &err);
+    doc = poppler_document_new_from_data((char*)data, size, NULL, &err);
     if (doc == NULL) {
         g_error_free(err);
         return 0;
diff --git a/glib/tests/fuzzing/util_fuzzer.c b/glib/tests/fuzzing/util_fuzzer.cc
similarity index 64%
rename from glib/tests/fuzzing/util_fuzzer.c
rename to glib/tests/fuzzing/util_fuzzer.cc
index 185a341f..b39a1b30 100644
--- a/glib/tests/fuzzing/util_fuzzer.c
+++ b/glib/tests/fuzzing/util_fuzzer.cc
@@ -1,7 +1,9 @@
+#include <stdlib.h>
 #include <stdint.h>
+#include <string.h>
 #include <poppler.h>
 
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
     char *tmp_ch;
     char *buf;
@@ -12,7 +14,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     memcpy(buf, data, size);
     buf[size] = '\0';
 
-    tmp_ch = poppler_named_dest_from_bytestring(buf, size);
+    tmp_ch = poppler_named_dest_from_bytestring((const guint8*)buf, size);
     tmp_uint = poppler_named_dest_to_bytestring(buf, &length);
 
     g_free(tmp_ch);
commit 44af15369a974b2b26a10fa3f4f99ba8e7542bd9
Author: Ceyhun Alp <ceyhunalp at google.com>
Date:   Fri Oct 30 00:41:41 2020 +0000

    Fixing null-terminated string parameters

diff --git a/cpp/tests/fuzzing/doc_fuzzer.cc b/cpp/tests/fuzzing/doc_fuzzer.cc
index 520649c7..1769ce40 100644
--- a/cpp/tests/fuzzing/doc_fuzzer.cc
+++ b/cpp/tests/fuzzing/doc_fuzzer.cc
@@ -1,16 +1,19 @@
 #include <cstdint>
-#include <poppler-global.h>
 #include <poppler-document.h>
-#include <poppler-page.h>
+#include <poppler-global.h>
 
 #include "FuzzedDataProvider.h"
 
 const size_t input_size = 32;
+const size_t count = 6;
 
 static void dummy_error_function(const std::string &, void *) { }
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
+    if (size < input_size * count) {
+        return 0;
+    }
     poppler::set_debug_error_function(dummy_error_function, nullptr);
     poppler::document *doc = poppler::document::load_from_raw_data((const char *)data, size);
     if (!doc || doc->is_locked()) {
@@ -34,12 +37,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     doc->set_subject(poppler::ustring::from_latin1(in_sub));
     doc->set_title(poppler::ustring::from_latin1(in_title));
 
-    doc->set_author(poppler::ustring::from_utf8((const char *)data, size));
-    doc->set_creator(poppler::ustring::from_utf8((const char *)data, size));
-    doc->set_keywords(poppler::ustring::from_utf8((const char *)data, size));
-    doc->set_producer(poppler::ustring::from_utf8((const char *)data, size));
-    doc->set_subject(poppler::ustring::from_utf8((const char *)data, size));
-    doc->set_title(poppler::ustring::from_utf8((const char *)data, size));
+    doc->set_author(poppler::ustring::from_utf8(in_auth.c_str(), -1));
+    doc->set_creator(poppler::ustring::from_utf8(in_creat.c_str(), -1));
+    doc->set_keywords(poppler::ustring::from_utf8(in_key.c_str(), -1));
+    doc->set_producer(poppler::ustring::from_utf8(in_prod.c_str(), -1));
+    doc->set_subject(poppler::ustring::from_utf8(in_sub.c_str(), -1));
+    doc->set_title(poppler::ustring::from_utf8(in_title.c_str(), -1));
 
     delete doc;
     return 0;
diff --git a/cpp/tests/fuzzing/page_label_fuzzer.cc b/cpp/tests/fuzzing/page_label_fuzzer.cc
index 19106036..467be74a 100644
--- a/cpp/tests/fuzzing/page_label_fuzzer.cc
+++ b/cpp/tests/fuzzing/page_label_fuzzer.cc
@@ -1,14 +1,20 @@
 #include <cstdint>
-
-#include <poppler-global.h>
 #include <poppler-document.h>
+#include <poppler-global.h>
 #include <poppler-page.h>
 #include <poppler-page-renderer.h>
 
+#include "FuzzedDataProvider.h"
+
+const size_t input_size = 32;
+
 static void dummy_error_function(const std::string &, void *) { }
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
+    if (size < input_size) {
+        return 0;
+    }
     poppler::set_debug_error_function(dummy_error_function, nullptr);
 
     poppler::document *doc = poppler::document::load_from_raw_data((const char *)data, size);
@@ -18,13 +24,15 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     }
 
     poppler::page_renderer r;
+    FuzzedDataProvider data_provider(data, size);
+    std::string in_label = data_provider.ConsumeBytesAsString(input_size);
     for (int i = 0; i < doc->pages(); i++) {
-        poppler::ustring label = poppler::ustring::from_utf8((const char *)data, size);
-        poppler::page *p = doc->create_page(label);
+        poppler::page *p = doc->create_page(poppler::ustring::from_utf8(in_label.c_str(), -1));
         if (!p) {
             continue;
         }
         r.render_page(p);
+        p->label();
         delete p;
     }
 
diff --git a/cpp/tests/fuzzing/page_search_fuzzer.cc b/cpp/tests/fuzzing/page_search_fuzzer.cc
index 6427976c..1c6977f2 100644
--- a/cpp/tests/fuzzing/page_search_fuzzer.cc
+++ b/cpp/tests/fuzzing/page_search_fuzzer.cc
@@ -1,14 +1,20 @@
 #include <cstdint>
-
-#include <poppler-global.h>
 #include <poppler-document.h>
+#include <poppler-global.h>
 #include <poppler-page.h>
 #include <poppler-page-renderer.h>
 
+#include "FuzzedDataProvider.h"
+
+const size_t input_size = 32;
+
 static void dummy_error_function(const std::string &, void *) { }
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
+    if (size < input_size) {
+        return 0;
+    }
     poppler::set_debug_error_function(dummy_error_function, nullptr);
 
     poppler::document *doc = poppler::document::load_from_raw_data((const char *)data, size);
@@ -18,13 +24,15 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     }
 
     poppler::page_renderer r;
+    FuzzedDataProvider data_provider(data, size);
+    std::string in_text = data_provider.ConsumeBytesAsString(input_size);
     for (int i = 0; i < doc->pages(); i++) {
         poppler::page *p = doc->create_page(i);
         if (!p) {
             continue;
         }
         poppler::rectf rect = p->page_rect();
-        poppler::ustring text = poppler::ustring::from_utf8((const char *)data, size);
+        poppler::ustring text = poppler::ustring::from_utf8(in_text.c_str(), -1);
         p->search(text, rect, poppler::page::search_from_top, poppler::case_insensitive, poppler::rotate_0);
         r.render_page(p);
         delete p;
diff --git a/cpp/tests/fuzzing/pdf_file_fuzzer.cc b/cpp/tests/fuzzing/pdf_file_fuzzer.cc
index 6a682a17..10374e8b 100644
--- a/cpp/tests/fuzzing/pdf_file_fuzzer.cc
+++ b/cpp/tests/fuzzing/pdf_file_fuzzer.cc
@@ -1,8 +1,6 @@
 #include <cstdint>
-#include <string>
-
-#include <poppler-global.h>
 #include <poppler-document.h>
+#include <poppler-global.h>
 #include <poppler-page.h>
 #include <poppler-page-renderer.h>
 
diff --git a/cpp/tests/fuzzing/pdf_fuzzer.cc b/cpp/tests/fuzzing/pdf_fuzzer.cc
index 71cc9ae6..90cad426 100644
--- a/cpp/tests/fuzzing/pdf_fuzzer.cc
+++ b/cpp/tests/fuzzing/pdf_fuzzer.cc
@@ -1,34 +1,15 @@
-/*
-# Copyright 2018 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-*/
-
 #include <cstdint>
-
 #include <poppler-destination.h>
-#include <poppler-global.h>
 #include <poppler-document.h>
+#include <poppler-global.h>
 #include <poppler-page.h>
 #include <poppler-page-renderer.h>
 
-static void nop_func(const std::string &msg, void *) {};
+static void dummy_error_function(const std::string &, void *) { }
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
-    poppler::set_debug_error_function(nop_func, nullptr);
+    poppler::set_debug_error_function(dummy_error_function, nullptr);
 
     poppler::document *doc = poppler::document::load_from_raw_data((const char *)data, size);
     if (!doc || doc->is_locked()) {
diff --git a/glib/tests/fuzzing/find_text_fuzzer.c b/glib/tests/fuzzing/find_text_fuzzer.c
index 744f0051..57707188 100644
--- a/glib/tests/fuzzing/find_text_fuzzer.c
+++ b/glib/tests/fuzzing/find_text_fuzzer.c
@@ -6,6 +6,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     GError *err = NULL;
     PopplerDocument *doc;
     PopplerPage *page;
+    char *buf;
     int npages;
 
     doc = poppler_document_new_from_data(data, size, NULL, &err);
@@ -19,13 +20,18 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
         return 0;
     }
 
+    buf = (char *)malloc(size + 1);
+    memcpy(buf, data, size);
+    buf[size] = '\0';
+
     for (int n = 0; n < npages; n++) {
         page = poppler_document_get_page(doc, n);
         if (!page) {
             continue;
         }
-        poppler_page_find_text(page, data);
+        poppler_page_find_text(page, buf);
         g_object_unref(page);
     }
+    free(buf);
     return 0;
 }
diff --git a/glib/tests/fuzzing/label_fuzzer.c b/glib/tests/fuzzing/label_fuzzer.c
index 0cb5f6d4..87bfc6c8 100644
--- a/glib/tests/fuzzing/label_fuzzer.c
+++ b/glib/tests/fuzzing/label_fuzzer.c
@@ -23,8 +23,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     buf = (char *)malloc(size + 1);
     memcpy(buf, data, size);
     buf[size] = '\0';
+
     for (int n = 0; n < npages; n++) {
-        /*page = poppler_document_get_page_by_label(doc, data);*/
         page = poppler_document_get_page_by_label(doc, buf);
         if (!page) {
             continue;
commit 919a71e52110774f461cbe079a5ed65cf8f48c91
Author: Ceyhun Alp <ceyhunalp at google.com>
Date:   Thu Oct 29 23:32:15 2020 +0000

    Updating pdf_fuzzer with the version from OSS-Fuzz repository

diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt
index 18b17334..10ac0b32 100644
--- a/cpp/tests/CMakeLists.txt
+++ b/cpp/tests/CMakeLists.txt
@@ -22,6 +22,7 @@ cpp_add_simpletest(poppler-render poppler-render.cpp ${CMAKE_SOURCE_DIR}/utils/p
 
 if(ENABLE_FUZZER)
   cpp_add_simpletest(doc_fuzzer ./fuzzing/doc_fuzzer.cc)
+  cpp_add_simpletest(pdf_fuzzer ./fuzzing/pdf_fuzzer.cc)
   cpp_add_simpletest(pdf_file_fuzzer ./fuzzing/pdf_file_fuzzer.cc)
   cpp_add_simpletest(page_label_fuzzer ./fuzzing/page_label_fuzzer.cc)
   cpp_add_simpletest(page_search_fuzzer ./fuzzing/page_search_fuzzer.cc)
diff --git a/cpp/tests/pdf_fuzzer.cc b/cpp/tests/fuzzing/pdf_fuzzer.cc
similarity index 80%
rename from cpp/tests/pdf_fuzzer.cc
rename to cpp/tests/fuzzing/pdf_fuzzer.cc
index 6924bc00..71cc9ae6 100644
--- a/cpp/tests/pdf_fuzzer.cc
+++ b/cpp/tests/fuzzing/pdf_fuzzer.cc
@@ -18,22 +18,27 @@
 
 #include <cstdint>
 
+#include <poppler-destination.h>
 #include <poppler-global.h>
 #include <poppler-document.h>
 #include <poppler-page.h>
 #include <poppler-page-renderer.h>
 
-static void dummy_error_function(const std::string &, void *) { }
+static void nop_func(const std::string &msg, void *) {};
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
-    poppler::set_debug_error_function(dummy_error_function, nullptr);
+    poppler::set_debug_error_function(nop_func, nullptr);
 
     poppler::document *doc = poppler::document::load_from_raw_data((const char *)data, size);
     if (!doc || doc->is_locked()) {
         delete doc;
         return 0;
     }
+    doc->metadata();
+    doc->create_destination_map();
+    doc->embedded_files();
+    doc->fonts();
 
     poppler::page_renderer r;
     for (int i = 0; i < doc->pages(); i++) {
@@ -42,6 +47,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
             continue;
         }
         r.render_page(p);
+        p->text_list(poppler::page::text_list_include_font);
         delete p;
     }
 
commit 1e73805f7d8d1ca453550d133d86f59305011e78
Author: Ceyhun Alp <ceyhunalp at google.com>
Date:   Wed Oct 28 01:00:58 2020 +0000

    Fixes from Michael's feedback

diff --git a/cpp/tests/fuzzing/doc_fuzzer.cc b/cpp/tests/fuzzing/doc_fuzzer.cc
index b8dd957f..520649c7 100644
--- a/cpp/tests/fuzzing/doc_fuzzer.cc
+++ b/cpp/tests/fuzzing/doc_fuzzer.cc
@@ -1,11 +1,11 @@
 #include <cstdint>
-
 #include <poppler-global.h>
 #include <poppler-document.h>
 #include <poppler-page.h>
+
 #include "FuzzedDataProvider.h"
 
-#define INPUT_SIZE 32
+const size_t input_size = 32;
 
 static void dummy_error_function(const std::string &, void *) { }
 
@@ -19,12 +19,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     }
 
     FuzzedDataProvider data_provider(data, size);
-    std::string in_auth = data_provider.ConsumeBytesAsString(INPUT_SIZE);
-    std::string in_creat = data_provider.ConsumeBytesAsString(INPUT_SIZE);
-    std::string in_key = data_provider.ConsumeBytesAsString(INPUT_SIZE);
-    std::string in_prod = data_provider.ConsumeBytesAsString(INPUT_SIZE);
-    std::string in_sub = data_provider.ConsumeBytesAsString(INPUT_SIZE);
-    std::string in_title = data_provider.ConsumeBytesAsString(INPUT_SIZE);
+    std::string in_auth = data_provider.ConsumeBytesAsString(input_size);
+    std::string in_creat = data_provider.ConsumeBytesAsString(input_size);
+    std::string in_key = data_provider.ConsumeBytesAsString(input_size);
+    std::string in_prod = data_provider.ConsumeBytesAsString(input_size);
+    std::string in_sub = data_provider.ConsumeBytesAsString(input_size);
+    std::string in_title = data_provider.ConsumeBytesAsString(input_size);
 
     // Testing both methods for conversion to ustring
     doc->set_author(poppler::ustring::from_latin1(in_auth));
diff --git a/glib/tests/fuzzing/annot_fuzzer.c b/glib/tests/fuzzing/annot_fuzzer.c
index db3f0e49..db9c033b 100644
--- a/glib/tests/fuzzing/annot_fuzzer.c
+++ b/glib/tests/fuzzing/annot_fuzzer.c
@@ -56,8 +56,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
                 continue;
             }
             poppler_page_add_annot(page, annot);
-            /*poppler_annot_set_contents(annot, data);*/
-            /*poppler_annot_markup_set_label(annot, data);*/
         }
 
         cr = cairo_create(surface);
diff --git a/glib/tests/fuzzing/doc_attr_fuzzer.c b/glib/tests/fuzzing/doc_attr_fuzzer.c
index 1b62884b..a20726aa 100644
--- a/glib/tests/fuzzing/doc_attr_fuzzer.c
+++ b/glib/tests/fuzzing/doc_attr_fuzzer.c
@@ -6,6 +6,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     GError *err = NULL;
     PopplerDocument *doc;
     PopplerPage *page;
+    char *buf;
     int npages, n;
 
     doc = poppler_document_new_from_data(data, size, NULL, &err);
@@ -13,11 +14,18 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
         g_error_free(err);
         return 0;
     }
-    poppler_document_set_author(doc, data);
-    poppler_document_set_creator(doc, data);
-    poppler_document_set_keywords(doc, data);
-    poppler_document_set_producer(doc, data);
-    poppler_document_set_subject(doc, data);
-    poppler_document_set_title(doc, data);
+
+    buf = (char *)malloc(size + 1);
+    memcpy(buf, data, size);
+    buf[size] = '\0';
+
+    poppler_document_set_author(doc, buf);
+    poppler_document_set_creator(doc, buf);
+    poppler_document_set_keywords(doc, buf);
+    poppler_document_set_producer(doc, buf);
+    poppler_document_set_subject(doc, buf);
+    poppler_document_set_title(doc, buf);
+
+    free(buf);
     return 0;
 }
diff --git a/glib/tests/fuzzing/label_fuzzer.c b/glib/tests/fuzzing/label_fuzzer.c
index 5475184e..0cb5f6d4 100644
--- a/glib/tests/fuzzing/label_fuzzer.c
+++ b/glib/tests/fuzzing/label_fuzzer.c
@@ -6,6 +6,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     GError *err = NULL;
     PopplerDocument *doc;
     PopplerPage *page;
+    char *buf;
     int npages;
 
     doc = poppler_document_new_from_data(data, size, NULL, &err);
@@ -19,12 +20,17 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
         return 0;
     }
 
+    buf = (char *)malloc(size + 1);
+    memcpy(buf, data, size);
+    buf[size] = '\0';
     for (int n = 0; n < npages; n++) {
-        page = poppler_document_get_page_by_label(doc, data);
+        /*page = poppler_document_get_page_by_label(doc, data);*/
+        page = poppler_document_get_page_by_label(doc, buf);
         if (!page) {
             continue;
         }
         g_object_unref(page);
     }
+    free(buf);
     return 0;
 }
diff --git a/glib/tests/fuzzing/util_fuzzer.c b/glib/tests/fuzzing/util_fuzzer.c
index 01f3c2d4..185a341f 100644
--- a/glib/tests/fuzzing/util_fuzzer.c
+++ b/glib/tests/fuzzing/util_fuzzer.c
@@ -3,8 +3,20 @@
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
+    char *tmp_ch;
+    char *buf;
     gsize length;
-    poppler_named_dest_from_bytestring(data, size);
-    poppler_named_dest_to_bytestring(data, &length);
+    guint8 *tmp_uint;
+
+    buf = (char *)malloc(size + 1);
+    memcpy(buf, data, size);
+    buf[size] = '\0';
+
+    tmp_ch = poppler_named_dest_from_bytestring(buf, size);
+    tmp_uint = poppler_named_dest_to_bytestring(buf, &length);
+
+    g_free(tmp_ch);
+    g_free(tmp_uint);
+    free(buf);
     return 0;
 }
diff --git a/qt5/tests/fuzzing/FuzzedDataProvider.h b/qt5/tests/fuzzing/FuzzedDataProvider.h
deleted file mode 100644
index 1996bcad..00000000
--- a/qt5/tests/fuzzing/FuzzedDataProvider.h
+++ /dev/null
@@ -1,409 +0,0 @@
-//===- FuzzedDataProvider.h - Utility header for fuzz targets ---*- C++ -* ===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// A single header library providing an utility class to break up an array of
-// bytes. Whenever run on the same input, provides the same output, as long as
-// its methods are called in the same order, with the same arguments.
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
-#define LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
-
-#include <algorithm>
-#include <climits>
-#include <cstddef>
-#include <cstdint>
-#include <cstring>
-#include <initializer_list>
-#include <string>
-#include <type_traits>
-#include <utility>
-#include <vector>
-
-// In addition to the comments below, the API is also briefly documented at
-// https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider
-class FuzzedDataProvider
-{
-public:
-    // |data| is an array of length |size| that the FuzzedDataProvider wraps to
-    // provide more granular access. |data| must outlive the FuzzedDataProvider.
-    FuzzedDataProvider(const uint8_t *data, size_t size) : data_ptr_(data), remaining_bytes_(size) { }
-    ~FuzzedDataProvider() = default;
-
-    // See the implementation below (after the class definition) for more verbose
-    // comments for each of the methods.
-
-    // Methods returning std::vector of bytes. These are the most popular choice
-    // when splitting fuzzing input into pieces, as every piece is put into a
-    // separate buffer (i.e. ASan would catch any under-/overflow) and the memory
-    // will be released automatically.
-    template<typename T>
-    std::vector<T> ConsumeBytes(size_t num_bytes);
-    template<typename T>
-    std::vector<T> ConsumeBytesWithTerminator(size_t num_bytes, T terminator = 0);
-    template<typename T>
-    std::vector<T> ConsumeRemainingBytes();
-
-    // Methods returning strings. Use only when you need a std::string or a null
-    // terminated C-string. Otherwise, prefer the methods returning std::vector.
-    std::string ConsumeBytesAsString(size_t num_bytes);
-    std::string ConsumeRandomLengthString(size_t max_length);
-    std::string ConsumeRandomLengthString();
-    std::string ConsumeRemainingBytesAsString();
-
-    // Methods returning integer values.
-    template<typename T>
-    T ConsumeIntegral();
-    template<typename T>
-    T ConsumeIntegralInRange(T min, T max);
-
-    // Methods returning floating point values.
-    template<typename T>
-    T ConsumeFloatingPoint();
-    template<typename T>
-    T ConsumeFloatingPointInRange(T min, T max);
-
-    // 0 <= return value <= 1.
-    template<typename T>
-    T ConsumeProbability();
-
-    bool ConsumeBool();
-
-    // Returns a value chosen from the given enum.
-    template<typename T>
-    T ConsumeEnum();
-
-    // Returns a value from the given array.
-    template<typename T, size_t size>
-    T PickValueInArray(const T (&array)[size]);
-    template<typename T>
-    T PickValueInArray(std::initializer_list<const T> list);
-
-    // Writes data to the given destination and returns number of bytes written.
-    size_t ConsumeData(void *destination, size_t num_bytes);
-
-    // Reports the remaining bytes available for fuzzed input.
-    size_t remaining_bytes() { return remaining_bytes_; }
-
-private:
-    FuzzedDataProvider(const FuzzedDataProvider &) = delete;
-    FuzzedDataProvider &operator=(const FuzzedDataProvider &) = delete;
-
-    void CopyAndAdvance(void *destination, size_t num_bytes);
-
-    void Advance(size_t num_bytes);
-
-    template<typename T>
-    std::vector<T> ConsumeBytes(size_t size, size_t num_bytes);
-
-    template<typename TS, typename TU>
-    TS ConvertUnsignedToSigned(TU value);
-
-    const uint8_t *data_ptr_;
-    size_t remaining_bytes_;
-};
-
-// Returns a std::vector containing |num_bytes| of input data. If fewer than
-// |num_bytes| of data remain, returns a shorter std::vector containing all
-// of the data that's left. Can be used with any byte sized type, such as
-// char, unsigned char, uint8_t, etc.
-template<typename T>
-std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t num_bytes)
-{
-    num_bytes = std::min(num_bytes, remaining_bytes_);
-    return ConsumeBytes<T>(num_bytes, num_bytes);
-}
-
-// Similar to |ConsumeBytes|, but also appends the terminator value at the end
-// of the resulting vector. Useful, when a mutable null-terminated C-string is
-// needed, for example. But that is a rare case. Better avoid it, if possible,
-// and prefer using |ConsumeBytes| or |ConsumeBytesAsString| methods.
-template<typename T>
-std::vector<T> FuzzedDataProvider::ConsumeBytesWithTerminator(size_t num_bytes, T terminator)
-{
-    num_bytes = std::min(num_bytes, remaining_bytes_);
-    std::vector<T> result = ConsumeBytes<T>(num_bytes + 1, num_bytes);
-    result.back() = terminator;
-    return result;
-}
-
-// Returns a std::vector containing all remaining bytes of the input data.
-template<typename T>
-std::vector<T> FuzzedDataProvider::ConsumeRemainingBytes()
-{
-    return ConsumeBytes<T>(remaining_bytes_);
-}
-
-// Returns a std::string containing |num_bytes| of input data. Using this and
-// |.c_str()| on the resulting string is the best way to get an immutable
-// null-terminated C string. If fewer than |num_bytes| of data remain, returns
-// a shorter std::string containing all of the data that's left.
-inline std::string FuzzedDataProvider::ConsumeBytesAsString(size_t num_bytes)
-{
-    static_assert(sizeof(std::string::value_type) == sizeof(uint8_t), "ConsumeBytesAsString cannot convert the data to a string.");
-
-    num_bytes = std::min(num_bytes, remaining_bytes_);
-    std::string result(reinterpret_cast<const std::string::value_type *>(data_ptr_), num_bytes);
-    Advance(num_bytes);
-    return result;
-}
-
-// Returns a std::string of length from 0 to |max_length|. When it runs out of
-// input data, returns what remains of the input. Designed to be more stable
-// with respect to a fuzzer inserting characters than just picking a random
-// length and then consuming that many bytes with |ConsumeBytes|.
-inline std::string FuzzedDataProvider::ConsumeRandomLengthString(size_t max_length)
-{
-    // Reads bytes from the start of |data_ptr_|. Maps "\\" to "\", and maps "\"
-    // followed by anything else to the end of the string. As a result of this
-    // logic, a fuzzer can insert characters into the string, and the string
-    // will be lengthened to include those new characters, resulting in a more
-    // stable fuzzer than picking the length of a string independently from
-    // picking its contents.
-    std::string result;
-
-    // Reserve the anticipated capaticity to prevent several reallocations.
-    result.reserve(std::min(max_length, remaining_bytes_));
-    for (size_t i = 0; i < max_length && remaining_bytes_ != 0; ++i) {
-        char next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
-        Advance(1);
-        if (next == '\\' && remaining_bytes_ != 0) {
-            next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
-            Advance(1);
-            if (next != '\\')
-                break;
-        }
-        result += next;
-    }
-
-    result.shrink_to_fit();
-    return result;
-}
-
-// Returns a std::string of length from 0 to |remaining_bytes_|.
-inline std::string FuzzedDataProvider::ConsumeRandomLengthString()
-{
-    return ConsumeRandomLengthString(remaining_bytes_);
-}
-
-// Returns a std::string containing all remaining bytes of the input data.
-// Prefer using |ConsumeRemainingBytes| unless you actually need a std::string
-// object.
-inline std::string FuzzedDataProvider::ConsumeRemainingBytesAsString()
-{
-    return ConsumeBytesAsString(remaining_bytes_);
-}
-
-// Returns a number in the range [Type's min, Type's max]. The value might
-// not be uniformly distributed in the given range. If there's no input data
-// left, always returns |min|.
-template<typename T>
-T FuzzedDataProvider::ConsumeIntegral()
-{
-    return ConsumeIntegralInRange(std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
-}
-
-// Returns a number in the range [min, max] by consuming bytes from the
-// input data. The value might not be uniformly distributed in the given
-// range. If there's no input data left, always returns |min|. |min| must
-// be less than or equal to |max|.
-template<typename T>
-T FuzzedDataProvider::ConsumeIntegralInRange(T min, T max)
-{
-    static_assert(std::is_integral<T>::value, "An integral type is required.");
-    static_assert(sizeof(T) <= sizeof(uint64_t), "Unsupported integral type.");
-
-    if (min > max)
-        abort();
-
-    // Use the biggest type possible to hold the range and the result.
-    uint64_t range = static_cast<uint64_t>(max) - min;
-    uint64_t result = 0;
-    size_t offset = 0;
-
-    while (offset < sizeof(T) * CHAR_BIT && (range >> offset) > 0 && remaining_bytes_ != 0) {
-        // Pull bytes off the end of the seed data. Experimentally, this seems to
-        // allow the fuzzer to more easily explore the input space. This makes
-        // sense, since it works by modifying inputs that caused new code to run,
-        // and this data is often used to encode length of data read by
-        // |ConsumeBytes|. Separating out read lengths makes it easier modify the
-        // contents of the data that is actually read.
-        --remaining_bytes_;
-        result = (result << CHAR_BIT) | data_ptr_[remaining_bytes_];
-        offset += CHAR_BIT;
-    }
-
-    // Avoid division by 0, in case |range + 1| results in overflow.
-    if (range != std::numeric_limits<decltype(range)>::max())
-        result = result % (range + 1);
-
-    return static_cast<T>(min + result);
-}
-
-// Returns a floating point value in the range [Type's lowest, Type's max] by
-// consuming bytes from the input data. If there's no input data left, always
-// returns approximately 0.
-template<typename T>
-T FuzzedDataProvider::ConsumeFloatingPoint()
-{
-    return ConsumeFloatingPointInRange<T>(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max());
-}
-
-// Returns a floating point value in the given range by consuming bytes from
-// the input data. If there's no input data left, returns |min|. Note that
-// |min| must be less than or equal to |max|.
-template<typename T>
-T FuzzedDataProvider::ConsumeFloatingPointInRange(T min, T max)
-{
-    if (min > max)
-        abort();
-
-    T range = .0;
-    T result = min;
-    constexpr T zero(.0);
-    if (max > zero && min < zero && max > min + std::numeric_limits<T>::max()) {
-        // The diff |max - min| would overflow the given floating point type. Use
-        // the half of the diff as the range and consume a bool to decide whether
-        // the result is in the first of the second part of the diff.
-        range = (max / 2.0) - (min / 2.0);
-        if (ConsumeBool()) {
-            result += range;
-        }
-    } else {
-        range = max - min;
-    }
-
-    return result + range * ConsumeProbability<T>();
-}
-
-// Returns a floating point number in the range [0.0, 1.0]. If there's no
-// input data left, always returns 0.
-template<typename T>
-T FuzzedDataProvider::ConsumeProbability()
-{
-    static_assert(std::is_floating_point<T>::value, "A floating point type is required.");
-
-    // Use different integral types for different floating point types in order
-    // to provide better density of the resulting values.
-    using IntegralType = typename std::conditional<(sizeof(T) <= sizeof(uint32_t)), uint32_t, uint64_t>::type;
-
-    T result = static_cast<T>(ConsumeIntegral<IntegralType>());
-    result /= static_cast<T>(std::numeric_limits<IntegralType>::max());
-    return result;
-}
-
-// Reads one byte and returns a bool, or false when no data remains.
-inline bool FuzzedDataProvider::ConsumeBool()
-{
-    return 1 & ConsumeIntegral<uint8_t>();
-}
-
-// Returns an enum value. The enum must start at 0 and be contiguous. It must
-// also contain |kMaxValue| aliased to its largest (inclusive) value. Such as:
-// enum class Foo { SomeValue, OtherValue, kMaxValue = OtherValue };
-template<typename T>
-T FuzzedDataProvider::ConsumeEnum()
-{
-    static_assert(std::is_enum<T>::value, "|T| must be an enum type.");
-    return static_cast<T>(ConsumeIntegralInRange<uint32_t>(0, static_cast<uint32_t>(T::kMaxValue)));
-}
-
-// Returns a copy of the value selected from the given fixed-size |array|.
-template<typename T, size_t size>
-T FuzzedDataProvider::PickValueInArray(const T (&array)[size])
-{
-    static_assert(size > 0, "The array must be non empty.");
-    return array[ConsumeIntegralInRange<size_t>(0, size - 1)];
-}
-
-template<typename T>
-T FuzzedDataProvider::PickValueInArray(std::initializer_list<const T> list)
-{
-    // TODO(Dor1s): switch to static_assert once C++14 is allowed.
-    if (!list.size())
-        abort();
-
-    return *(list.begin() + ConsumeIntegralInRange<size_t>(0, list.size() - 1));
-}
-
-// Writes |num_bytes| of input data to the given destination pointer. If there
-// is not enough data left, writes all remaining bytes. Return value is the
-// number of bytes written.
-// In general, it's better to avoid using this function, but it may be useful
-// in cases when it's necessary to fill a certain buffer or object with
-// fuzzing data.
-inline size_t FuzzedDataProvider::ConsumeData(void *destination, size_t num_bytes)
-{
-    num_bytes = std::min(num_bytes, remaining_bytes_);
-    CopyAndAdvance(destination, num_bytes);
-    return num_bytes;
-}
-
-// Private methods.
-inline void FuzzedDataProvider::CopyAndAdvance(void *destination, size_t num_bytes)
-{
-    std::memcpy(destination, data_ptr_, num_bytes);
-    Advance(num_bytes);
-}
-
-inline void FuzzedDataProvider::Advance(size_t num_bytes)
-{
-    if (num_bytes > remaining_bytes_)
-        abort();
-
-    data_ptr_ += num_bytes;
-    remaining_bytes_ -= num_bytes;
-}
-
-template<typename T>
-std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t size, size_t num_bytes)
-{
-    static_assert(sizeof(T) == sizeof(uint8_t), "Incompatible data type.");
-
-    // The point of using the size-based constructor below is to increase the
-    // odds of having a vector object with capacity being equal to the length.
-    // That part is always implementation specific, but at least both libc++ and
-    // libstdc++ allocate the requested number of bytes in that constructor,
-    // which seems to be a natural choice for other implementations as well.
-    // To increase the odds even more, we also call |shrink_to_fit| below.
-    std::vector<T> result(size);
-    if (size == 0) {
-        if (num_bytes != 0)
-            abort();
-        return result;
-    }
-
-    CopyAndAdvance(result.data(), num_bytes);
-
-    // Even though |shrink_to_fit| is also implementation specific, we expect it
-    // to provide an additional assurance in case vector's constructor allocated
-    // a buffer which is larger than the actual amount of data we put inside it.
-    result.shrink_to_fit();
-    return result;
-}
-
-template<typename TS, typename TU>
-TS FuzzedDataProvider::ConvertUnsignedToSigned(TU value)
-{
-    static_assert(sizeof(TS) == sizeof(TU), "Incompatible data types.");
-    static_assert(!std::numeric_limits<TU>::is_signed, "Source type must be unsigned.");
-
-    // TODO(Dor1s): change to `if constexpr` once C++17 becomes mainstream.
-    if (std::numeric_limits<TS>::is_modulo)
-        return static_cast<TS>(value);
-
-    // Avoid using implementation-defined unsigned to signed conversions.
-    // To learn more, see https://stackoverflow.com/questions/13150449.
-    if (value <= std::numeric_limits<TS>::max()) {
-        return static_cast<TS>(value);
-    } else {
-        constexpr auto TS_min = std::numeric_limits<TS>::min();
-        return TS_min + static_cast<char>(value - TS_min);
-    }
-}
-
-#endif // LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
diff --git a/qt5/tests/fuzzing/fuzzer_temp_file.h b/qt5/tests/fuzzing/fuzzer_temp_file.h
deleted file mode 100644
index d0568ac5..00000000
--- a/qt5/tests/fuzzing/fuzzer_temp_file.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2018 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Adapter utility from fuzzer input to a temporary file, for fuzzing APIs that
-// require a file instead of an input buffer.
-
-#ifndef FUZZER_TEMP_FILE_H_
-#define FUZZER_TEMP_FILE_H_
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-// Pure-C interface for creating and cleaning up temporary files.
-
-static char *fuzzer_get_tmpfile(const uint8_t *data, size_t size)
-{
-    char *filename_buffer = strdup("/tmp/generate_temporary_file.XXXXXX");
-    if (!filename_buffer) {
-        perror("Failed to allocate file name buffer.");
-        abort();
-    }
-    const int file_descriptor = mkstemp(filename_buffer);
-    if (file_descriptor < 0) {
-        perror("Failed to make temporary file.");
-        abort();
-    }
-    FILE *file = fdopen(file_descriptor, "wb");
-    if (!file) {
-        perror("Failed to open file descriptor.");
-        close(file_descriptor);
-        abort();
-    }
-    const size_t bytes_written = fwrite(data, sizeof(uint8_t), size, file);
-    if (bytes_written < size) {
-        close(file_descriptor);
-        fprintf(stderr, "Failed to write all bytes to file (%zu out of %zu)", bytes_written, size);
-        abort();
-    }
-    fclose(file);
-    return filename_buffer;
-}
-
-static void fuzzer_release_tmpfile(char *filename)
-{
-    if (unlink(filename) != 0) {
-        perror("WARNING: Failed to delete temporary file.");
-    }
-    free(filename);
-}
-
-// C++ RAII object for creating temporary files.
-
-#ifdef __cplusplus
-class FuzzerTemporaryFile
-{
-public:
-    FuzzerTemporaryFile(const uint8_t *data, size_t size) : filename_(fuzzer_get_tmpfile(data, size)) { }
-
-    ~FuzzerTemporaryFile() { fuzzer_release_tmpfile(filename_); }
-
-    const char *filename() const { return filename_; }
-
-private:
-    char *filename_;
-};
-#endif
-
-#endif // FUZZER_TEMP_FILE_H_
diff --git a/qt5/tests/fuzzing/qt_annot_fuzzer.cc b/qt5/tests/fuzzing/qt_annot_fuzzer.cc
index 8b569f28..f34af342 100644
--- a/qt5/tests/fuzzing/qt_annot_fuzzer.cc
+++ b/qt5/tests/fuzzing/qt_annot_fuzzer.cc
@@ -1,6 +1,6 @@
 #include <cstdint>
 #include <poppler-qt5.h>
-#include "fuzzer_temp_file.h"
+#include <QtCore/QBuffer>
 
 static void dummy_error_function(const QString &, const QVariant &) { }
 
@@ -9,14 +9,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     Poppler::setDebugErrorFunction(dummy_error_function, QVariant());
     const QFont font(QStringLiteral("Helvetica"), 20);
     const QColor color = QColor::fromRgb(0xAB, 0xCD, 0xEF);
-    char *tmpfile = fuzzer_get_tmpfile(data, size);
 
     QByteArray in_data = QByteArray::fromRawData((const char *)data, size);
     Poppler::Document *doc = Poppler::Document::loadFromData(in_data);
 
     if (!doc || doc->isLocked()) {
         delete doc;
-        fuzzer_release_tmpfile(tmpfile);
         return 0;
     }
 
@@ -32,15 +30,17 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
         ann->setContents(QString(in_data));
         p->addAnnotation(ann);
 
+        QBuffer buffer;
+        buffer.open(QIODevice::WriteOnly);
         std::unique_ptr<Poppler::PDFConverter> conv(doc->pdfConverter());
-        conv->setOutputFileName(tmpfile);
+        conv->setOutputDevice(&buffer);
         conv->setPDFOptions(Poppler::PDFConverter::WithChanges);
         conv->convert();
+        buffer.close();
         delete ann;
         delete p;
     }
 
-    fuzzer_release_tmpfile(tmpfile);
     delete doc;
     return 0;
 }
commit 48026f90fd07f3da886ce0079facec49f8022c07
Author: Ceyhun Alp <ceyhunalp at google.com>
Date:   Fri Oct 23 11:02:20 2020 +0000

    Fixing clang_format issues

diff --git a/cpp/tests/fuzzing/FuzzedDataProvider.h b/cpp/tests/fuzzing/FuzzedDataProvider.h
index 83bcd013..1996bcad 100644
--- a/cpp/tests/fuzzing/FuzzedDataProvider.h
+++ b/cpp/tests/fuzzing/FuzzedDataProvider.h
@@ -26,288 +26,308 @@
 
 // In addition to the comments below, the API is also briefly documented at
 // https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider
-class FuzzedDataProvider {
- public:
-  // |data| is an array of length |size| that the FuzzedDataProvider wraps to
-  // provide more granular access. |data| must outlive the FuzzedDataProvider.
-  FuzzedDataProvider(const uint8_t *data, size_t size)
-      : data_ptr_(data), remaining_bytes_(size) {}
-  ~FuzzedDataProvider() = default;
-
-  // See the implementation below (after the class definition) for more verbose
-  // comments for each of the methods.
-
-  // Methods returning std::vector of bytes. These are the most popular choice
-  // when splitting fuzzing input into pieces, as every piece is put into a
-  // separate buffer (i.e. ASan would catch any under-/overflow) and the memory
-  // will be released automatically.
-  template <typename T> std::vector<T> ConsumeBytes(size_t num_bytes);
-  template <typename T>
-  std::vector<T> ConsumeBytesWithTerminator(size_t num_bytes, T terminator = 0);
-  template <typename T> std::vector<T> ConsumeRemainingBytes();
-
-  // Methods returning strings. Use only when you need a std::string or a null
-  // terminated C-string. Otherwise, prefer the methods returning std::vector.
-  std::string ConsumeBytesAsString(size_t num_bytes);
-  std::string ConsumeRandomLengthString(size_t max_length);
-  std::string ConsumeRandomLengthString();
-  std::string ConsumeRemainingBytesAsString();
-
-  // Methods returning integer values.
-  template <typename T> T ConsumeIntegral();
-  template <typename T> T ConsumeIntegralInRange(T min, T max);
-
-  // Methods returning floating point values.
-  template <typename T> T ConsumeFloatingPoint();
-  template <typename T> T ConsumeFloatingPointInRange(T min, T max);
-
-  // 0 <= return value <= 1.
-  template <typename T> T ConsumeProbability();
-
-  bool ConsumeBool();
-
-  // Returns a value chosen from the given enum.
-  template <typename T> T ConsumeEnum();
-
-  // Returns a value from the given array.
-  template <typename T, size_t size> T PickValueInArray(const T (&array)[size]);
-  template <typename T> T PickValueInArray(std::initializer_list<const T> list);
-
-  // Writes data to the given destination and returns number of bytes written.
-  size_t ConsumeData(void *destination, size_t num_bytes);
-
-  // Reports the remaining bytes available for fuzzed input.
-  size_t remaining_bytes() { return remaining_bytes_; }
-
- private:
-  FuzzedDataProvider(const FuzzedDataProvider &) = delete;
-  FuzzedDataProvider &operator=(const FuzzedDataProvider &) = delete;
-
-  void CopyAndAdvance(void *destination, size_t num_bytes);
-
-  void Advance(size_t num_bytes);
-
-  template <typename T>
-  std::vector<T> ConsumeBytes(size_t size, size_t num_bytes);
-
-  template <typename TS, typename TU> TS ConvertUnsignedToSigned(TU value);
-
-  const uint8_t *data_ptr_;
-  size_t remaining_bytes_;
+class FuzzedDataProvider
+{
+public:
+    // |data| is an array of length |size| that the FuzzedDataProvider wraps to
+    // provide more granular access. |data| must outlive the FuzzedDataProvider.
+    FuzzedDataProvider(const uint8_t *data, size_t size) : data_ptr_(data), remaining_bytes_(size) { }
+    ~FuzzedDataProvider() = default;
+
+    // See the implementation below (after the class definition) for more verbose
+    // comments for each of the methods.
+
+    // Methods returning std::vector of bytes. These are the most popular choice
+    // when splitting fuzzing input into pieces, as every piece is put into a
+    // separate buffer (i.e. ASan would catch any under-/overflow) and the memory
+    // will be released automatically.
+    template<typename T>
+    std::vector<T> ConsumeBytes(size_t num_bytes);
+    template<typename T>
+    std::vector<T> ConsumeBytesWithTerminator(size_t num_bytes, T terminator = 0);
+    template<typename T>
+    std::vector<T> ConsumeRemainingBytes();
+
+    // Methods returning strings. Use only when you need a std::string or a null
+    // terminated C-string. Otherwise, prefer the methods returning std::vector.
+    std::string ConsumeBytesAsString(size_t num_bytes);
+    std::string ConsumeRandomLengthString(size_t max_length);
+    std::string ConsumeRandomLengthString();
+    std::string ConsumeRemainingBytesAsString();
+
+    // Methods returning integer values.
+    template<typename T>
+    T ConsumeIntegral();
+    template<typename T>
+    T ConsumeIntegralInRange(T min, T max);
+
+    // Methods returning floating point values.
+    template<typename T>
+    T ConsumeFloatingPoint();
+    template<typename T>
+    T ConsumeFloatingPointInRange(T min, T max);
+
+    // 0 <= return value <= 1.
+    template<typename T>
+    T ConsumeProbability();
+
+    bool ConsumeBool();
+
+    // Returns a value chosen from the given enum.
+    template<typename T>
+    T ConsumeEnum();
+
+    // Returns a value from the given array.
+    template<typename T, size_t size>
+    T PickValueInArray(const T (&array)[size]);
+    template<typename T>
+    T PickValueInArray(std::initializer_list<const T> list);
+
+    // Writes data to the given destination and returns number of bytes written.
+    size_t ConsumeData(void *destination, size_t num_bytes);
+
+    // Reports the remaining bytes available for fuzzed input.
+    size_t remaining_bytes() { return remaining_bytes_; }
+
+private:
+    FuzzedDataProvider(const FuzzedDataProvider &) = delete;
+    FuzzedDataProvider &operator=(const FuzzedDataProvider &) = delete;
+
+    void CopyAndAdvance(void *destination, size_t num_bytes);
+
+    void Advance(size_t num_bytes);
+
+    template<typename T>
+    std::vector<T> ConsumeBytes(size_t size, size_t num_bytes);
+
+    template<typename TS, typename TU>
+    TS ConvertUnsignedToSigned(TU value);
+
+    const uint8_t *data_ptr_;
+    size_t remaining_bytes_;
 };
 
 // Returns a std::vector containing |num_bytes| of input data. If fewer than
 // |num_bytes| of data remain, returns a shorter std::vector containing all
 // of the data that's left. Can be used with any byte sized type, such as
 // char, unsigned char, uint8_t, etc.
-template <typename T>
-std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t num_bytes) {
-  num_bytes = std::min(num_bytes, remaining_bytes_);
-  return ConsumeBytes<T>(num_bytes, num_bytes);
+template<typename T>
+std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t num_bytes)
+{
+    num_bytes = std::min(num_bytes, remaining_bytes_);
+    return ConsumeBytes<T>(num_bytes, num_bytes);
 }
 
 // Similar to |ConsumeBytes|, but also appends the terminator value at the end
 // of the resulting vector. Useful, when a mutable null-terminated C-string is
 // needed, for example. But that is a rare case. Better avoid it, if possible,
 // and prefer using |ConsumeBytes| or |ConsumeBytesAsString| methods.
-template <typename T>
-std::vector<T> FuzzedDataProvider::ConsumeBytesWithTerminator(size_t num_bytes,
-                                                              T terminator) {
-  num_bytes = std::min(num_bytes, remaining_bytes_);
-  std::vector<T> result = ConsumeBytes<T>(num_bytes + 1, num_bytes);
-  result.back() = terminator;
-  return result;
+template<typename T>
+std::vector<T> FuzzedDataProvider::ConsumeBytesWithTerminator(size_t num_bytes, T terminator)
+{
+    num_bytes = std::min(num_bytes, remaining_bytes_);
+    std::vector<T> result = ConsumeBytes<T>(num_bytes + 1, num_bytes);
+    result.back() = terminator;
+    return result;
 }
 
 // Returns a std::vector containing all remaining bytes of the input data.
-template <typename T>
-std::vector<T> FuzzedDataProvider::ConsumeRemainingBytes() {
-  return ConsumeBytes<T>(remaining_bytes_);
+template<typename T>
+std::vector<T> FuzzedDataProvider::ConsumeRemainingBytes()
+{
+    return ConsumeBytes<T>(remaining_bytes_);
 }
 
 // Returns a std::string containing |num_bytes| of input data. Using this and
 // |.c_str()| on the resulting string is the best way to get an immutable
 // null-terminated C string. If fewer than |num_bytes| of data remain, returns
 // a shorter std::string containing all of the data that's left.
-inline std::string FuzzedDataProvider::ConsumeBytesAsString(size_t num_bytes) {
-  static_assert(sizeof(std::string::value_type) == sizeof(uint8_t),
-                "ConsumeBytesAsString cannot convert the data to a string.");
-
-  num_bytes = std::min(num_bytes, remaining_bytes_);
-  std::string result(
-      reinterpret_cast<const std::string::value_type *>(data_ptr_), num_bytes);
-  Advance(num_bytes);
-  return result;
+inline std::string FuzzedDataProvider::ConsumeBytesAsString(size_t num_bytes)
+{
+    static_assert(sizeof(std::string::value_type) == sizeof(uint8_t), "ConsumeBytesAsString cannot convert the data to a string.");
+
+    num_bytes = std::min(num_bytes, remaining_bytes_);
+    std::string result(reinterpret_cast<const std::string::value_type *>(data_ptr_), num_bytes);
+    Advance(num_bytes);
+    return result;
 }
 
 // Returns a std::string of length from 0 to |max_length|. When it runs out of
 // input data, returns what remains of the input. Designed to be more stable
 // with respect to a fuzzer inserting characters than just picking a random
 // length and then consuming that many bytes with |ConsumeBytes|.
-inline std::string
-FuzzedDataProvider::ConsumeRandomLengthString(size_t max_length) {
-  // Reads bytes from the start of |data_ptr_|. Maps "\\" to "\", and maps "\"
-  // followed by anything else to the end of the string. As a result of this
-  // logic, a fuzzer can insert characters into the string, and the string
-  // will be lengthened to include those new characters, resulting in a more
-  // stable fuzzer than picking the length of a string independently from
-  // picking its contents.
-  std::string result;
-
-  // Reserve the anticipated capaticity to prevent several reallocations.
-  result.reserve(std::min(max_length, remaining_bytes_));
-  for (size_t i = 0; i < max_length && remaining_bytes_ != 0; ++i) {
-    char next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
-    Advance(1);
-    if (next == '\\' && remaining_bytes_ != 0) {
-      next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
-      Advance(1);
-      if (next != '\\')
-        break;
+inline std::string FuzzedDataProvider::ConsumeRandomLengthString(size_t max_length)
+{
+    // Reads bytes from the start of |data_ptr_|. Maps "\\" to "\", and maps "\"
+    // followed by anything else to the end of the string. As a result of this
+    // logic, a fuzzer can insert characters into the string, and the string
+    // will be lengthened to include those new characters, resulting in a more
+    // stable fuzzer than picking the length of a string independently from
+    // picking its contents.
+    std::string result;
+
+    // Reserve the anticipated capaticity to prevent several reallocations.
+    result.reserve(std::min(max_length, remaining_bytes_));
+    for (size_t i = 0; i < max_length && remaining_bytes_ != 0; ++i) {
+        char next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
+        Advance(1);
+        if (next == '\\' && remaining_bytes_ != 0) {
+            next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
+            Advance(1);
+            if (next != '\\')
+                break;
+        }
+        result += next;
     }
-    result += next;
-  }
 
-  result.shrink_to_fit();
-  return result;
+    result.shrink_to_fit();
+    return result;
 }
 
 // Returns a std::string of length from 0 to |remaining_bytes_|.
-inline std::string FuzzedDataProvider::ConsumeRandomLengthString() {
-  return ConsumeRandomLengthString(remaining_bytes_);
+inline std::string FuzzedDataProvider::ConsumeRandomLengthString()
+{
+    return ConsumeRandomLengthString(remaining_bytes_);
 }
 
 // Returns a std::string containing all remaining bytes of the input data.
 // Prefer using |ConsumeRemainingBytes| unless you actually need a std::string
 // object.
-inline std::string FuzzedDataProvider::ConsumeRemainingBytesAsString() {
-  return ConsumeBytesAsString(remaining_bytes_);
+inline std::string FuzzedDataProvider::ConsumeRemainingBytesAsString()
+{
+    return ConsumeBytesAsString(remaining_bytes_);
 }
 
 // Returns a number in the range [Type's min, Type's max]. The value might
 // not be uniformly distributed in the given range. If there's no input data
 // left, always returns |min|.
-template <typename T> T FuzzedDataProvider::ConsumeIntegral() {
-  return ConsumeIntegralInRange(std::numeric_limits<T>::min(),
-                                std::numeric_limits<T>::max());
+template<typename T>
+T FuzzedDataProvider::ConsumeIntegral()
+{
+    return ConsumeIntegralInRange(std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
 }
 
 // Returns a number in the range [min, max] by consuming bytes from the
 // input data. The value might not be uniformly distributed in the given
 // range. If there's no input data left, always returns |min|. |min| must
 // be less than or equal to |max|.
-template <typename T>
-T FuzzedDataProvider::ConsumeIntegralInRange(T min, T max) {
-  static_assert(std::is_integral<T>::value, "An integral type is required.");
-  static_assert(sizeof(T) <= sizeof(uint64_t), "Unsupported integral type.");
-
-  if (min > max)
-    abort();
-
-  // Use the biggest type possible to hold the range and the result.
-  uint64_t range = static_cast<uint64_t>(max) - min;
-  uint64_t result = 0;
-  size_t offset = 0;
-
-  while (offset < sizeof(T) * CHAR_BIT && (range >> offset) > 0 &&
-         remaining_bytes_ != 0) {
-    // Pull bytes off the end of the seed data. Experimentally, this seems to
-    // allow the fuzzer to more easily explore the input space. This makes
-    // sense, since it works by modifying inputs that caused new code to run,
-    // and this data is often used to encode length of data read by
-    // |ConsumeBytes|. Separating out read lengths makes it easier modify the
-    // contents of the data that is actually read.
-    --remaining_bytes_;
-    result = (result << CHAR_BIT) | data_ptr_[remaining_bytes_];
-    offset += CHAR_BIT;
-  }
-
-  // Avoid division by 0, in case |range + 1| results in overflow.
-  if (range != std::numeric_limits<decltype(range)>::max())
-    result = result % (range + 1);
-
-  return static_cast<T>(min + result);
+template<typename T>
+T FuzzedDataProvider::ConsumeIntegralInRange(T min, T max)
+{
+    static_assert(std::is_integral<T>::value, "An integral type is required.");
+    static_assert(sizeof(T) <= sizeof(uint64_t), "Unsupported integral type.");
+
+    if (min > max)
+        abort();
+
+    // Use the biggest type possible to hold the range and the result.
+    uint64_t range = static_cast<uint64_t>(max) - min;
+    uint64_t result = 0;
+    size_t offset = 0;
+
+    while (offset < sizeof(T) * CHAR_BIT && (range >> offset) > 0 && remaining_bytes_ != 0) {
+        // Pull bytes off the end of the seed data. Experimentally, this seems to
+        // allow the fuzzer to more easily explore the input space. This makes
+        // sense, since it works by modifying inputs that caused new code to run,
+        // and this data is often used to encode length of data read by
+        // |ConsumeBytes|. Separating out read lengths makes it easier modify the
+        // contents of the data that is actually read.
+        --remaining_bytes_;
+        result = (result << CHAR_BIT) | data_ptr_[remaining_bytes_];
+        offset += CHAR_BIT;
+    }
+
+    // Avoid division by 0, in case |range + 1| results in overflow.
+    if (range != std::numeric_limits<decltype(range)>::max())
+        result = result % (range + 1);
+
+    return static_cast<T>(min + result);
 }
 
 // Returns a floating point value in the range [Type's lowest, Type's max] by
 // consuming bytes from the input data. If there's no input data left, always
 // returns approximately 0.
-template <typename T> T FuzzedDataProvider::ConsumeFloatingPoint() {
-  return ConsumeFloatingPointInRange<T>(std::numeric_limits<T>::lowest(),
-                                        std::numeric_limits<T>::max());
+template<typename T>
+T FuzzedDataProvider::ConsumeFloatingPoint()
+{
+    return ConsumeFloatingPointInRange<T>(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max());
 }
 
 // Returns a floating point value in the given range by consuming bytes from
 // the input data. If there's no input data left, returns |min|. Note that
 // |min| must be less than or equal to |max|.
-template <typename T>
-T FuzzedDataProvider::ConsumeFloatingPointInRange(T min, T max) {
-  if (min > max)
-    abort();
-
-  T range = .0;
-  T result = min;
-  constexpr T zero(.0);
-  if (max > zero && min < zero && max > min + std::numeric_limits<T>::max()) {
-    // The diff |max - min| would overflow the given floating point type. Use
-    // the half of the diff as the range and consume a bool to decide whether
-    // the result is in the first of the second part of the diff.
-    range = (max / 2.0) - (min / 2.0);
-    if (ConsumeBool()) {
-      result += range;
+template<typename T>
+T FuzzedDataProvider::ConsumeFloatingPointInRange(T min, T max)
+{
+    if (min > max)
+        abort();
+
+    T range = .0;
+    T result = min;
+    constexpr T zero(.0);
+    if (max > zero && min < zero && max > min + std::numeric_limits<T>::max()) {
+        // The diff |max - min| would overflow the given floating point type. Use
+        // the half of the diff as the range and consume a bool to decide whether
+        // the result is in the first of the second part of the diff.
+        range = (max / 2.0) - (min / 2.0);
+        if (ConsumeBool()) {
+            result += range;
+        }
+    } else {
+        range = max - min;
     }
-  } else {
-    range = max - min;
-  }
 
-  return result + range * ConsumeProbability<T>();
+    return result + range * ConsumeProbability<T>();
 }
 
 // Returns a floating point number in the range [0.0, 1.0]. If there's no
 // input data left, always returns 0.
-template <typename T> T FuzzedDataProvider::ConsumeProbability() {
-  static_assert(std::is_floating_point<T>::value,
-                "A floating point type is required.");
-
-  // Use different integral types for different floating point types in order
-  // to provide better density of the resulting values.
-  using IntegralType =
-      typename std::conditional<(sizeof(T) <= sizeof(uint32_t)), uint32_t,
-                                uint64_t>::type;
-
-  T result = static_cast<T>(ConsumeIntegral<IntegralType>());
-  result /= static_cast<T>(std::numeric_limits<IntegralType>::max());
-  return result;
+template<typename T>
+T FuzzedDataProvider::ConsumeProbability()
+{
+    static_assert(std::is_floating_point<T>::value, "A floating point type is required.");
+
+    // Use different integral types for different floating point types in order
+    // to provide better density of the resulting values.
+    using IntegralType = typename std::conditional<(sizeof(T) <= sizeof(uint32_t)), uint32_t, uint64_t>::type;
+
+    T result = static_cast<T>(ConsumeIntegral<IntegralType>());
+    result /= static_cast<T>(std::numeric_limits<IntegralType>::max());
+    return result;
 }
 
 // Reads one byte and returns a bool, or false when no data remains.
-inline bool FuzzedDataProvider::ConsumeBool() {
-  return 1 & ConsumeIntegral<uint8_t>();
+inline bool FuzzedDataProvider::ConsumeBool()
+{
+    return 1 & ConsumeIntegral<uint8_t>();
 }
 
 // Returns an enum value. The enum must start at 0 and be contiguous. It must
 // also contain |kMaxValue| aliased to its largest (inclusive) value. Such as:
 // enum class Foo { SomeValue, OtherValue, kMaxValue = OtherValue };
-template <typename T> T FuzzedDataProvider::ConsumeEnum() {
-  static_assert(std::is_enum<T>::value, "|T| must be an enum type.");
-  return static_cast<T>(
-      ConsumeIntegralInRange<uint32_t>(0, static_cast<uint32_t>(T::kMaxValue)));
+template<typename T>
+T FuzzedDataProvider::ConsumeEnum()
+{
+    static_assert(std::is_enum<T>::value, "|T| must be an enum type.");
+    return static_cast<T>(ConsumeIntegralInRange<uint32_t>(0, static_cast<uint32_t>(T::kMaxValue)));
 }
 
 // Returns a copy of the value selected from the given fixed-size |array|.
-template <typename T, size_t size>
-T FuzzedDataProvider::PickValueInArray(const T (&array)[size]) {
-  static_assert(size > 0, "The array must be non empty.");
-  return array[ConsumeIntegralInRange<size_t>(0, size - 1)];
+template<typename T, size_t size>
+T FuzzedDataProvider::PickValueInArray(const T (&array)[size])
+{
+    static_assert(size > 0, "The array must be non empty.");
+    return array[ConsumeIntegralInRange<size_t>(0, size - 1)];
 }
 
-template <typename T>
-T FuzzedDataProvider::PickValueInArray(std::initializer_list<const T> list) {
-  // TODO(Dor1s): switch to static_assert once C++14 is allowed.
-  if (!list.size())
-    abort();
+template<typename T>
+T FuzzedDataProvider::PickValueInArray(std::initializer_list<const T> list)
+{
+    // TODO(Dor1s): switch to static_assert once C++14 is allowed.
+    if (!list.size())
+        abort();
 
-  return *(list.begin() + ConsumeIntegralInRange<size_t>(0, list.size() - 1));
+    return *(list.begin() + ConsumeIntegralInRange<size_t>(0, list.size() - 1));
 }
 
 // Writes |num_bytes| of input data to the given destination pointer. If there
@@ -316,72 +336,74 @@ T FuzzedDataProvider::PickValueInArray(std::initializer_list<const T> list) {
 // In general, it's better to avoid using this function, but it may be useful
 // in cases when it's necessary to fill a certain buffer or object with
 // fuzzing data.
-inline size_t FuzzedDataProvider::ConsumeData(void *destination,
-                                              size_t num_bytes) {
-  num_bytes = std::min(num_bytes, remaining_bytes_);
-  CopyAndAdvance(destination, num_bytes);
-  return num_bytes;
+inline size_t FuzzedDataProvider::ConsumeData(void *destination, size_t num_bytes)
+{
+    num_bytes = std::min(num_bytes, remaining_bytes_);
+    CopyAndAdvance(destination, num_bytes);
+    return num_bytes;
 }
 
 // Private methods.
-inline void FuzzedDataProvider::CopyAndAdvance(void *destination,
-                                               size_t num_bytes) {
-  std::memcpy(destination, data_ptr_, num_bytes);
-  Advance(num_bytes);
+inline void FuzzedDataProvider::CopyAndAdvance(void *destination, size_t num_bytes)
+{
+    std::memcpy(destination, data_ptr_, num_bytes);
+    Advance(num_bytes);
 }
 
-inline void FuzzedDataProvider::Advance(size_t num_bytes) {
-  if (num_bytes > remaining_bytes_)
-    abort();
+inline void FuzzedDataProvider::Advance(size_t num_bytes)
+{
+    if (num_bytes > remaining_bytes_)
+        abort();
 
-  data_ptr_ += num_bytes;
-  remaining_bytes_ -= num_bytes;
+    data_ptr_ += num_bytes;
+    remaining_bytes_ -= num_bytes;
 }
 
-template <typename T>
-std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t size, size_t num_bytes) {
-  static_assert(sizeof(T) == sizeof(uint8_t), "Incompatible data type.");
-
-  // The point of using the size-based constructor below is to increase the
-  // odds of having a vector object with capacity being equal to the length.
-  // That part is always implementation specific, but at least both libc++ and
-  // libstdc++ allocate the requested number of bytes in that constructor,
-  // which seems to be a natural choice for other implementations as well.
-  // To increase the odds even more, we also call |shrink_to_fit| below.
-  std::vector<T> result(size);
-  if (size == 0) {
-    if (num_bytes != 0)
-      abort();
-    return result;
-  }
+template<typename T>
+std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t size, size_t num_bytes)
+{
+    static_assert(sizeof(T) == sizeof(uint8_t), "Incompatible data type.");
+
+    // The point of using the size-based constructor below is to increase the
+    // odds of having a vector object with capacity being equal to the length.
+    // That part is always implementation specific, but at least both libc++ and
+    // libstdc++ allocate the requested number of bytes in that constructor,
+    // which seems to be a natural choice for other implementations as well.
+    // To increase the odds even more, we also call |shrink_to_fit| below.
+    std::vector<T> result(size);
+    if (size == 0) {
+        if (num_bytes != 0)
+            abort();
+        return result;
+    }
 
-  CopyAndAdvance(result.data(), num_bytes);
+    CopyAndAdvance(result.data(), num_bytes);
 
-  // Even though |shrink_to_fit| is also implementation specific, we expect it
-  // to provide an additional assurance in case vector's constructor allocated
-  // a buffer which is larger than the actual amount of data we put inside it.
-  result.shrink_to_fit();
-  return result;
+    // Even though |shrink_to_fit| is also implementation specific, we expect it
+    // to provide an additional assurance in case vector's constructor allocated
+    // a buffer which is larger than the actual amount of data we put inside it.
+    result.shrink_to_fit();
+    return result;
 }
 
-template <typename TS, typename TU>
-TS FuzzedDataProvider::ConvertUnsignedToSigned(TU value) {
-  static_assert(sizeof(TS) == sizeof(TU), "Incompatible data types.");
-  static_assert(!std::numeric_limits<TU>::is_signed,
-                "Source type must be unsigned.");
-
-  // TODO(Dor1s): change to `if constexpr` once C++17 becomes mainstream.
-  if (std::numeric_limits<TS>::is_modulo)
-    return static_cast<TS>(value);
-
-  // Avoid using implementation-defined unsigned to signed conversions.
-  // To learn more, see https://stackoverflow.com/questions/13150449.
-  if (value <= std::numeric_limits<TS>::max()) {
-    return static_cast<TS>(value);
-  } else {
-    constexpr auto TS_min = std::numeric_limits<TS>::min();
-    return TS_min + static_cast<char>(value - TS_min);
-  }
+template<typename TS, typename TU>
+TS FuzzedDataProvider::ConvertUnsignedToSigned(TU value)
+{
+    static_assert(sizeof(TS) == sizeof(TU), "Incompatible data types.");
+    static_assert(!std::numeric_limits<TU>::is_signed, "Source type must be unsigned.");
+
+    // TODO(Dor1s): change to `if constexpr` once C++17 becomes mainstream.
+    if (std::numeric_limits<TS>::is_modulo)
+        return static_cast<TS>(value);
+
+    // Avoid using implementation-defined unsigned to signed conversions.
+    // To learn more, see https://stackoverflow.com/questions/13150449.
+    if (value <= std::numeric_limits<TS>::max()) {
+        return static_cast<TS>(value);
+    } else {
+        constexpr auto TS_min = std::numeric_limits<TS>::min();
+        return TS_min + static_cast<char>(value - TS_min);
+    }
 }
 
 #endif // LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
diff --git a/cpp/tests/fuzzing/doc_fuzzer.cc b/cpp/tests/fuzzing/doc_fuzzer.cc
index 720909d3..b8dd957f 100644
--- a/cpp/tests/fuzzing/doc_fuzzer.cc
+++ b/cpp/tests/fuzzing/doc_fuzzer.cc
@@ -34,12 +34,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     doc->set_subject(poppler::ustring::from_latin1(in_sub));
     doc->set_title(poppler::ustring::from_latin1(in_title));
 
-    doc->set_author(poppler::ustring::from_utf8((const char*)data,size));
-    doc->set_creator(poppler::ustring::from_utf8((const char*)data,size));
-    doc->set_keywords(poppler::ustring::from_utf8((const char*)data,size));
-    doc->set_producer(poppler::ustring::from_utf8((const char*)data,size));
-    doc->set_subject(poppler::ustring::from_utf8((const char*)data,size));
-    doc->set_title(poppler::ustring::from_utf8((const char*)data,size));
+    doc->set_author(poppler::ustring::from_utf8((const char *)data, size));
+    doc->set_creator(poppler::ustring::from_utf8((const char *)data, size));
+    doc->set_keywords(poppler::ustring::from_utf8((const char *)data, size));
+    doc->set_producer(poppler::ustring::from_utf8((const char *)data, size));
+    doc->set_subject(poppler::ustring::from_utf8((const char *)data, size));
+    doc->set_title(poppler::ustring::from_utf8((const char *)data, size));
 
     delete doc;
     return 0;
diff --git a/cpp/tests/fuzzing/fuzzer_temp_file.h b/cpp/tests/fuzzing/fuzzer_temp_file.h
index fe25caba..d0568ac5 100644
--- a/cpp/tests/fuzzing/fuzzer_temp_file.h
+++ b/cpp/tests/fuzzing/fuzzer_temp_file.h
@@ -26,56 +26,57 @@
 
 // Pure-C interface for creating and cleaning up temporary files.
 
-static char* fuzzer_get_tmpfile(const uint8_t* data, size_t size) {
-  char* filename_buffer = strdup("/tmp/generate_temporary_file.XXXXXX");
-  if (!filename_buffer) {
-    perror("Failed to allocate file name buffer.");
-    abort();
-  }
-  const int file_descriptor = mkstemp(filename_buffer);
-  if (file_descriptor < 0) {
-    perror("Failed to make temporary file.");
-    abort();
-  }
-  FILE* file = fdopen(file_descriptor, "wb");
-  if (!file) {
-    perror("Failed to open file descriptor.");
-    close(file_descriptor);
-    abort();
-  }
-  const size_t bytes_written = fwrite(data, sizeof(uint8_t), size, file);
-  if (bytes_written < size) {
-    close(file_descriptor);
-    fprintf(stderr, "Failed to write all bytes to file (%zu out of %zu)",
-            bytes_written, size);
-    abort();
-  }
-  fclose(file);
-  return filename_buffer;
+static char *fuzzer_get_tmpfile(const uint8_t *data, size_t size)
+{
+    char *filename_buffer = strdup("/tmp/generate_temporary_file.XXXXXX");
+    if (!filename_buffer) {
+        perror("Failed to allocate file name buffer.");
+        abort();
+    }
+    const int file_descriptor = mkstemp(filename_buffer);
+    if (file_descriptor < 0) {
+        perror("Failed to make temporary file.");
+        abort();
+    }
+    FILE *file = fdopen(file_descriptor, "wb");
+    if (!file) {
+        perror("Failed to open file descriptor.");
+        close(file_descriptor);
+        abort();
+    }
+    const size_t bytes_written = fwrite(data, sizeof(uint8_t), size, file);
+    if (bytes_written < size) {
+        close(file_descriptor);
+        fprintf(stderr, "Failed to write all bytes to file (%zu out of %zu)", bytes_written, size);
+        abort();
+    }
+    fclose(file);
+    return filename_buffer;
 }
 
-static void fuzzer_release_tmpfile(char* filename) {
-  if (unlink(filename) != 0) {
-    perror("WARNING: Failed to delete temporary file.");
-  }
-  free(filename);
+static void fuzzer_release_tmpfile(char *filename)
+{
+    if (unlink(filename) != 0) {
+        perror("WARNING: Failed to delete temporary file.");
+    }
+    free(filename);
 }
 
 // C++ RAII object for creating temporary files.
 
 #ifdef __cplusplus
-class FuzzerTemporaryFile {
- public:
-  FuzzerTemporaryFile(const uint8_t* data, size_t size)
-      : filename_(fuzzer_get_tmpfile(data, size)) {}
+class FuzzerTemporaryFile
+{
+public:
+    FuzzerTemporaryFile(const uint8_t *data, size_t size) : filename_(fuzzer_get_tmpfile(data, size)) { }
 
-  ~FuzzerTemporaryFile() { fuzzer_release_tmpfile(filename_); }
+    ~FuzzerTemporaryFile() { fuzzer_release_tmpfile(filename_); }
 
-  const char* filename() const { return filename_; }
+    const char *filename() const { return filename_; }
 
- private:
-  char* filename_;
+private:
+    char *filename_;
 };
 #endif
 
-#endif  // FUZZER_TEMP_FILE_H_
+#endif // FUZZER_TEMP_FILE_H_
diff --git a/cpp/tests/fuzzing/page_label_fuzzer.cc b/cpp/tests/fuzzing/page_label_fuzzer.cc
index 510ca40d..19106036 100644
--- a/cpp/tests/fuzzing/page_label_fuzzer.cc
+++ b/cpp/tests/fuzzing/page_label_fuzzer.cc
@@ -19,7 +19,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 
     poppler::page_renderer r;
     for (int i = 0; i < doc->pages(); i++) {
-        poppler::ustring label = poppler::ustring::from_utf8((const char*)data, size);
+        poppler::ustring label = poppler::ustring::from_utf8((const char *)data, size);
         poppler::page *p = doc->create_page(label);
         if (!p) {
             continue;
diff --git a/cpp/tests/fuzzing/page_search_fuzzer.cc b/cpp/tests/fuzzing/page_search_fuzzer.cc
index 24a4e23c..6427976c 100644
--- a/cpp/tests/fuzzing/page_search_fuzzer.cc
+++ b/cpp/tests/fuzzing/page_search_fuzzer.cc
@@ -24,7 +24,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
             continue;
         }
         poppler::rectf rect = p->page_rect();
-        poppler::ustring text = poppler::ustring::from_utf8((const char*)data, size);
+        poppler::ustring text = poppler::ustring::from_utf8((const char *)data, size);
         p->search(text, rect, poppler::page::search_from_top, poppler::case_insensitive, poppler::rotate_0);
         r.render_page(p);
         delete p;
diff --git a/glib/tests/fuzzing/annot_fuzzer.c b/glib/tests/fuzzing/annot_fuzzer.c
index ad2f23d6..db3f0e49 100644
--- a/glib/tests/fuzzing/annot_fuzzer.c
+++ b/glib/tests/fuzzing/annot_fuzzer.c
@@ -5,7 +5,8 @@
 
 #include "fuzzer_temp_file.h"
 
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
     GError *err = NULL;
     PopplerDocument *doc;
     PopplerPage *page;
diff --git a/glib/tests/fuzzing/doc_attr_fuzzer.c b/glib/tests/fuzzing/doc_attr_fuzzer.c
index 7fe0ee59..1b62884b 100644
--- a/glib/tests/fuzzing/doc_attr_fuzzer.c
+++ b/glib/tests/fuzzing/doc_attr_fuzzer.c
@@ -1,7 +1,8 @@
 #include <stdint.h>
 #include <poppler.h>
 
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
     GError *err = NULL;
     PopplerDocument *doc;
     PopplerPage *page;
diff --git a/glib/tests/fuzzing/find_text_fuzzer.c b/glib/tests/fuzzing/find_text_fuzzer.c
index 207704a3..744f0051 100644
--- a/glib/tests/fuzzing/find_text_fuzzer.c
+++ b/glib/tests/fuzzing/find_text_fuzzer.c
@@ -1,7 +1,8 @@
 #include <stdint.h>
 #include <poppler.h>
 
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
     GError *err = NULL;
     PopplerDocument *doc;
     PopplerPage *page;
diff --git a/glib/tests/fuzzing/fuzzer_temp_file.h b/glib/tests/fuzzing/fuzzer_temp_file.h
index fe25caba..d0568ac5 100644
--- a/glib/tests/fuzzing/fuzzer_temp_file.h
+++ b/glib/tests/fuzzing/fuzzer_temp_file.h
@@ -26,56 +26,57 @@
 
 // Pure-C interface for creating and cleaning up temporary files.
 
-static char* fuzzer_get_tmpfile(const uint8_t* data, size_t size) {
-  char* filename_buffer = strdup("/tmp/generate_temporary_file.XXXXXX");
-  if (!filename_buffer) {
-    perror("Failed to allocate file name buffer.");
-    abort();
-  }
-  const int file_descriptor = mkstemp(filename_buffer);
-  if (file_descriptor < 0) {
-    perror("Failed to make temporary file.");
-    abort();
-  }
-  FILE* file = fdopen(file_descriptor, "wb");
-  if (!file) {
-    perror("Failed to open file descriptor.");
-    close(file_descriptor);
-    abort();
-  }
-  const size_t bytes_written = fwrite(data, sizeof(uint8_t), size, file);
-  if (bytes_written < size) {
-    close(file_descriptor);
-    fprintf(stderr, "Failed to write all bytes to file (%zu out of %zu)",
-            bytes_written, size);
-    abort();
-  }
-  fclose(file);
-  return filename_buffer;
+static char *fuzzer_get_tmpfile(const uint8_t *data, size_t size)
+{
+    char *filename_buffer = strdup("/tmp/generate_temporary_file.XXXXXX");
+    if (!filename_buffer) {
+        perror("Failed to allocate file name buffer.");
+        abort();
+    }
+    const int file_descriptor = mkstemp(filename_buffer);
+    if (file_descriptor < 0) {
+        perror("Failed to make temporary file.");
+        abort();
+    }
+    FILE *file = fdopen(file_descriptor, "wb");
+    if (!file) {
+        perror("Failed to open file descriptor.");
+        close(file_descriptor);
+        abort();
+    }
+    const size_t bytes_written = fwrite(data, sizeof(uint8_t), size, file);
+    if (bytes_written < size) {
+        close(file_descriptor);
+        fprintf(stderr, "Failed to write all bytes to file (%zu out of %zu)", bytes_written, size);
+        abort();
+    }
+    fclose(file);
+    return filename_buffer;
 }
 
-static void fuzzer_release_tmpfile(char* filename) {
-  if (unlink(filename) != 0) {
-    perror("WARNING: Failed to delete temporary file.");
-  }
-  free(filename);
+static void fuzzer_release_tmpfile(char *filename)
+{
+    if (unlink(filename) != 0) {
+        perror("WARNING: Failed to delete temporary file.");
+    }
+    free(filename);
 }
 
 // C++ RAII object for creating temporary files.
 
 #ifdef __cplusplus
-class FuzzerTemporaryFile {
- public:
-  FuzzerTemporaryFile(const uint8_t* data, size_t size)
-      : filename_(fuzzer_get_tmpfile(data, size)) {}
+class FuzzerTemporaryFile
+{
+public:
+    FuzzerTemporaryFile(const uint8_t *data, size_t size) : filename_(fuzzer_get_tmpfile(data, size)) { }
 
-  ~FuzzerTemporaryFile() { fuzzer_release_tmpfile(filename_); }
+    ~FuzzerTemporaryFile() { fuzzer_release_tmpfile(filename_); }
 
-  const char* filename() const { return filename_; }
+    const char *filename() const { return filename_; }
 
- private:
-  char* filename_;
+private:
+    char *filename_;
 };
 #endif
 
-#endif  // FUZZER_TEMP_FILE_H_
+#endif // FUZZER_TEMP_FILE_H_
diff --git a/glib/tests/fuzzing/label_fuzzer.c b/glib/tests/fuzzing/label_fuzzer.c
index ee417a55..5475184e 100644
--- a/glib/tests/fuzzing/label_fuzzer.c
+++ b/glib/tests/fuzzing/label_fuzzer.c
@@ -1,7 +1,8 @@
 #include <stdint.h>
 #include <poppler.h>
 
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
     GError *err = NULL;
     PopplerDocument *doc;
     PopplerPage *page;
diff --git a/glib/tests/fuzzing/pdf_draw_fuzzer.c b/glib/tests/fuzzing/pdf_draw_fuzzer.c
index f0881e16..fffbdb20 100644
--- a/glib/tests/fuzzing/pdf_draw_fuzzer.c
+++ b/glib/tests/fuzzing/pdf_draw_fuzzer.c
@@ -5,7 +5,8 @@
 
 #include "fuzzer_temp_file.h"
 
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
     GError *err = NULL;
     PopplerDocument *doc;
     PopplerPage *page;
@@ -54,7 +55,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
         if (status != CAIRO_STATUS_SUCCESS) {
             g_object_unref(page);
             continue;
-
         }
         if (hg) {
             cairo_set_source_rgb(cr, 0.6, 0.6, 1.0);
diff --git a/glib/tests/fuzzing/util_fuzzer.c b/glib/tests/fuzzing/util_fuzzer.c
index 752e46d9..01f3c2d4 100644
--- a/glib/tests/fuzzing/util_fuzzer.c
+++ b/glib/tests/fuzzing/util_fuzzer.c
@@ -1,7 +1,8 @@
 #include <stdint.h>
 #include <poppler.h>
 
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
     gsize length;
     poppler_named_dest_from_bytestring(data, size);
     poppler_named_dest_to_bytestring(data, &length);
diff --git a/qt5/tests/fuzzing/FuzzedDataProvider.h b/qt5/tests/fuzzing/FuzzedDataProvider.h
index 83bcd013..1996bcad 100644
--- a/qt5/tests/fuzzing/FuzzedDataProvider.h
+++ b/qt5/tests/fuzzing/FuzzedDataProvider.h
@@ -26,288 +26,308 @@
 
 // In addition to the comments below, the API is also briefly documented at
 // https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider
-class FuzzedDataProvider {
- public:
-  // |data| is an array of length |size| that the FuzzedDataProvider wraps to
-  // provide more granular access. |data| must outlive the FuzzedDataProvider.
-  FuzzedDataProvider(const uint8_t *data, size_t size)
-      : data_ptr_(data), remaining_bytes_(size) {}
-  ~FuzzedDataProvider() = default;
-
-  // See the implementation below (after the class definition) for more verbose
-  // comments for each of the methods.
-
-  // Methods returning std::vector of bytes. These are the most popular choice
-  // when splitting fuzzing input into pieces, as every piece is put into a
-  // separate buffer (i.e. ASan would catch any under-/overflow) and the memory
-  // will be released automatically.
-  template <typename T> std::vector<T> ConsumeBytes(size_t num_bytes);
-  template <typename T>
-  std::vector<T> ConsumeBytesWithTerminator(size_t num_bytes, T terminator = 0);
-  template <typename T> std::vector<T> ConsumeRemainingBytes();
-
-  // Methods returning strings. Use only when you need a std::string or a null
-  // terminated C-string. Otherwise, prefer the methods returning std::vector.
-  std::string ConsumeBytesAsString(size_t num_bytes);
-  std::string ConsumeRandomLengthString(size_t max_length);
-  std::string ConsumeRandomLengthString();
-  std::string ConsumeRemainingBytesAsString();
-
-  // Methods returning integer values.
-  template <typename T> T ConsumeIntegral();
-  template <typename T> T ConsumeIntegralInRange(T min, T max);
-
-  // Methods returning floating point values.
-  template <typename T> T ConsumeFloatingPoint();
-  template <typename T> T ConsumeFloatingPointInRange(T min, T max);
-
-  // 0 <= return value <= 1.
-  template <typename T> T ConsumeProbability();
-
-  bool ConsumeBool();
-
-  // Returns a value chosen from the given enum.
-  template <typename T> T ConsumeEnum();
-
-  // Returns a value from the given array.
-  template <typename T, size_t size> T PickValueInArray(const T (&array)[size]);
-  template <typename T> T PickValueInArray(std::initializer_list<const T> list);
-
-  // Writes data to the given destination and returns number of bytes written.
-  size_t ConsumeData(void *destination, size_t num_bytes);
-
-  // Reports the remaining bytes available for fuzzed input.
-  size_t remaining_bytes() { return remaining_bytes_; }
-
- private:
-  FuzzedDataProvider(const FuzzedDataProvider &) = delete;
-  FuzzedDataProvider &operator=(const FuzzedDataProvider &) = delete;
-
-  void CopyAndAdvance(void *destination, size_t num_bytes);
-
-  void Advance(size_t num_bytes);
-
-  template <typename T>
-  std::vector<T> ConsumeBytes(size_t size, size_t num_bytes);
-
-  template <typename TS, typename TU> TS ConvertUnsignedToSigned(TU value);
-
-  const uint8_t *data_ptr_;
-  size_t remaining_bytes_;
+class FuzzedDataProvider
+{
+public:
+    // |data| is an array of length |size| that the FuzzedDataProvider wraps to
+    // provide more granular access. |data| must outlive the FuzzedDataProvider.
+    FuzzedDataProvider(const uint8_t *data, size_t size) : data_ptr_(data), remaining_bytes_(size) { }
+    ~FuzzedDataProvider() = default;
+
+    // See the implementation below (after the class definition) for more verbose
+    // comments for each of the methods.
+
+    // Methods returning std::vector of bytes. These are the most popular choice
+    // when splitting fuzzing input into pieces, as every piece is put into a
+    // separate buffer (i.e. ASan would catch any under-/overflow) and the memory
+    // will be released automatically.
+    template<typename T>
+    std::vector<T> ConsumeBytes(size_t num_bytes);
+    template<typename T>
+    std::vector<T> ConsumeBytesWithTerminator(size_t num_bytes, T terminator = 0);
+    template<typename T>
+    std::vector<T> ConsumeRemainingBytes();
+
+    // Methods returning strings. Use only when you need a std::string or a null
+    // terminated C-string. Otherwise, prefer the methods returning std::vector.
+    std::string ConsumeBytesAsString(size_t num_bytes);
+    std::string ConsumeRandomLengthString(size_t max_length);
+    std::string ConsumeRandomLengthString();
+    std::string ConsumeRemainingBytesAsString();
+
+    // Methods returning integer values.
+    template<typename T>
+    T ConsumeIntegral();
+    template<typename T>
+    T ConsumeIntegralInRange(T min, T max);
+
+    // Methods returning floating point values.
+    template<typename T>
+    T ConsumeFloatingPoint();
+    template<typename T>
+    T ConsumeFloatingPointInRange(T min, T max);
+
+    // 0 <= return value <= 1.
+    template<typename T>
+    T ConsumeProbability();
+
+    bool ConsumeBool();
+
+    // Returns a value chosen from the given enum.
+    template<typename T>
+    T ConsumeEnum();
+
+    // Returns a value from the given array.
+    template<typename T, size_t size>
+    T PickValueInArray(const T (&array)[size]);
+    template<typename T>
+    T PickValueInArray(std::initializer_list<const T> list);
+
+    // Writes data to the given destination and returns number of bytes written.
+    size_t ConsumeData(void *destination, size_t num_bytes);
+
+    // Reports the remaining bytes available for fuzzed input.
+    size_t remaining_bytes() { return remaining_bytes_; }
+
+private:
+    FuzzedDataProvider(const FuzzedDataProvider &) = delete;
+    FuzzedDataProvider &operator=(const FuzzedDataProvider &) = delete;
+
+    void CopyAndAdvance(void *destination, size_t num_bytes);
+
+    void Advance(size_t num_bytes);
+
+    template<typename T>
+    std::vector<T> ConsumeBytes(size_t size, size_t num_bytes);
+
+    template<typename TS, typename TU>
+    TS ConvertUnsignedToSigned(TU value);
+
+    const uint8_t *data_ptr_;
+    size_t remaining_bytes_;
 };
 
 // Returns a std::vector containing |num_bytes| of input data. If fewer than
 // |num_bytes| of data remain, returns a shorter std::vector containing all
 // of the data that's left. Can be used with any byte sized type, such as
 // char, unsigned char, uint8_t, etc.
-template <typename T>
-std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t num_bytes) {
-  num_bytes = std::min(num_bytes, remaining_bytes_);
-  return ConsumeBytes<T>(num_bytes, num_bytes);
+template<typename T>
+std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t num_bytes)
+{
+    num_bytes = std::min(num_bytes, remaining_bytes_);
+    return ConsumeBytes<T>(num_bytes, num_bytes);
 }
 
 // Similar to |ConsumeBytes|, but also appends the terminator value at the end
 // of the resulting vector. Useful, when a mutable null-terminated C-string is
 // needed, for example. But that is a rare case. Better avoid it, if possible,
 // and prefer using |ConsumeBytes| or |ConsumeBytesAsString| methods.
-template <typename T>
-std::vector<T> FuzzedDataProvider::ConsumeBytesWithTerminator(size_t num_bytes,
-                                                              T terminator) {
-  num_bytes = std::min(num_bytes, remaining_bytes_);
-  std::vector<T> result = ConsumeBytes<T>(num_bytes + 1, num_bytes);
-  result.back() = terminator;
-  return result;
+template<typename T>
+std::vector<T> FuzzedDataProvider::ConsumeBytesWithTerminator(size_t num_bytes, T terminator)
+{
+    num_bytes = std::min(num_bytes, remaining_bytes_);
+    std::vector<T> result = ConsumeBytes<T>(num_bytes + 1, num_bytes);
+    result.back() = terminator;
+    return result;
 }
 
 // Returns a std::vector containing all remaining bytes of the input data.
-template <typename T>
-std::vector<T> FuzzedDataProvider::ConsumeRemainingBytes() {
-  return ConsumeBytes<T>(remaining_bytes_);
+template<typename T>
+std::vector<T> FuzzedDataProvider::ConsumeRemainingBytes()
+{
+    return ConsumeBytes<T>(remaining_bytes_);
 }
 
 // Returns a std::string containing |num_bytes| of input data. Using this and
 // |.c_str()| on the resulting string is the best way to get an immutable
 // null-terminated C string. If fewer than |num_bytes| of data remain, returns
 // a shorter std::string containing all of the data that's left.
-inline std::string FuzzedDataProvider::ConsumeBytesAsString(size_t num_bytes) {
-  static_assert(sizeof(std::string::value_type) == sizeof(uint8_t),
-                "ConsumeBytesAsString cannot convert the data to a string.");
-
-  num_bytes = std::min(num_bytes, remaining_bytes_);
-  std::string result(
-      reinterpret_cast<const std::string::value_type *>(data_ptr_), num_bytes);
-  Advance(num_bytes);
-  return result;
+inline std::string FuzzedDataProvider::ConsumeBytesAsString(size_t num_bytes)
+{
+    static_assert(sizeof(std::string::value_type) == sizeof(uint8_t), "ConsumeBytesAsString cannot convert the data to a string.");
+
+    num_bytes = std::min(num_bytes, remaining_bytes_);
+    std::string result(reinterpret_cast<const std::string::value_type *>(data_ptr_), num_bytes);
+    Advance(num_bytes);
+    return result;
 }
 
 // Returns a std::string of length from 0 to |max_length|. When it runs out of
 // input data, returns what remains of the input. Designed to be more stable
 // with respect to a fuzzer inserting characters than just picking a random
 // length and then consuming that many bytes with |ConsumeBytes|.
-inline std::string
-FuzzedDataProvider::ConsumeRandomLengthString(size_t max_length) {
-  // Reads bytes from the start of |data_ptr_|. Maps "\\" to "\", and maps "\"
-  // followed by anything else to the end of the string. As a result of this
-  // logic, a fuzzer can insert characters into the string, and the string
-  // will be lengthened to include those new characters, resulting in a more
-  // stable fuzzer than picking the length of a string independently from
-  // picking its contents.
-  std::string result;
-
-  // Reserve the anticipated capaticity to prevent several reallocations.
-  result.reserve(std::min(max_length, remaining_bytes_));
-  for (size_t i = 0; i < max_length && remaining_bytes_ != 0; ++i) {
-    char next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
-    Advance(1);
-    if (next == '\\' && remaining_bytes_ != 0) {
-      next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
-      Advance(1);
-      if (next != '\\')
-        break;
+inline std::string FuzzedDataProvider::ConsumeRandomLengthString(size_t max_length)
+{
+    // Reads bytes from the start of |data_ptr_|. Maps "\\" to "\", and maps "\"
+    // followed by anything else to the end of the string. As a result of this
+    // logic, a fuzzer can insert characters into the string, and the string
+    // will be lengthened to include those new characters, resulting in a more
+    // stable fuzzer than picking the length of a string independently from
+    // picking its contents.
+    std::string result;
+
+    // Reserve the anticipated capaticity to prevent several reallocations.
+    result.reserve(std::min(max_length, remaining_bytes_));
+    for (size_t i = 0; i < max_length && remaining_bytes_ != 0; ++i) {
+        char next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
+        Advance(1);
+        if (next == '\\' && remaining_bytes_ != 0) {
+            next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
+            Advance(1);
+            if (next != '\\')
+                break;
+        }
+        result += next;
     }
-    result += next;
-  }
 
-  result.shrink_to_fit();
-  return result;
+    result.shrink_to_fit();
+    return result;
 }
 
 // Returns a std::string of length from 0 to |remaining_bytes_|.
-inline std::string FuzzedDataProvider::ConsumeRandomLengthString() {
-  return ConsumeRandomLengthString(remaining_bytes_);
+inline std::string FuzzedDataProvider::ConsumeRandomLengthString()
+{
+    return ConsumeRandomLengthString(remaining_bytes_);
 }
 
 // Returns a std::string containing all remaining bytes of the input data.
 // Prefer using |ConsumeRemainingBytes| unless you actually need a std::string
 // object.
-inline std::string FuzzedDataProvider::ConsumeRemainingBytesAsString() {
-  return ConsumeBytesAsString(remaining_bytes_);
+inline std::string FuzzedDataProvider::ConsumeRemainingBytesAsString()
+{
+    return ConsumeBytesAsString(remaining_bytes_);
 }
 
 // Returns a number in the range [Type's min, Type's max]. The value might
 // not be uniformly distributed in the given range. If there's no input data
 // left, always returns |min|.
-template <typename T> T FuzzedDataProvider::ConsumeIntegral() {
-  return ConsumeIntegralInRange(std::numeric_limits<T>::min(),
-                                std::numeric_limits<T>::max());
+template<typename T>
+T FuzzedDataProvider::ConsumeIntegral()
+{
+    return ConsumeIntegralInRange(std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
 }
 
 // Returns a number in the range [min, max] by consuming bytes from the
 // input data. The value might not be uniformly distributed in the given
 // range. If there's no input data left, always returns |min|. |min| must
 // be less than or equal to |max|.
-template <typename T>
-T FuzzedDataProvider::ConsumeIntegralInRange(T min, T max) {
-  static_assert(std::is_integral<T>::value, "An integral type is required.");
-  static_assert(sizeof(T) <= sizeof(uint64_t), "Unsupported integral type.");
-
-  if (min > max)
-    abort();
-
-  // Use the biggest type possible to hold the range and the result.
-  uint64_t range = static_cast<uint64_t>(max) - min;
-  uint64_t result = 0;
-  size_t offset = 0;
-
-  while (offset < sizeof(T) * CHAR_BIT && (range >> offset) > 0 &&
-         remaining_bytes_ != 0) {
-    // Pull bytes off the end of the seed data. Experimentally, this seems to
-    // allow the fuzzer to more easily explore the input space. This makes
-    // sense, since it works by modifying inputs that caused new code to run,
-    // and this data is often used to encode length of data read by
-    // |ConsumeBytes|. Separating out read lengths makes it easier modify the
-    // contents of the data that is actually read.
-    --remaining_bytes_;
-    result = (result << CHAR_BIT) | data_ptr_[remaining_bytes_];
-    offset += CHAR_BIT;
-  }
-
-  // Avoid division by 0, in case |range + 1| results in overflow.
-  if (range != std::numeric_limits<decltype(range)>::max())
-    result = result % (range + 1);
-
-  return static_cast<T>(min + result);
+template<typename T>
+T FuzzedDataProvider::ConsumeIntegralInRange(T min, T max)
+{
+    static_assert(std::is_integral<T>::value, "An integral type is required.");
+    static_assert(sizeof(T) <= sizeof(uint64_t), "Unsupported integral type.");
+
+    if (min > max)
+        abort();
+
+    // Use the biggest type possible to hold the range and the result.
+    uint64_t range = static_cast<uint64_t>(max) - min;
+    uint64_t result = 0;
+    size_t offset = 0;
+
+    while (offset < sizeof(T) * CHAR_BIT && (range >> offset) > 0 && remaining_bytes_ != 0) {
+        // Pull bytes off the end of the seed data. Experimentally, this seems to
+        // allow the fuzzer to more easily explore the input space. This makes
+        // sense, since it works by modifying inputs that caused new code to run,
+        // and this data is often used to encode length of data read by
+        // |ConsumeBytes|. Separating out read lengths makes it easier modify the
+        // contents of the data that is actually read.
+        --remaining_bytes_;
+        result = (result << CHAR_BIT) | data_ptr_[remaining_bytes_];
+        offset += CHAR_BIT;
+    }
+
+    // Avoid division by 0, in case |range + 1| results in overflow.
+    if (range != std::numeric_limits<decltype(range)>::max())
+        result = result % (range + 1);
+
+    return static_cast<T>(min + result);
 }
 
 // Returns a floating point value in the range [Type's lowest, Type's max] by
 // consuming bytes from the input data. If there's no input data left, always
 // returns approximately 0.
-template <typename T> T FuzzedDataProvider::ConsumeFloatingPoint() {
-  return ConsumeFloatingPointInRange<T>(std::numeric_limits<T>::lowest(),
-                                        std::numeric_limits<T>::max());
+template<typename T>
+T FuzzedDataProvider::ConsumeFloatingPoint()
+{
+    return ConsumeFloatingPointInRange<T>(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max());
 }
 
 // Returns a floating point value in the given range by consuming bytes from
 // the input data. If there's no input data left, returns |min|. Note that
 // |min| must be less than or equal to |max|.
-template <typename T>
-T FuzzedDataProvider::ConsumeFloatingPointInRange(T min, T max) {
-  if (min > max)
-    abort();
-
-  T range = .0;
-  T result = min;
-  constexpr T zero(.0);
-  if (max > zero && min < zero && max > min + std::numeric_limits<T>::max()) {
-    // The diff |max - min| would overflow the given floating point type. Use
-    // the half of the diff as the range and consume a bool to decide whether
-    // the result is in the first of the second part of the diff.
-    range = (max / 2.0) - (min / 2.0);
-    if (ConsumeBool()) {
-      result += range;
+template<typename T>
+T FuzzedDataProvider::ConsumeFloatingPointInRange(T min, T max)
+{
+    if (min > max)
+        abort();
+
+    T range = .0;
+    T result = min;
+    constexpr T zero(.0);
+    if (max > zero && min < zero && max > min + std::numeric_limits<T>::max()) {
+        // The diff |max - min| would overflow the given floating point type. Use
+        // the half of the diff as the range and consume a bool to decide whether
+        // the result is in the first of the second part of the diff.
+        range = (max / 2.0) - (min / 2.0);
+        if (ConsumeBool()) {
+            result += range;
+        }
+    } else {
+        range = max - min;
     }
-  } else {
-    range = max - min;
-  }
 
-  return result + range * ConsumeProbability<T>();
+    return result + range * ConsumeProbability<T>();
 }
 
 // Returns a floating point number in the range [0.0, 1.0]. If there's no
 // input data left, always returns 0.
-template <typename T> T FuzzedDataProvider::ConsumeProbability() {
-  static_assert(std::is_floating_point<T>::value,
-                "A floating point type is required.");
-
-  // Use different integral types for different floating point types in order
-  // to provide better density of the resulting values.
-  using IntegralType =
-      typename std::conditional<(sizeof(T) <= sizeof(uint32_t)), uint32_t,
-                                uint64_t>::type;
-
-  T result = static_cast<T>(ConsumeIntegral<IntegralType>());
-  result /= static_cast<T>(std::numeric_limits<IntegralType>::max());
-  return result;
+template<typename T>
+T FuzzedDataProvider::ConsumeProbability()
+{
+    static_assert(std::is_floating_point<T>::value, "A floating point type is required.");
+
+    // Use different integral types for different floating point types in order
+    // to provide better density of the resulting values.
+    using IntegralType = typename std::conditional<(sizeof(T) <= sizeof(uint32_t)), uint32_t, uint64_t>::type;
+
+    T result = static_cast<T>(ConsumeIntegral<IntegralType>());
+    result /= static_cast<T>(std::numeric_limits<IntegralType>::max());
+    return result;
 }
 
 // Reads one byte and returns a bool, or false when no data remains.
-inline bool FuzzedDataProvider::ConsumeBool() {
-  return 1 & ConsumeIntegral<uint8_t>();
+inline bool FuzzedDataProvider::ConsumeBool()
+{
+    return 1 & ConsumeIntegral<uint8_t>();
 }
 
 // Returns an enum value. The enum must start at 0 and be contiguous. It must
 // also contain |kMaxValue| aliased to its largest (inclusive) value. Such as:
 // enum class Foo { SomeValue, OtherValue, kMaxValue = OtherValue };
-template <typename T> T FuzzedDataProvider::ConsumeEnum() {
-  static_assert(std::is_enum<T>::value, "|T| must be an enum type.");
-  return static_cast<T>(
-      ConsumeIntegralInRange<uint32_t>(0, static_cast<uint32_t>(T::kMaxValue)));
+template<typename T>
+T FuzzedDataProvider::ConsumeEnum()
+{
+    static_assert(std::is_enum<T>::value, "|T| must be an enum type.");
+    return static_cast<T>(ConsumeIntegralInRange<uint32_t>(0, static_cast<uint32_t>(T::kMaxValue)));
 }
 
 // Returns a copy of the value selected from the given fixed-size |array|.
-template <typename T, size_t size>
-T FuzzedDataProvider::PickValueInArray(const T (&array)[size]) {
-  static_assert(size > 0, "The array must be non empty.");
-  return array[ConsumeIntegralInRange<size_t>(0, size - 1)];
+template<typename T, size_t size>
+T FuzzedDataProvider::PickValueInArray(const T (&array)[size])
+{
+    static_assert(size > 0, "The array must be non empty.");
+    return array[ConsumeIntegralInRange<size_t>(0, size - 1)];
 }
 
-template <typename T>
-T FuzzedDataProvider::PickValueInArray(std::initializer_list<const T> list) {
-  // TODO(Dor1s): switch to static_assert once C++14 is allowed.
-  if (!list.size())
-    abort();
+template<typename T>
+T FuzzedDataProvider::PickValueInArray(std::initializer_list<const T> list)
+{
+    // TODO(Dor1s): switch to static_assert once C++14 is allowed.
+    if (!list.size())
+        abort();
 
-  return *(list.begin() + ConsumeIntegralInRange<size_t>(0, list.size() - 1));
+    return *(list.begin() + ConsumeIntegralInRange<size_t>(0, list.size() - 1));
 }
 
 // Writes |num_bytes| of input data to the given destination pointer. If there
@@ -316,72 +336,74 @@ T FuzzedDataProvider::PickValueInArray(std::initializer_list<const T> list) {
 // In general, it's better to avoid using this function, but it may be useful
 // in cases when it's necessary to fill a certain buffer or object with
 // fuzzing data.
-inline size_t FuzzedDataProvider::ConsumeData(void *destination,
-                                              size_t num_bytes) {
-  num_bytes = std::min(num_bytes, remaining_bytes_);
-  CopyAndAdvance(destination, num_bytes);
-  return num_bytes;
+inline size_t FuzzedDataProvider::ConsumeData(void *destination, size_t num_bytes)
+{
+    num_bytes = std::min(num_bytes, remaining_bytes_);
+    CopyAndAdvance(destination, num_bytes);
+    return num_bytes;
 }
 
 // Private methods.
-inline void FuzzedDataProvider::CopyAndAdvance(void *destination,
-                                               size_t num_bytes) {
-  std::memcpy(destination, data_ptr_, num_bytes);
-  Advance(num_bytes);
+inline void FuzzedDataProvider::CopyAndAdvance(void *destination, size_t num_bytes)
+{
+    std::memcpy(destination, data_ptr_, num_bytes);
+    Advance(num_bytes);
 }
 
-inline void FuzzedDataProvider::Advance(size_t num_bytes) {
-  if (num_bytes > remaining_bytes_)
-    abort();
+inline void FuzzedDataProvider::Advance(size_t num_bytes)
+{
+    if (num_bytes > remaining_bytes_)
+        abort();
 
-  data_ptr_ += num_bytes;
-  remaining_bytes_ -= num_bytes;
+    data_ptr_ += num_bytes;
+    remaining_bytes_ -= num_bytes;
 }
 
-template <typename T>
-std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t size, size_t num_bytes) {
-  static_assert(sizeof(T) == sizeof(uint8_t), "Incompatible data type.");
-
-  // The point of using the size-based constructor below is to increase the
-  // odds of having a vector object with capacity being equal to the length.
-  // That part is always implementation specific, but at least both libc++ and
-  // libstdc++ allocate the requested number of bytes in that constructor,
-  // which seems to be a natural choice for other implementations as well.
-  // To increase the odds even more, we also call |shrink_to_fit| below.
-  std::vector<T> result(size);
-  if (size == 0) {
-    if (num_bytes != 0)
-      abort();
-    return result;
-  }
+template<typename T>
+std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t size, size_t num_bytes)
+{
+    static_assert(sizeof(T) == sizeof(uint8_t), "Incompatible data type.");
+
+    // The point of using the size-based constructor below is to increase the
+    // odds of having a vector object with capacity being equal to the length.
+    // That part is always implementation specific, but at least both libc++ and
+    // libstdc++ allocate the requested number of bytes in that constructor,
+    // which seems to be a natural choice for other implementations as well.
+    // To increase the odds even more, we also call |shrink_to_fit| below.
+    std::vector<T> result(size);
+    if (size == 0) {
+        if (num_bytes != 0)
+            abort();
+        return result;
+    }
 
-  CopyAndAdvance(result.data(), num_bytes);
+    CopyAndAdvance(result.data(), num_bytes);
 
-  // Even though |shrink_to_fit| is also implementation specific, we expect it
-  // to provide an additional assurance in case vector's constructor allocated
-  // a buffer which is larger than the actual amount of data we put inside it.
-  result.shrink_to_fit();
-  return result;
+    // Even though |shrink_to_fit| is also implementation specific, we expect it
+    // to provide an additional assurance in case vector's constructor allocated
+    // a buffer which is larger than the actual amount of data we put inside it.
+    result.shrink_to_fit();
+    return result;
 }
 
-template <typename TS, typename TU>
-TS FuzzedDataProvider::ConvertUnsignedToSigned(TU value) {
-  static_assert(sizeof(TS) == sizeof(TU), "Incompatible data types.");
-  static_assert(!std::numeric_limits<TU>::is_signed,
-                "Source type must be unsigned.");
-
-  // TODO(Dor1s): change to `if constexpr` once C++17 becomes mainstream.
-  if (std::numeric_limits<TS>::is_modulo)
-    return static_cast<TS>(value);
-
-  // Avoid using implementation-defined unsigned to signed conversions.
-  // To learn more, see https://stackoverflow.com/questions/13150449.
-  if (value <= std::numeric_limits<TS>::max()) {
-    return static_cast<TS>(value);
-  } else {
-    constexpr auto TS_min = std::numeric_limits<TS>::min();
-    return TS_min + static_cast<char>(value - TS_min);
-  }
+template<typename TS, typename TU>
+TS FuzzedDataProvider::ConvertUnsignedToSigned(TU value)
+{
+    static_assert(sizeof(TS) == sizeof(TU), "Incompatible data types.");
+    static_assert(!std::numeric_limits<TU>::is_signed, "Source type must be unsigned.");
+
+    // TODO(Dor1s): change to `if constexpr` once C++17 becomes mainstream.
+    if (std::numeric_limits<TS>::is_modulo)
+        return static_cast<TS>(value);
+
+    // Avoid using implementation-defined unsigned to signed conversions.
+    // To learn more, see https://stackoverflow.com/questions/13150449.
+    if (value <= std::numeric_limits<TS>::max()) {
+        return static_cast<TS>(value);
+    } else {
+        constexpr auto TS_min = std::numeric_limits<TS>::min();
+        return TS_min + static_cast<char>(value - TS_min);
+    }
 }
 
 #endif // LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
diff --git a/qt5/tests/fuzzing/fuzzer_temp_file.h b/qt5/tests/fuzzing/fuzzer_temp_file.h
index fe25caba..d0568ac5 100644
--- a/qt5/tests/fuzzing/fuzzer_temp_file.h
+++ b/qt5/tests/fuzzing/fuzzer_temp_file.h
@@ -26,56 +26,57 @@
 
 // Pure-C interface for creating and cleaning up temporary files.
 
-static char* fuzzer_get_tmpfile(const uint8_t* data, size_t size) {
-  char* filename_buffer = strdup("/tmp/generate_temporary_file.XXXXXX");
-  if (!filename_buffer) {
-    perror("Failed to allocate file name buffer.");
-    abort();
-  }
-  const int file_descriptor = mkstemp(filename_buffer);
-  if (file_descriptor < 0) {
-    perror("Failed to make temporary file.");
-    abort();
-  }
-  FILE* file = fdopen(file_descriptor, "wb");
-  if (!file) {
-    perror("Failed to open file descriptor.");
-    close(file_descriptor);
-    abort();
-  }
-  const size_t bytes_written = fwrite(data, sizeof(uint8_t), size, file);
-  if (bytes_written < size) {
-    close(file_descriptor);
-    fprintf(stderr, "Failed to write all bytes to file (%zu out of %zu)",
-            bytes_written, size);
-    abort();
-  }
-  fclose(file);
-  return filename_buffer;
+static char *fuzzer_get_tmpfile(const uint8_t *data, size_t size)
+{
+    char *filename_buffer = strdup("/tmp/generate_temporary_file.XXXXXX");
+    if (!filename_buffer) {
+        perror("Failed to allocate file name buffer.");
+        abort();
+    }
+    const int file_descriptor = mkstemp(filename_buffer);
+    if (file_descriptor < 0) {
+        perror("Failed to make temporary file.");
+        abort();
+    }
+    FILE *file = fdopen(file_descriptor, "wb");
+    if (!file) {
+        perror("Failed to open file descriptor.");
+        close(file_descriptor);
+        abort();
+    }
+    const size_t bytes_written = fwrite(data, sizeof(uint8_t), size, file);
+    if (bytes_written < size) {
+        close(file_descriptor);
+        fprintf(stderr, "Failed to write all bytes to file (%zu out of %zu)", bytes_written, size);
+        abort();
+    }
+    fclose(file);
+    return filename_buffer;
 }
 
-static void fuzzer_release_tmpfile(char* filename) {
-  if (unlink(filename) != 0) {
-    perror("WARNING: Failed to delete temporary file.");
-  }
-  free(filename);
+static void fuzzer_release_tmpfile(char *filename)
+{
+    if (unlink(filename) != 0) {
+        perror("WARNING: Failed to delete temporary file.");
+    }
+    free(filename);
 }
 
 // C++ RAII object for creating temporary files.
 
 #ifdef __cplusplus
-class FuzzerTemporaryFile {
- public:
-  FuzzerTemporaryFile(const uint8_t* data, size_t size)
-      : filename_(fuzzer_get_tmpfile(data, size)) {}
+class FuzzerTemporaryFile
+{
+public:
+    FuzzerTemporaryFile(const uint8_t *data, size_t size) : filename_(fuzzer_get_tmpfile(data, size)) { }
 
-  ~FuzzerTemporaryFile() { fuzzer_release_tmpfile(filename_); }
+    ~FuzzerTemporaryFile() { fuzzer_release_tmpfile(filename_); }
 
-  const char* filename() const { return filename_; }
+    const char *filename() const { return filename_; }
 
- private:
-  char* filename_;
+private:
+    char *filename_;
 };
 #endif
 
-#endif  // FUZZER_TEMP_FILE_H_
+#endif // FUZZER_TEMP_FILE_H_
diff --git a/qt5/tests/fuzzing/qt_annot_fuzzer.cc b/qt5/tests/fuzzing/qt_annot_fuzzer.cc
index 1e6de148..8b569f28 100644
--- a/qt5/tests/fuzzing/qt_annot_fuzzer.cc
+++ b/qt5/tests/fuzzing/qt_annot_fuzzer.cc
@@ -11,17 +11,17 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
     const QColor color = QColor::fromRgb(0xAB, 0xCD, 0xEF);
     char *tmpfile = fuzzer_get_tmpfile(data, size);
 
-    QByteArray in_data = QByteArray::fromRawData((const char*)data, size);
+    QByteArray in_data = QByteArray::fromRawData((const char *)data, size);
     Poppler::Document *doc = Poppler::Document::loadFromData(in_data);
 
-    if (!doc || doc->isLocked()){
+    if (!doc || doc->isLocked()) {
         delete doc;
         fuzzer_release_tmpfile(tmpfile);
         return 0;
     }
 
     for (int i = 0; i < doc->numPages(); i++) {
-        Poppler::Page* p = doc->page(i);
+        Poppler::Page *p = doc->page(i);
         if (!p) {
             continue;
         }
diff --git a/qt5/tests/fuzzing/qt_label_fuzzer.cc b/qt5/tests/fuzzing/qt_label_fuzzer.cc
index 64049fcc..65a81629 100644
--- a/qt5/tests/fuzzing/qt_label_fuzzer.cc
+++ b/qt5/tests/fuzzing/qt_label_fuzzer.cc
@@ -7,16 +7,16 @@ static void dummy_error_function(const QString &, const QVariant &) { }
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
     Poppler::setDebugErrorFunction(dummy_error_function, QVariant());
-    QByteArray in_data = QByteArray::fromRawData((const char*)data, size);
+    QByteArray in_data = QByteArray::fromRawData((const char *)data, size);
     Poppler::Document *doc = Poppler::Document::loadFromData(in_data);
-    if (!doc || doc->isLocked()){
+    if (!doc || doc->isLocked()) {
         delete doc;
         return 0;
     }
 
     for (int i = 0; i < doc->numPages(); i++) {
         QString label = QString(in_data);
-        Poppler::Page* p = doc->page(label);
+        Poppler::Page *p = doc->page(label);
         if (!p) {
             continue;
         }
diff --git a/qt5/tests/fuzzing/qt_pdf_fuzzer.cc b/qt5/tests/fuzzing/qt_pdf_fuzzer.cc
index 1398b28a..82786994 100644
--- a/qt5/tests/fuzzing/qt_pdf_fuzzer.cc
+++ b/qt5/tests/fuzzing/qt_pdf_fuzzer.cc
@@ -7,15 +7,15 @@ static void dummy_error_function(const QString &, const QVariant &) { }
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
     Poppler::setDebugErrorFunction(dummy_error_function, QVariant());
-    QByteArray in_data = QByteArray::fromRawData((const char*)data, size);
+    QByteArray in_data = QByteArray::fromRawData((const char *)data, size);
     Poppler::Document *doc = Poppler::Document::loadFromData(in_data);
-    if (!doc || doc->isLocked()){
+    if (!doc || doc->isLocked()) {
         delete doc;
         return 0;
     }
 
     for (int i = 0; i < doc->numPages(); i++) {
-        Poppler::Page* p = doc->page(i);
+        Poppler::Page *p = doc->page(i);
         if (!p) {
             continue;
         }
diff --git a/qt5/tests/fuzzing/qt_search_fuzzer.cc b/qt5/tests/fuzzing/qt_search_fuzzer.cc
index 6d00720a..989589fd 100644
--- a/qt5/tests/fuzzing/qt_search_fuzzer.cc
+++ b/qt5/tests/fuzzing/qt_search_fuzzer.cc
@@ -6,15 +6,15 @@ static void dummy_error_function(const QString &, const QVariant &) { }
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
     Poppler::setDebugErrorFunction(dummy_error_function, QVariant());
-    QByteArray in_data = QByteArray::fromRawData((const char*)data, size);
+    QByteArray in_data = QByteArray::fromRawData((const char *)data, size);
     Poppler::Document *doc = Poppler::Document::loadFromData(in_data);
-    if (!doc || doc->isLocked()){
+    if (!doc || doc->isLocked()) {
         delete doc;
         return 0;
     }
 
     for (int i = 0; i < doc->numPages(); i++) {
-        Poppler::Page* p = doc->page(i);
+        Poppler::Page *p = doc->page(i);
         if (!p) {
             continue;
         }
diff --git a/qt5/tests/fuzzing/qt_textbox_fuzzer.cc b/qt5/tests/fuzzing/qt_textbox_fuzzer.cc
index e90dbaab..c0ecef74 100644
--- a/qt5/tests/fuzzing/qt_textbox_fuzzer.cc
+++ b/qt5/tests/fuzzing/qt_textbox_fuzzer.cc
@@ -8,15 +8,15 @@ static void dummy_error_function(const QString &, const QVariant &) { }
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
     Poppler::setDebugErrorFunction(dummy_error_function, QVariant());
-    QByteArray in_data = QByteArray::fromRawData((const char*)data, size);
+    QByteArray in_data = QByteArray::fromRawData((const char *)data, size);
     Poppler::Document *doc = Poppler::Document::loadFromData(in_data);
-    if (!doc || doc->isLocked()){
+    if (!doc || doc->isLocked()) {
         delete doc;
         return 0;
     }
 
     for (int i = 0; i < doc->numPages(); i++) {
-        Poppler::Page* p = doc->page(i);
+        Poppler::Page *p = doc->page(i);
         if (!p) {
             continue;
         }
commit 890de69dbe531484f687877124c080508b25a9f8
Author: Ceyhun Alp <ceyhunalp at google.com>
Date:   Mon Oct 19 08:23:48 2020 +0000

    Fuzzers for qt5 + cleaning up cpp and glib fuzzers

diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt
index 9517b39a..18b17334 100644
--- a/cpp/tests/CMakeLists.txt
+++ b/cpp/tests/CMakeLists.txt
@@ -21,7 +21,7 @@ cpp_add_simpletest(poppler-dump poppler-dump.cpp ${CMAKE_SOURCE_DIR}/utils/parse
 cpp_add_simpletest(poppler-render poppler-render.cpp ${CMAKE_SOURCE_DIR}/utils/parseargs.cc)
 
 if(ENABLE_FUZZER)
-  cpp_add_simpletest(pdf_fuzzer pdf_fuzzer.cc)
+  cpp_add_simpletest(doc_fuzzer ./fuzzing/doc_fuzzer.cc)
   cpp_add_simpletest(pdf_file_fuzzer ./fuzzing/pdf_file_fuzzer.cc)
   cpp_add_simpletest(page_label_fuzzer ./fuzzing/page_label_fuzzer.cc)
   cpp_add_simpletest(page_search_fuzzer ./fuzzing/page_search_fuzzer.cc)
diff --git a/cpp/tests/fuzzing/FuzzedDataProvider.h b/cpp/tests/fuzzing/FuzzedDataProvider.h
new file mode 100644
index 00000000..83bcd013
--- /dev/null
+++ b/cpp/tests/fuzzing/FuzzedDataProvider.h
@@ -0,0 +1,387 @@
+//===- FuzzedDataProvider.h - Utility header for fuzz targets ---*- C++ -* ===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// A single header library providing an utility class to break up an array of
+// bytes. Whenever run on the same input, provides the same output, as long as
+// its methods are called in the same order, with the same arguments.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
+#define LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
+
+#include <algorithm>
+#include <climits>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <initializer_list>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+// In addition to the comments below, the API is also briefly documented at
+// https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider
+class FuzzedDataProvider {
+ public:
+  // |data| is an array of length |size| that the FuzzedDataProvider wraps to
+  // provide more granular access. |data| must outlive the FuzzedDataProvider.
+  FuzzedDataProvider(const uint8_t *data, size_t size)
+      : data_ptr_(data), remaining_bytes_(size) {}
+  ~FuzzedDataProvider() = default;
+
+  // See the implementation below (after the class definition) for more verbose
+  // comments for each of the methods.
+
+  // Methods returning std::vector of bytes. These are the most popular choice
+  // when splitting fuzzing input into pieces, as every piece is put into a
+  // separate buffer (i.e. ASan would catch any under-/overflow) and the memory
+  // will be released automatically.
+  template <typename T> std::vector<T> ConsumeBytes(size_t num_bytes);
+  template <typename T>
+  std::vector<T> ConsumeBytesWithTerminator(size_t num_bytes, T terminator = 0);
+  template <typename T> std::vector<T> ConsumeRemainingBytes();
+
+  // Methods returning strings. Use only when you need a std::string or a null
+  // terminated C-string. Otherwise, prefer the methods returning std::vector.
+  std::string ConsumeBytesAsString(size_t num_bytes);
+  std::string ConsumeRandomLengthString(size_t max_length);
+  std::string ConsumeRandomLengthString();
+  std::string ConsumeRemainingBytesAsString();
+
+  // Methods returning integer values.
+  template <typename T> T ConsumeIntegral();
+  template <typename T> T ConsumeIntegralInRange(T min, T max);
+
+  // Methods returning floating point values.
+  template <typename T> T ConsumeFloatingPoint();
+  template <typename T> T ConsumeFloatingPointInRange(T min, T max);
+
+  // 0 <= return value <= 1.
+  template <typename T> T ConsumeProbability();
+
+  bool ConsumeBool();
+
+  // Returns a value chosen from the given enum.
+  template <typename T> T ConsumeEnum();
+
+  // Returns a value from the given array.
+  template <typename T, size_t size> T PickValueInArray(const T (&array)[size]);
+  template <typename T> T PickValueInArray(std::initializer_list<const T> list);
+
+  // Writes data to the given destination and returns number of bytes written.
+  size_t ConsumeData(void *destination, size_t num_bytes);
+
+  // Reports the remaining bytes available for fuzzed input.
+  size_t remaining_bytes() { return remaining_bytes_; }
+
+ private:
+  FuzzedDataProvider(const FuzzedDataProvider &) = delete;
+  FuzzedDataProvider &operator=(const FuzzedDataProvider &) = delete;
+
+  void CopyAndAdvance(void *destination, size_t num_bytes);
+
+  void Advance(size_t num_bytes);
+
+  template <typename T>
+  std::vector<T> ConsumeBytes(size_t size, size_t num_bytes);
+
+  template <typename TS, typename TU> TS ConvertUnsignedToSigned(TU value);
+
+  const uint8_t *data_ptr_;
+  size_t remaining_bytes_;
+};
+
+// Returns a std::vector containing |num_bytes| of input data. If fewer than
+// |num_bytes| of data remain, returns a shorter std::vector containing all
+// of the data that's left. Can be used with any byte sized type, such as
+// char, unsigned char, uint8_t, etc.
+template <typename T>
+std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t num_bytes) {
+  num_bytes = std::min(num_bytes, remaining_bytes_);
+  return ConsumeBytes<T>(num_bytes, num_bytes);
+}
+
+// Similar to |ConsumeBytes|, but also appends the terminator value at the end
+// of the resulting vector. Useful, when a mutable null-terminated C-string is
+// needed, for example. But that is a rare case. Better avoid it, if possible,
+// and prefer using |ConsumeBytes| or |ConsumeBytesAsString| methods.
+template <typename T>
+std::vector<T> FuzzedDataProvider::ConsumeBytesWithTerminator(size_t num_bytes,
+                                                              T terminator) {
+  num_bytes = std::min(num_bytes, remaining_bytes_);
+  std::vector<T> result = ConsumeBytes<T>(num_bytes + 1, num_bytes);
+  result.back() = terminator;
+  return result;
+}
+
+// Returns a std::vector containing all remaining bytes of the input data.
+template <typename T>
+std::vector<T> FuzzedDataProvider::ConsumeRemainingBytes() {
+  return ConsumeBytes<T>(remaining_bytes_);
+}
+
+// Returns a std::string containing |num_bytes| of input data. Using this and
+// |.c_str()| on the resulting string is the best way to get an immutable
+// null-terminated C string. If fewer than |num_bytes| of data remain, returns
+// a shorter std::string containing all of the data that's left.
+inline std::string FuzzedDataProvider::ConsumeBytesAsString(size_t num_bytes) {
+  static_assert(sizeof(std::string::value_type) == sizeof(uint8_t),
+                "ConsumeBytesAsString cannot convert the data to a string.");
+
+  num_bytes = std::min(num_bytes, remaining_bytes_);
+  std::string result(
+      reinterpret_cast<const std::string::value_type *>(data_ptr_), num_bytes);
+  Advance(num_bytes);
+  return result;
+}
+
+// Returns a std::string of length from 0 to |max_length|. When it runs out of
+// input data, returns what remains of the input. Designed to be more stable
+// with respect to a fuzzer inserting characters than just picking a random
+// length and then consuming that many bytes with |ConsumeBytes|.
+inline std::string
+FuzzedDataProvider::ConsumeRandomLengthString(size_t max_length) {
+  // Reads bytes from the start of |data_ptr_|. Maps "\\" to "\", and maps "\"
+  // followed by anything else to the end of the string. As a result of this
+  // logic, a fuzzer can insert characters into the string, and the string
+  // will be lengthened to include those new characters, resulting in a more
+  // stable fuzzer than picking the length of a string independently from
+  // picking its contents.
+  std::string result;
+
+  // Reserve the anticipated capaticity to prevent several reallocations.
+  result.reserve(std::min(max_length, remaining_bytes_));
+  for (size_t i = 0; i < max_length && remaining_bytes_ != 0; ++i) {
+    char next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
+    Advance(1);
+    if (next == '\\' && remaining_bytes_ != 0) {
+      next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
+      Advance(1);
+      if (next != '\\')
+        break;
+    }
+    result += next;
+  }
+
+  result.shrink_to_fit();
+  return result;
+}
+
+// Returns a std::string of length from 0 to |remaining_bytes_|.
+inline std::string FuzzedDataProvider::ConsumeRandomLengthString() {
+  return ConsumeRandomLengthString(remaining_bytes_);
+}
+
+// Returns a std::string containing all remaining bytes of the input data.
+// Prefer using |ConsumeRemainingBytes| unless you actually need a std::string
+// object.
+inline std::string FuzzedDataProvider::ConsumeRemainingBytesAsString() {
+  return ConsumeBytesAsString(remaining_bytes_);
+}
+
+// Returns a number in the range [Type's min, Type's max]. The value might
+// not be uniformly distributed in the given range. If there's no input data
+// left, always returns |min|.
+template <typename T> T FuzzedDataProvider::ConsumeIntegral() {
+  return ConsumeIntegralInRange(std::numeric_limits<T>::min(),
+                                std::numeric_limits<T>::max());
+}
+
+// Returns a number in the range [min, max] by consuming bytes from the
+// input data. The value might not be uniformly distributed in the given
+// range. If there's no input data left, always returns |min|. |min| must
+// be less than or equal to |max|.
+template <typename T>
+T FuzzedDataProvider::ConsumeIntegralInRange(T min, T max) {
+  static_assert(std::is_integral<T>::value, "An integral type is required.");
+  static_assert(sizeof(T) <= sizeof(uint64_t), "Unsupported integral type.");
+
+  if (min > max)
+    abort();
+
+  // Use the biggest type possible to hold the range and the result.
+  uint64_t range = static_cast<uint64_t>(max) - min;
+  uint64_t result = 0;
+  size_t offset = 0;
+
+  while (offset < sizeof(T) * CHAR_BIT && (range >> offset) > 0 &&
+         remaining_bytes_ != 0) {
+    // Pull bytes off the end of the seed data. Experimentally, this seems to
+    // allow the fuzzer to more easily explore the input space. This makes
+    // sense, since it works by modifying inputs that caused new code to run,
+    // and this data is often used to encode length of data read by
+    // |ConsumeBytes|. Separating out read lengths makes it easier modify the
+    // contents of the data that is actually read.
+    --remaining_bytes_;
+    result = (result << CHAR_BIT) | data_ptr_[remaining_bytes_];
+    offset += CHAR_BIT;
+  }
+
+  // Avoid division by 0, in case |range + 1| results in overflow.
+  if (range != std::numeric_limits<decltype(range)>::max())
+    result = result % (range + 1);
+
+  return static_cast<T>(min + result);
+}
+
+// Returns a floating point value in the range [Type's lowest, Type's max] by
+// consuming bytes from the input data. If there's no input data left, always
+// returns approximately 0.
+template <typename T> T FuzzedDataProvider::ConsumeFloatingPoint() {
+  return ConsumeFloatingPointInRange<T>(std::numeric_limits<T>::lowest(),
+                                        std::numeric_limits<T>::max());
+}
+
+// Returns a floating point value in the given range by consuming bytes from
+// the input data. If there's no input data left, returns |min|. Note that
+// |min| must be less than or equal to |max|.
+template <typename T>
+T FuzzedDataProvider::ConsumeFloatingPointInRange(T min, T max) {
+  if (min > max)
+    abort();
+
+  T range = .0;
+  T result = min;
+  constexpr T zero(.0);
+  if (max > zero && min < zero && max > min + std::numeric_limits<T>::max()) {
+    // The diff |max - min| would overflow the given floating point type. Use
+    // the half of the diff as the range and consume a bool to decide whether
+    // the result is in the first of the second part of the diff.
+    range = (max / 2.0) - (min / 2.0);
+    if (ConsumeBool()) {
+      result += range;
+    }
+  } else {
+    range = max - min;
+  }
+
+  return result + range * ConsumeProbability<T>();
+}
+
+// Returns a floating point number in the range [0.0, 1.0]. If there's no
+// input data left, always returns 0.
+template <typename T> T FuzzedDataProvider::ConsumeProbability() {
+  static_assert(std::is_floating_point<T>::value,
+                "A floating point type is required.");
+
+  // Use different integral types for different floating point types in order
+  // to provide better density of the resulting values.
+  using IntegralType =
+      typename std::conditional<(sizeof(T) <= sizeof(uint32_t)), uint32_t,
+                                uint64_t>::type;
+
+  T result = static_cast<T>(ConsumeIntegral<IntegralType>());
+  result /= static_cast<T>(std::numeric_limits<IntegralType>::max());
+  return result;
+}
+
+// Reads one byte and returns a bool, or false when no data remains.
+inline bool FuzzedDataProvider::ConsumeBool() {
+  return 1 & ConsumeIntegral<uint8_t>();
+}
+
+// Returns an enum value. The enum must start at 0 and be contiguous. It must
+// also contain |kMaxValue| aliased to its largest (inclusive) value. Such as:
+// enum class Foo { SomeValue, OtherValue, kMaxValue = OtherValue };
+template <typename T> T FuzzedDataProvider::ConsumeEnum() {
+  static_assert(std::is_enum<T>::value, "|T| must be an enum type.");
+  return static_cast<T>(
+      ConsumeIntegralInRange<uint32_t>(0, static_cast<uint32_t>(T::kMaxValue)));
+}
+
+// Returns a copy of the value selected from the given fixed-size |array|.
+template <typename T, size_t size>
+T FuzzedDataProvider::PickValueInArray(const T (&array)[size]) {
+  static_assert(size > 0, "The array must be non empty.");
+  return array[ConsumeIntegralInRange<size_t>(0, size - 1)];
+}
+
+template <typename T>
+T FuzzedDataProvider::PickValueInArray(std::initializer_list<const T> list) {
+  // TODO(Dor1s): switch to static_assert once C++14 is allowed.
+  if (!list.size())
+    abort();
+
+  return *(list.begin() + ConsumeIntegralInRange<size_t>(0, list.size() - 1));
+}
+
+// Writes |num_bytes| of input data to the given destination pointer. If there
+// is not enough data left, writes all remaining bytes. Return value is the
+// number of bytes written.
+// In general, it's better to avoid using this function, but it may be useful
+// in cases when it's necessary to fill a certain buffer or object with
+// fuzzing data.
+inline size_t FuzzedDataProvider::ConsumeData(void *destination,
+                                              size_t num_bytes) {
+  num_bytes = std::min(num_bytes, remaining_bytes_);
+  CopyAndAdvance(destination, num_bytes);
+  return num_bytes;
+}
+
+// Private methods.
+inline void FuzzedDataProvider::CopyAndAdvance(void *destination,
+                                               size_t num_bytes) {
+  std::memcpy(destination, data_ptr_, num_bytes);
+  Advance(num_bytes);
+}
+
+inline void FuzzedDataProvider::Advance(size_t num_bytes) {
+  if (num_bytes > remaining_bytes_)
+    abort();
+
+  data_ptr_ += num_bytes;
+  remaining_bytes_ -= num_bytes;
+}
+
+template <typename T>
+std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t size, size_t num_bytes) {
+  static_assert(sizeof(T) == sizeof(uint8_t), "Incompatible data type.");
+
+  // The point of using the size-based constructor below is to increase the
+  // odds of having a vector object with capacity being equal to the length.
+  // That part is always implementation specific, but at least both libc++ and
+  // libstdc++ allocate the requested number of bytes in that constructor,
+  // which seems to be a natural choice for other implementations as well.
+  // To increase the odds even more, we also call |shrink_to_fit| below.
+  std::vector<T> result(size);
+  if (size == 0) {
+    if (num_bytes != 0)
+      abort();
+    return result;
+  }
+
+  CopyAndAdvance(result.data(), num_bytes);
+
+  // Even though |shrink_to_fit| is also implementation specific, we expect it
+  // to provide an additional assurance in case vector's constructor allocated
+  // a buffer which is larger than the actual amount of data we put inside it.
+  result.shrink_to_fit();
+  return result;
+}
+
+template <typename TS, typename TU>
+TS FuzzedDataProvider::ConvertUnsignedToSigned(TU value) {
+  static_assert(sizeof(TS) == sizeof(TU), "Incompatible data types.");
+  static_assert(!std::numeric_limits<TU>::is_signed,
+                "Source type must be unsigned.");
+
+  // TODO(Dor1s): change to `if constexpr` once C++17 becomes mainstream.
+  if (std::numeric_limits<TS>::is_modulo)
+    return static_cast<TS>(value);
+
+  // Avoid using implementation-defined unsigned to signed conversions.
+  // To learn more, see https://stackoverflow.com/questions/13150449.
+  if (value <= std::numeric_limits<TS>::max()) {
+    return static_cast<TS>(value);
+  } else {
+    constexpr auto TS_min = std::numeric_limits<TS>::min();
+    return TS_min + static_cast<char>(value - TS_min);
+  }
+}
+
+#endif // LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
diff --git a/cpp/tests/fuzzing/doc_fuzzer.cc b/cpp/tests/fuzzing/doc_fuzzer.cc
new file mode 100644
index 00000000..720909d3
--- /dev/null
+++ b/cpp/tests/fuzzing/doc_fuzzer.cc
@@ -0,0 +1,46 @@
+#include <cstdint>
+
+#include <poppler-global.h>
+#include <poppler-document.h>
+#include <poppler-page.h>
+#include "FuzzedDataProvider.h"
+
+#define INPUT_SIZE 32
+
+static void dummy_error_function(const std::string &, void *) { }
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+    poppler::set_debug_error_function(dummy_error_function, nullptr);
+    poppler::document *doc = poppler::document::load_from_raw_data((const char *)data, size);
+    if (!doc || doc->is_locked()) {
+        delete doc;
+        return 0;
+    }
+
+    FuzzedDataProvider data_provider(data, size);
+    std::string in_auth = data_provider.ConsumeBytesAsString(INPUT_SIZE);
+    std::string in_creat = data_provider.ConsumeBytesAsString(INPUT_SIZE);
+    std::string in_key = data_provider.ConsumeBytesAsString(INPUT_SIZE);
+    std::string in_prod = data_provider.ConsumeBytesAsString(INPUT_SIZE);
+    std::string in_sub = data_provider.ConsumeBytesAsString(INPUT_SIZE);
+    std::string in_title = data_provider.ConsumeBytesAsString(INPUT_SIZE);
+
+    // Testing both methods for conversion to ustring
+    doc->set_author(poppler::ustring::from_latin1(in_auth));
+    doc->set_creator(poppler::ustring::from_latin1(in_creat));
+    doc->set_keywords(poppler::ustring::from_latin1(in_key));
+    doc->set_producer(poppler::ustring::from_latin1(in_prod));
+    doc->set_subject(poppler::ustring::from_latin1(in_sub));
+    doc->set_title(poppler::ustring::from_latin1(in_title));
+
+    doc->set_author(poppler::ustring::from_utf8((const char*)data,size));
+    doc->set_creator(poppler::ustring::from_utf8((const char*)data,size));
+    doc->set_keywords(poppler::ustring::from_utf8((const char*)data,size));
+    doc->set_producer(poppler::ustring::from_utf8((const char*)data,size));
+    doc->set_subject(poppler::ustring::from_utf8((const char*)data,size));
+    doc->set_title(poppler::ustring::from_utf8((const char*)data,size));
+
+    delete doc;
+    return 0;
+}
diff --git a/cpp/tests/fuzzing/page_label_fuzzer.cc b/cpp/tests/fuzzing/page_label_fuzzer.cc
index ca168da3..510ca40d 100644
--- a/cpp/tests/fuzzing/page_label_fuzzer.cc
+++ b/cpp/tests/fuzzing/page_label_fuzzer.cc
@@ -1,21 +1,3 @@
-/*
-# Copyright 2018 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-*/
-
 #include <cstdint>
 
 #include <poppler-global.h>
diff --git a/cpp/tests/fuzzing/page_search_fuzzer.cc b/cpp/tests/fuzzing/page_search_fuzzer.cc
index 99fc99aa..24a4e23c 100644
--- a/cpp/tests/fuzzing/page_search_fuzzer.cc
+++ b/cpp/tests/fuzzing/page_search_fuzzer.cc
@@ -1,21 +1,3 @@
-/*
-# Copyright 2018 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-*/
-
 #include <cstdint>
 
 #include <poppler-global.h>
diff --git a/cpp/tests/fuzzing/pdf_file_fuzzer.cc b/cpp/tests/fuzzing/pdf_file_fuzzer.cc
index 6ee40e29..6a682a17 100644
--- a/cpp/tests/fuzzing/pdf_file_fuzzer.cc
+++ b/cpp/tests/fuzzing/pdf_file_fuzzer.cc
@@ -1,21 +1,3 @@
-/*
-# Copyright 2018 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-*/
-
 #include <cstdint>
 #include <string>
 
diff --git a/glib/tests/fuzzing/annot_fuzzer.c b/glib/tests/fuzzing/annot_fuzzer.c
index 3748e5d9..ad2f23d6 100644
--- a/glib/tests/fuzzing/annot_fuzzer.c
+++ b/glib/tests/fuzzing/annot_fuzzer.c
@@ -1,5 +1,9 @@
 #include <stdint.h>
 #include <poppler.h>
+#include <cairo.h>
+#include <cairo-pdf.h>
+
+#include "fuzzer_temp_file.h"
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
     GError *err = NULL;
@@ -7,8 +11,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
     PopplerPage *page;
     PopplerAnnot *annot;
     PopplerRectangle bb;
+    gdouble width, height;
     gboolean hg;
-    int npages, n;
+    int npages;
+
+    cairo_t *cr;
+    cairo_surface_t *surface;
+    cairo_status_t status;
 
     doc = poppler_document_new_from_data(data, size, NULL, &err);
     if (doc == NULL) {
@@ -17,22 +26,53 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
     }
     npages = poppler_document_get_n_pages(doc);
     if (npages < 1) {
+        g_object_unref(doc);
+        return 0;
+    }
+
+    char *tmpfile = fuzzer_get_tmpfile(data, size);
+    surface = cairo_pdf_surface_create(tmpfile, 1.0, 1.0);
+    status = cairo_surface_status(surface);
+    if (status != CAIRO_STATUS_SUCCESS) {
+        g_object_unref(doc);
+        fuzzer_release_tmpfile(tmpfile);
         return 0;
     }
 
-    for (n = 0; n < poppler_document_get_n_pages(doc); n++) {
+    for (int n = 0; n < npages; n++) {
         page = poppler_document_get_page(doc, n);
         if (!page) {
             continue;
         }
+
+        poppler_page_get_size(page, &width, &height);
+        cairo_pdf_surface_set_size(surface, width, height);
         hg = poppler_page_get_bounding_box(page, &bb);
         if (hg) {
             annot = poppler_annot_text_new(doc, &bb);
+            if (annot != NULL) {
+                g_object_unref(page);
+                continue;
+            }
             poppler_page_add_annot(page, annot);
-            poppler_annot_set_contents(annot, data);
-            poppler_annot_markup_set_label(annot, data);
+            /*poppler_annot_set_contents(annot, data);*/
+            /*poppler_annot_markup_set_label(annot, data);*/
+        }
+
+        cr = cairo_create(surface);
+        status = cairo_status(cr);
+        if (status != CAIRO_STATUS_SUCCESS) {
+            cairo_destroy(cr);
+            g_object_unref(page);
+            continue;
         }
+        poppler_page_render_for_printing(page, cr);
+        cairo_surface_show_page(surface);
+        cairo_destroy(cr);
         g_object_unref(page);
     }
+    cairo_surface_destroy(surface);
+    fuzzer_release_tmpfile(tmpfile);
+    g_object_unref(doc);
     return 0;
 }
diff --git a/glib/tests/fuzzing/doc_attr_fuzzer.c b/glib/tests/fuzzing/doc_attr_fuzzer.c
index bf4531b2..7fe0ee59 100644
--- a/glib/tests/fuzzing/doc_attr_fuzzer.c
+++ b/glib/tests/fuzzing/doc_attr_fuzzer.c
@@ -1,6 +1,5 @@
 #include <stdint.h>
 #include <poppler.h>
-#include <cairo.h>
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
     GError *err = NULL;
diff --git a/glib/tests/fuzzing/find_text_fuzzer.c b/glib/tests/fuzzing/find_text_fuzzer.c
index f1611328..207704a3 100644
--- a/glib/tests/fuzzing/find_text_fuzzer.c
+++ b/glib/tests/fuzzing/find_text_fuzzer.c
@@ -1,12 +1,11 @@
 #include <stdint.h>
 #include <poppler.h>
-#include <cairo.h>
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
     GError *err = NULL;
     PopplerDocument *doc;
     PopplerPage *page;
-    int npages, n;
+    int npages;
 
     doc = poppler_document_new_from_data(data, size, NULL, &err);
     if (doc == NULL) {
@@ -19,7 +18,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
         return 0;
     }
 
-    for (n = 0; n < poppler_document_get_n_pages(doc); n++) {
+    for (int n = 0; n < npages; n++) {
         page = poppler_document_get_page(doc, n);
         if (!page) {
             continue;
diff --git a/glib/tests/fuzzing/label_fuzzer.c b/glib/tests/fuzzing/label_fuzzer.c
index e70f6644..ee417a55 100644
--- a/glib/tests/fuzzing/label_fuzzer.c
+++ b/glib/tests/fuzzing/label_fuzzer.c
@@ -1,12 +1,11 @@
 #include <stdint.h>
 #include <poppler.h>
-#include <cairo.h>
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
     GError *err = NULL;
     PopplerDocument *doc;
     PopplerPage *page;
-    int npages, n;
+    int npages;
 
     doc = poppler_document_new_from_data(data, size, NULL, &err);
     if (doc == NULL) {
@@ -19,7 +18,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
         return 0;
     }
 
-    for (n = 0; n < poppler_document_get_n_pages(doc); n++) {
+    for (int n = 0; n < npages; n++) {
         page = poppler_document_get_page_by_label(doc, data);
         if (!page) {
             continue;
diff --git a/glib/tests/fuzzing/pdf_draw_fuzzer.c b/glib/tests/fuzzing/pdf_draw_fuzzer.c
index 24abdc43..f0881e16 100644
--- a/glib/tests/fuzzing/pdf_draw_fuzzer.c
+++ b/glib/tests/fuzzing/pdf_draw_fuzzer.c
@@ -12,10 +12,11 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
     PopplerRectangle bb;
     gdouble width, height;
     gboolean hg;
-    int npages, n;
+    int npages;
 
-    cairo_surface_t *surface;
     cairo_t *cr;
+    cairo_surface_t *surface;
+    cairo_status_t status;
 
     doc = poppler_document_new_from_data(data, size, NULL, &err);
     if (doc == NULL) {
@@ -31,31 +32,43 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
 
     char *tmpfile = fuzzer_get_tmpfile(data, size);
     surface = cairo_pdf_surface_create(tmpfile, 1.0, 1.0);
+    status = cairo_surface_status(surface);
+    if (status != CAIRO_STATUS_SUCCESS) {
+        g_object_unref(doc);
+        fuzzer_release_tmpfile(tmpfile);
+        return 0;
+    }
 
-    for (n = 0; n < poppler_document_get_n_pages(doc); n++) {
+    for (int n = 0; n < npages; n++) {
         page = poppler_document_get_page(doc, n);
         if (!page) {
             continue;
         }
+
         poppler_page_get_size(page, &width, &height);
         cairo_pdf_surface_set_size(surface, width, height);
         hg = poppler_page_get_bounding_box(page, &bb);
 
         cr = cairo_create(surface);
-        poppler_page_render_for_printing(page, cr);
+        status = cairo_status(cr);
+        if (status != CAIRO_STATUS_SUCCESS) {
+            g_object_unref(page);
+            continue;
+
+        }
         if (hg) {
-            cairo_set_source_rgb(cr, 1.6, 1.6, 1.6);
+            cairo_set_source_rgb(cr, 0.6, 0.6, 1.0);
             cairo_rectangle(cr, bb.x1, bb.y1, bb.x2 - bb.x1, bb.y2 - bb.y1);
             cairo_stroke(cr);
         }
-        cairo_destroy(cr);
-        cairo_surface_show_page(surface);
 
+        poppler_page_render_for_printing(page, cr);
+        cairo_surface_show_page(surface);
+        cairo_destroy(cr);
         g_object_unref(page);
     }
-
-    g_object_unref(doc);
     cairo_surface_destroy(surface);
+    g_object_unref(doc);
     fuzzer_release_tmpfile(tmpfile);
     return 0;
 }
diff --git a/glib/tests/fuzzing/util_fuzzer.c b/glib/tests/fuzzing/util_fuzzer.c
index 3514cd73..752e46d9 100644
--- a/glib/tests/fuzzing/util_fuzzer.c
+++ b/glib/tests/fuzzing/util_fuzzer.c
@@ -1,12 +1,9 @@
 #include <stdint.h>
 #include <poppler.h>
-#include <cairo.h>
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
     gsize length;
     poppler_named_dest_from_bytestring(data, size);
     poppler_named_dest_to_bytestring(data, &length);
-    /*poppler_named_dest_from_bytestring((const guint8*)data, size);*/
-    /*poppler_named_dest_to_bytestring((const char*)data, &length);*/
     return 0;
 }
diff --git a/qt5/tests/CMakeLists.txt b/qt5/tests/CMakeLists.txt
index 5f542440..b8b5a399 100644
--- a/qt5/tests/CMakeLists.txt
+++ b/qt5/tests/CMakeLists.txt
@@ -43,6 +43,14 @@ macro(QT5_ADD_QTEST exe source)
   endif ()
 endmacro(QT5_ADD_QTEST)
 
+macro(QT_ADD_FUZZER exe)
+  string(REPLACE "-" "" test_name ${exe})
+  set(${test_name}_SOURCES
+    ${ARGN}
+  )
+  poppler_add_test(${exe} BUILD_QT5_TESTS ${${test_name}_SOURCES})
+  target_link_libraries(${exe} poppler-qt5 ${Qt5Widgets_LIBRARIES} ${Qt5Test_LIBRARIES} ${Qt5Core_LIBRARIES} ${Qt5Gui_LIBRARIES})
+endmacro(QT_ADD_FUZZER)
 
 qt5_add_simpletest(test-poppler-qt5 test-poppler-qt5.cpp)
 qt5_add_simpletest(test-password-qt5 test-password-qt5.cpp)
@@ -80,3 +88,11 @@ if (NOT WIN32)
   qt5_add_qtest(check_qt5_pagelabelinfo check_pagelabelinfo.cpp)
   qt5_add_qtest(check_qt5_strings check_strings.cpp)
 endif ()
+
+if(ENABLE_FUZZER)
+    qt_add_fuzzer(qt_annot_fuzzer ./fuzzing/qt_annot_fuzzer.cc)
+    qt_add_fuzzer(qt_pdf_fuzzer ./fuzzing/qt_pdf_fuzzer.cc)
+    qt_add_fuzzer(qt_label_fuzzer ./fuzzing/qt_label_fuzzer.cc)
+    qt_add_fuzzer(qt_search_fuzzer ./fuzzing/qt_search_fuzzer.cc)
+    qt_add_fuzzer(qt_textbox_fuzzer ./fuzzing/qt_textbox_fuzzer.cc)
+endif()
diff --git a/qt5/tests/fuzzing/FuzzedDataProvider.h b/qt5/tests/fuzzing/FuzzedDataProvider.h
new file mode 100644
index 00000000..83bcd013
--- /dev/null
+++ b/qt5/tests/fuzzing/FuzzedDataProvider.h
@@ -0,0 +1,387 @@
+//===- FuzzedDataProvider.h - Utility header for fuzz targets ---*- C++ -* ===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// A single header library providing an utility class to break up an array of
+// bytes. Whenever run on the same input, provides the same output, as long as
+// its methods are called in the same order, with the same arguments.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
+#define LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
+
+#include <algorithm>
+#include <climits>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <initializer_list>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+// In addition to the comments below, the API is also briefly documented at
+// https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider
+class FuzzedDataProvider {
+ public:
+  // |data| is an array of length |size| that the FuzzedDataProvider wraps to
+  // provide more granular access. |data| must outlive the FuzzedDataProvider.
+  FuzzedDataProvider(const uint8_t *data, size_t size)
+      : data_ptr_(data), remaining_bytes_(size) {}
+  ~FuzzedDataProvider() = default;
+
+  // See the implementation below (after the class definition) for more verbose
+  // comments for each of the methods.
+
+  // Methods returning std::vector of bytes. These are the most popular choice
+  // when splitting fuzzing input into pieces, as every piece is put into a
+  // separate buffer (i.e. ASan would catch any under-/overflow) and the memory
+  // will be released automatically.
+  template <typename T> std::vector<T> ConsumeBytes(size_t num_bytes);
+  template <typename T>
+  std::vector<T> ConsumeBytesWithTerminator(size_t num_bytes, T terminator = 0);
+  template <typename T> std::vector<T> ConsumeRemainingBytes();
+
+  // Methods returning strings. Use only when you need a std::string or a null
+  // terminated C-string. Otherwise, prefer the methods returning std::vector.
+  std::string ConsumeBytesAsString(size_t num_bytes);
+  std::string ConsumeRandomLengthString(size_t max_length);
+  std::string ConsumeRandomLengthString();
+  std::string ConsumeRemainingBytesAsString();
+
+  // Methods returning integer values.
+  template <typename T> T ConsumeIntegral();
+  template <typename T> T ConsumeIntegralInRange(T min, T max);
+
+  // Methods returning floating point values.
+  template <typename T> T ConsumeFloatingPoint();
+  template <typename T> T ConsumeFloatingPointInRange(T min, T max);
+
+  // 0 <= return value <= 1.
+  template <typename T> T ConsumeProbability();
+
+  bool ConsumeBool();
+
+  // Returns a value chosen from the given enum.
+  template <typename T> T ConsumeEnum();
+
+  // Returns a value from the given array.
+  template <typename T, size_t size> T PickValueInArray(const T (&array)[size]);
+  template <typename T> T PickValueInArray(std::initializer_list<const T> list);
+
+  // Writes data to the given destination and returns number of bytes written.
+  size_t ConsumeData(void *destination, size_t num_bytes);
+
+  // Reports the remaining bytes available for fuzzed input.
+  size_t remaining_bytes() { return remaining_bytes_; }
+
+ private:
+  FuzzedDataProvider(const FuzzedDataProvider &) = delete;
+  FuzzedDataProvider &operator=(const FuzzedDataProvider &) = delete;
+
+  void CopyAndAdvance(void *destination, size_t num_bytes);
+
+  void Advance(size_t num_bytes);
+
+  template <typename T>
+  std::vector<T> ConsumeBytes(size_t size, size_t num_bytes);
+
+  template <typename TS, typename TU> TS ConvertUnsignedToSigned(TU value);
+
+  const uint8_t *data_ptr_;
+  size_t remaining_bytes_;
+};
+
+// Returns a std::vector containing |num_bytes| of input data. If fewer than
+// |num_bytes| of data remain, returns a shorter std::vector containing all
+// of the data that's left. Can be used with any byte sized type, such as
+// char, unsigned char, uint8_t, etc.
+template <typename T>
+std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t num_bytes) {
+  num_bytes = std::min(num_bytes, remaining_bytes_);
+  return ConsumeBytes<T>(num_bytes, num_bytes);
+}
+
+// Similar to |ConsumeBytes|, but also appends the terminator value at the end
+// of the resulting vector. Useful, when a mutable null-terminated C-string is
+// needed, for example. But that is a rare case. Better avoid it, if possible,
+// and prefer using |ConsumeBytes| or |ConsumeBytesAsString| methods.
+template <typename T>
+std::vector<T> FuzzedDataProvider::ConsumeBytesWithTerminator(size_t num_bytes,
+                                                              T terminator) {
+  num_bytes = std::min(num_bytes, remaining_bytes_);
+  std::vector<T> result = ConsumeBytes<T>(num_bytes + 1, num_bytes);
+  result.back() = terminator;
+  return result;
+}
+
+// Returns a std::vector containing all remaining bytes of the input data.
+template <typename T>
+std::vector<T> FuzzedDataProvider::ConsumeRemainingBytes() {
+  return ConsumeBytes<T>(remaining_bytes_);
+}
+
+// Returns a std::string containing |num_bytes| of input data. Using this and
+// |.c_str()| on the resulting string is the best way to get an immutable
+// null-terminated C string. If fewer than |num_bytes| of data remain, returns
+// a shorter std::string containing all of the data that's left.
+inline std::string FuzzedDataProvider::ConsumeBytesAsString(size_t num_bytes) {
+  static_assert(sizeof(std::string::value_type) == sizeof(uint8_t),
+                "ConsumeBytesAsString cannot convert the data to a string.");
+
+  num_bytes = std::min(num_bytes, remaining_bytes_);
+  std::string result(
+      reinterpret_cast<const std::string::value_type *>(data_ptr_), num_bytes);
+  Advance(num_bytes);
+  return result;
+}
+
+// Returns a std::string of length from 0 to |max_length|. When it runs out of
+// input data, returns what remains of the input. Designed to be more stable
+// with respect to a fuzzer inserting characters than just picking a random
+// length and then consuming that many bytes with |ConsumeBytes|.
+inline std::string
+FuzzedDataProvider::ConsumeRandomLengthString(size_t max_length) {
+  // Reads bytes from the start of |data_ptr_|. Maps "\\" to "\", and maps "\"
+  // followed by anything else to the end of the string. As a result of this
+  // logic, a fuzzer can insert characters into the string, and the string
+  // will be lengthened to include those new characters, resulting in a more
+  // stable fuzzer than picking the length of a string independently from
+  // picking its contents.
+  std::string result;
+
+  // Reserve the anticipated capaticity to prevent several reallocations.
+  result.reserve(std::min(max_length, remaining_bytes_));
+  for (size_t i = 0; i < max_length && remaining_bytes_ != 0; ++i) {
+    char next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
+    Advance(1);
+    if (next == '\\' && remaining_bytes_ != 0) {
+      next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
+      Advance(1);
+      if (next != '\\')
+        break;
+    }
+    result += next;
+  }
+
+  result.shrink_to_fit();
+  return result;
+}
+
+// Returns a std::string of length from 0 to |remaining_bytes_|.
+inline std::string FuzzedDataProvider::ConsumeRandomLengthString() {
+  return ConsumeRandomLengthString(remaining_bytes_);
+}
+
+// Returns a std::string containing all remaining bytes of the input data.
+// Prefer using |ConsumeRemainingBytes| unless you actually need a std::string
+// object.
+inline std::string FuzzedDataProvider::ConsumeRemainingBytesAsString() {
+  return ConsumeBytesAsString(remaining_bytes_);
+}
+
+// Returns a number in the range [Type's min, Type's max]. The value might
+// not be uniformly distributed in the given range. If there's no input data
+// left, always returns |min|.
+template <typename T> T FuzzedDataProvider::ConsumeIntegral() {
+  return ConsumeIntegralInRange(std::numeric_limits<T>::min(),
+                                std::numeric_limits<T>::max());
+}
+
+// Returns a number in the range [min, max] by consuming bytes from the
+// input data. The value might not be uniformly distributed in the given
+// range. If there's no input data left, always returns |min|. |min| must
+// be less than or equal to |max|.
+template <typename T>
+T FuzzedDataProvider::ConsumeIntegralInRange(T min, T max) {
+  static_assert(std::is_integral<T>::value, "An integral type is required.");
+  static_assert(sizeof(T) <= sizeof(uint64_t), "Unsupported integral type.");
+
+  if (min > max)
+    abort();
+
+  // Use the biggest type possible to hold the range and the result.
+  uint64_t range = static_cast<uint64_t>(max) - min;
+  uint64_t result = 0;
+  size_t offset = 0;
+
+  while (offset < sizeof(T) * CHAR_BIT && (range >> offset) > 0 &&
+         remaining_bytes_ != 0) {
+    // Pull bytes off the end of the seed data. Experimentally, this seems to
+    // allow the fuzzer to more easily explore the input space. This makes
+    // sense, since it works by modifying inputs that caused new code to run,
+    // and this data is often used to encode length of data read by
+    // |ConsumeBytes|. Separating out read lengths makes it easier modify the
+    // contents of the data that is actually read.
+    --remaining_bytes_;
+    result = (result << CHAR_BIT) | data_ptr_[remaining_bytes_];
+    offset += CHAR_BIT;
+  }
+
+  // Avoid division by 0, in case |range + 1| results in overflow.
+  if (range != std::numeric_limits<decltype(range)>::max())
+    result = result % (range + 1);
+
+  return static_cast<T>(min + result);
+}
+
+// Returns a floating point value in the range [Type's lowest, Type's max] by
+// consuming bytes from the input data. If there's no input data left, always
+// returns approximately 0.
+template <typename T> T FuzzedDataProvider::ConsumeFloatingPoint() {
+  return ConsumeFloatingPointInRange<T>(std::numeric_limits<T>::lowest(),
+                                        std::numeric_limits<T>::max());
+}
+
+// Returns a floating point value in the given range by consuming bytes from
+// the input data. If there's no input data left, returns |min|. Note that
+// |min| must be less than or equal to |max|.
+template <typename T>
+T FuzzedDataProvider::ConsumeFloatingPointInRange(T min, T max) {
+  if (min > max)
+    abort();
+
+  T range = .0;
+  T result = min;
+  constexpr T zero(.0);
+  if (max > zero && min < zero && max > min + std::numeric_limits<T>::max()) {
+    // The diff |max - min| would overflow the given floating point type. Use
+    // the half of the diff as the range and consume a bool to decide whether
+    // the result is in the first of the second part of the diff.
+    range = (max / 2.0) - (min / 2.0);
+    if (ConsumeBool()) {
+      result += range;
+    }
+  } else {
+    range = max - min;
+  }
+
+  return result + range * ConsumeProbability<T>();
+}
+
+// Returns a floating point number in the range [0.0, 1.0]. If there's no
+// input data left, always returns 0.
+template <typename T> T FuzzedDataProvider::ConsumeProbability() {
+  static_assert(std::is_floating_point<T>::value,
+                "A floating point type is required.");
+
+  // Use different integral types for different floating point types in order
+  // to provide better density of the resulting values.
+  using IntegralType =
+      typename std::conditional<(sizeof(T) <= sizeof(uint32_t)), uint32_t,
+                                uint64_t>::type;
+
+  T result = static_cast<T>(ConsumeIntegral<IntegralType>());
+  result /= static_cast<T>(std::numeric_limits<IntegralType>::max());
+  return result;
+}
+
+// Reads one byte and returns a bool, or false when no data remains.
+inline bool FuzzedDataProvider::ConsumeBool() {
+  return 1 & ConsumeIntegral<uint8_t>();
+}
+
+// Returns an enum value. The enum must start at 0 and be contiguous. It must
+// also contain |kMaxValue| aliased to its largest (inclusive) value. Such as:
+// enum class Foo { SomeValue, OtherValue, kMaxValue = OtherValue };
+template <typename T> T FuzzedDataProvider::ConsumeEnum() {
+  static_assert(std::is_enum<T>::value, "|T| must be an enum type.");
+  return static_cast<T>(
+      ConsumeIntegralInRange<uint32_t>(0, static_cast<uint32_t>(T::kMaxValue)));
+}
+
+// Returns a copy of the value selected from the given fixed-size |array|.
+template <typename T, size_t size>
+T FuzzedDataProvider::PickValueInArray(const T (&array)[size]) {
+  static_assert(size > 0, "The array must be non empty.");
+  return array[ConsumeIntegralInRange<size_t>(0, size - 1)];
+}
+
+template <typename T>
+T FuzzedDataProvider::PickValueInArray(std::initializer_list<const T> list) {
+  // TODO(Dor1s): switch to static_assert once C++14 is allowed.
+  if (!list.size())
+    abort();
+
+  return *(list.begin() + ConsumeIntegralInRange<size_t>(0, list.size() - 1));
+}
+
+// Writes |num_bytes| of input data to the given destination pointer. If there
+// is not enough data left, writes all remaining bytes. Return value is the
+// number of bytes written.
+// In general, it's better to avoid using this function, but it may be useful
+// in cases when it's necessary to fill a certain buffer or object with
+// fuzzing data.
+inline size_t FuzzedDataProvider::ConsumeData(void *destination,
+                                              size_t num_bytes) {
+  num_bytes = std::min(num_bytes, remaining_bytes_);
+  CopyAndAdvance(destination, num_bytes);
+  return num_bytes;
+}
+
+// Private methods.
+inline void FuzzedDataProvider::CopyAndAdvance(void *destination,
+                                               size_t num_bytes) {
+  std::memcpy(destination, data_ptr_, num_bytes);
+  Advance(num_bytes);
+}
+
+inline void FuzzedDataProvider::Advance(size_t num_bytes) {
+  if (num_bytes > remaining_bytes_)
+    abort();
+
+  data_ptr_ += num_bytes;
+  remaining_bytes_ -= num_bytes;
+}
+
+template <typename T>
+std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t size, size_t num_bytes) {
+  static_assert(sizeof(T) == sizeof(uint8_t), "Incompatible data type.");
+
+  // The point of using the size-based constructor below is to increase the
+  // odds of having a vector object with capacity being equal to the length.
+  // That part is always implementation specific, but at least both libc++ and
+  // libstdc++ allocate the requested number of bytes in that constructor,
+  // which seems to be a natural choice for other implementations as well.
+  // To increase the odds even more, we also call |shrink_to_fit| below.
+  std::vector<T> result(size);
+  if (size == 0) {
+    if (num_bytes != 0)
+      abort();
+    return result;
+  }
+
+  CopyAndAdvance(result.data(), num_bytes);
+
+  // Even though |shrink_to_fit| is also implementation specific, we expect it
+  // to provide an additional assurance in case vector's constructor allocated
+  // a buffer which is larger than the actual amount of data we put inside it.
+  result.shrink_to_fit();
+  return result;
+}
+
+template <typename TS, typename TU>
+TS FuzzedDataProvider::ConvertUnsignedToSigned(TU value) {
+  static_assert(sizeof(TS) == sizeof(TU), "Incompatible data types.");
+  static_assert(!std::numeric_limits<TU>::is_signed,
+                "Source type must be unsigned.");
+
+  // TODO(Dor1s): change to `if constexpr` once C++17 becomes mainstream.
+  if (std::numeric_limits<TS>::is_modulo)
+    return static_cast<TS>(value);
+
+  // Avoid using implementation-defined unsigned to signed conversions.
+  // To learn more, see https://stackoverflow.com/questions/13150449.
+  if (value <= std::numeric_limits<TS>::max()) {
+    return static_cast<TS>(value);
+  } else {
+    constexpr auto TS_min = std::numeric_limits<TS>::min();
+    return TS_min + static_cast<char>(value - TS_min);
+  }
+}
+
+#endif // LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
diff --git a/qt5/tests/fuzzing/fuzzer_temp_file.h b/qt5/tests/fuzzing/fuzzer_temp_file.h
new file mode 100644
index 00000000..fe25caba
--- /dev/null
+++ b/qt5/tests/fuzzing/fuzzer_temp_file.h
@@ -0,0 +1,81 @@
+// Copyright 2018 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Adapter utility from fuzzer input to a temporary file, for fuzzing APIs that
+// require a file instead of an input buffer.
+
+#ifndef FUZZER_TEMP_FILE_H_
+#define FUZZER_TEMP_FILE_H_
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+// Pure-C interface for creating and cleaning up temporary files.
+
+static char* fuzzer_get_tmpfile(const uint8_t* data, size_t size) {
+  char* filename_buffer = strdup("/tmp/generate_temporary_file.XXXXXX");
+  if (!filename_buffer) {
+    perror("Failed to allocate file name buffer.");
+    abort();
+  }
+  const int file_descriptor = mkstemp(filename_buffer);
+  if (file_descriptor < 0) {
+    perror("Failed to make temporary file.");
+    abort();
+  }
+  FILE* file = fdopen(file_descriptor, "wb");
+  if (!file) {
+    perror("Failed to open file descriptor.");
+    close(file_descriptor);
+    abort();
+  }
+  const size_t bytes_written = fwrite(data, sizeof(uint8_t), size, file);
+  if (bytes_written < size) {
+    close(file_descriptor);
+    fprintf(stderr, "Failed to write all bytes to file (%zu out of %zu)",
+            bytes_written, size);
+    abort();
+  }
+  fclose(file);
+  return filename_buffer;
+}
+
+static void fuzzer_release_tmpfile(char* filename) {
+  if (unlink(filename) != 0) {
+    perror("WARNING: Failed to delete temporary file.");
+  }
+  free(filename);
+}
+
+// C++ RAII object for creating temporary files.
+
+#ifdef __cplusplus
+class FuzzerTemporaryFile {
+ public:
+  FuzzerTemporaryFile(const uint8_t* data, size_t size)
+      : filename_(fuzzer_get_tmpfile(data, size)) {}
+
+  ~FuzzerTemporaryFile() { fuzzer_release_tmpfile(filename_); }
+
+  const char* filename() const { return filename_; }
+
+ private:
+  char* filename_;
+};
+#endif
+
+#endif  // FUZZER_TEMP_FILE_H_
diff --git a/qt5/tests/fuzzing/qt_annot_fuzzer.cc b/qt5/tests/fuzzing/qt_annot_fuzzer.cc
new file mode 100644
index 00000000..1e6de148
--- /dev/null
+++ b/qt5/tests/fuzzing/qt_annot_fuzzer.cc
@@ -0,0 +1,46 @@
+#include <cstdint>
+#include <poppler-qt5.h>
+#include "fuzzer_temp_file.h"
+
+static void dummy_error_function(const QString &, const QVariant &) { }
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+    Poppler::setDebugErrorFunction(dummy_error_function, QVariant());
+    const QFont font(QStringLiteral("Helvetica"), 20);
+    const QColor color = QColor::fromRgb(0xAB, 0xCD, 0xEF);
+    char *tmpfile = fuzzer_get_tmpfile(data, size);
+
+    QByteArray in_data = QByteArray::fromRawData((const char*)data, size);
+    Poppler::Document *doc = Poppler::Document::loadFromData(in_data);
+
+    if (!doc || doc->isLocked()){
+        delete doc;
+        fuzzer_release_tmpfile(tmpfile);
+        return 0;
+    }
+
+    for (int i = 0; i < doc->numPages(); i++) {
+        Poppler::Page* p = doc->page(i);
+        if (!p) {
+            continue;
+        }
+        Poppler::TextAnnotation *ann = new Poppler::TextAnnotation(Poppler::TextAnnotation::InPlace);
+        ann->setTextFont(font);
+        ann->setTextColor(color);
+        ann->setBoundary(QRectF(0.1, 0.1, 0.2, 0.2));
+        ann->setContents(QString(in_data));
+        p->addAnnotation(ann);
+
+        std::unique_ptr<Poppler::PDFConverter> conv(doc->pdfConverter());
+        conv->setOutputFileName(tmpfile);
+        conv->setPDFOptions(Poppler::PDFConverter::WithChanges);
+        conv->convert();
+        delete ann;
+        delete p;
+    }
+
+    fuzzer_release_tmpfile(tmpfile);
+    delete doc;
+    return 0;
+}
diff --git a/qt5/tests/fuzzing/qt_label_fuzzer.cc b/qt5/tests/fuzzing/qt_label_fuzzer.cc
new file mode 100644
index 00000000..64049fcc
--- /dev/null
+++ b/qt5/tests/fuzzing/qt_label_fuzzer.cc
@@ -0,0 +1,29 @@
+#include <cstdint>
+#include <poppler-qt5.h>
+#include <QtGui/QImage>
+
+static void dummy_error_function(const QString &, const QVariant &) { }
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+    Poppler::setDebugErrorFunction(dummy_error_function, QVariant());
+    QByteArray in_data = QByteArray::fromRawData((const char*)data, size);
+    Poppler::Document *doc = Poppler::Document::loadFromData(in_data);
+    if (!doc || doc->isLocked()){
+        delete doc;
+        return 0;
+    }
+
+    for (int i = 0; i < doc->numPages(); i++) {
+        QString label = QString(in_data);
+        Poppler::Page* p = doc->page(label);
+        if (!p) {
+            continue;
+        }
+        QImage image = p->renderToImage(72.0, 72.0, -1, -1, -1, -1, Poppler::Page::Rotate0);
+        delete p;
+    }
+
+    delete doc;
+    return 0;
+}
diff --git a/qt5/tests/fuzzing/qt_pdf_fuzzer.cc b/qt5/tests/fuzzing/qt_pdf_fuzzer.cc
new file mode 100644
index 00000000..1398b28a
--- /dev/null
+++ b/qt5/tests/fuzzing/qt_pdf_fuzzer.cc
@@ -0,0 +1,27 @@
+#include <cstdint>
+#include <poppler-qt5.h>
+#include <QtGui/QImage>
+
+static void dummy_error_function(const QString &, const QVariant &) { }
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+    Poppler::setDebugErrorFunction(dummy_error_function, QVariant());
+    QByteArray in_data = QByteArray::fromRawData((const char*)data, size);
+    Poppler::Document *doc = Poppler::Document::loadFromData(in_data);
+    if (!doc || doc->isLocked()){
+        delete doc;
+        return 0;
+    }
+
+    for (int i = 0; i < doc->numPages(); i++) {
+        Poppler::Page* p = doc->page(i);
+        if (!p) {
+            continue;
+        }
+        QImage image = p->renderToImage(72.0, 72.0, -1, -1, -1, -1, Poppler::Page::Rotate0);
+        delete p;
+    }
+    delete doc;
+    return 0;
+}
diff --git a/qt5/tests/fuzzing/qt_search_fuzzer.cc b/qt5/tests/fuzzing/qt_search_fuzzer.cc
new file mode 100644
index 00000000..6d00720a
--- /dev/null
+++ b/qt5/tests/fuzzing/qt_search_fuzzer.cc
@@ -0,0 +1,28 @@
+#include <cstdint>
+#include <poppler-qt5.h>
+
+static void dummy_error_function(const QString &, const QVariant &) { }
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+    Poppler::setDebugErrorFunction(dummy_error_function, QVariant());
+    QByteArray in_data = QByteArray::fromRawData((const char*)data, size);
+    Poppler::Document *doc = Poppler::Document::loadFromData(in_data);
+    if (!doc || doc->isLocked()){
+        delete doc;
+        return 0;
+    }
+
+    for (int i = 0; i < doc->numPages(); i++) {
+        Poppler::Page* p = doc->page(i);
+        if (!p) {
+            continue;
+        }
+        QString text = QString(in_data);
+        p->search(text, Poppler::Page::IgnoreCase, Poppler::Page::Rotate0);
+        delete p;
+    }
+
+    delete doc;
+    return 0;
+}
diff --git a/qt5/tests/fuzzing/qt_textbox_fuzzer.cc b/qt5/tests/fuzzing/qt_textbox_fuzzer.cc
new file mode 100644
index 00000000..e90dbaab
--- /dev/null
+++ b/qt5/tests/fuzzing/qt_textbox_fuzzer.cc
@@ -0,0 +1,32 @@
+#include <cstdint>
+#include <poppler-qt5.h>
+#include <QtGui/QImage>
+#include <QtGui/QPainter>
+
+static void dummy_error_function(const QString &, const QVariant &) { }
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+    Poppler::setDebugErrorFunction(dummy_error_function, QVariant());
+    QByteArray in_data = QByteArray::fromRawData((const char*)data, size);
+    Poppler::Document *doc = Poppler::Document::loadFromData(in_data);
+    if (!doc || doc->isLocked()){
+        delete doc;
+        return 0;
+    }
+
+    for (int i = 0; i < doc->numPages(); i++) {
+        Poppler::Page* p = doc->page(i);
+        if (!p) {
+            continue;
+        }
+        QRectF rf = QRectF(0.0, 0.0, 1.0, 1.0);
+        Poppler::TextBox tb(QString(in_data), rf);
+        QImage image = p->renderToImage(72.0, 72.0, -1, -1, -1, -1, Poppler::Page::Rotate0);
+        QPainter painter(&image);
+        painter.drawRect(tb.boundingBox());
+        delete p;
+    }
+    delete doc;
+    return 0;
+}
commit 8b991bcf392c6c7e8957f4e18f3ca9437fcf4797
Author: Ceyhun Alp <ceyhunalp at google.com>
Date:   Mon Oct 12 23:05:37 2020 +0000

    Fuzzers for glib

diff --git a/glib/tests/CMakeLists.txt b/glib/tests/CMakeLists.txt
index 5f49511c..12f933b6 100644
--- a/glib/tests/CMakeLists.txt
+++ b/glib/tests/CMakeLists.txt
@@ -52,3 +52,21 @@ poppler_add_testcase(poppler-check-bb type3.pdf -p 10 125.80 130 509.30 695 125.
 
 add_executable(pdfdrawbb pdfdrawbb.c)
 target_link_libraries(pdfdrawbb poppler-glib)
+
+macro(GLIB_ADD_FUZZER exe)
+  string(REPLACE "-" "" test_name ${exe})
+  set(${test_name}_SOURCES
+    ${ARGN}
+  )
+  poppler_add_test(${exe} BUILD_GTK_TESTS ${${test_name}_SOURCES})
+  target_link_libraries(${exe} poppler-glib ${GTK3_LIBRARIES})
+endmacro(GLIB_ADD_FUZZER)
+
+if(ENABLE_FUZZER)
+    glib_add_fuzzer(annot_fuzzer ./fuzzing/annot_fuzzer.c)
+    glib_add_fuzzer(doc_attr_fuzzer ./fuzzing/doc_attr_fuzzer.c)
+    glib_add_fuzzer(find_text_fuzzer ./fuzzing/find_text_fuzzer.c)
+    glib_add_fuzzer(util_fuzzer ./fuzzing/util_fuzzer.c)
+    glib_add_fuzzer(label_fuzzer ./fuzzing/label_fuzzer.c)
+    glib_add_fuzzer(pdf_draw_fuzzer ./fuzzing/pdf_draw_fuzzer.c)
+endif()
diff --git a/glib/tests/fuzzing/annot_fuzzer.c b/glib/tests/fuzzing/annot_fuzzer.c
new file mode 100644
index 00000000..3748e5d9
--- /dev/null
+++ b/glib/tests/fuzzing/annot_fuzzer.c
@@ -0,0 +1,38 @@
+#include <stdint.h>
+#include <poppler.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    GError *err = NULL;
+    PopplerDocument *doc;
+    PopplerPage *page;
+    PopplerAnnot *annot;
+    PopplerRectangle bb;
+    gboolean hg;
+    int npages, n;
+
+    doc = poppler_document_new_from_data(data, size, NULL, &err);
+    if (doc == NULL) {
+        g_error_free(err);
+        return 0;
+    }
+    npages = poppler_document_get_n_pages(doc);
+    if (npages < 1) {
+        return 0;
+    }
+
+    for (n = 0; n < poppler_document_get_n_pages(doc); n++) {
+        page = poppler_document_get_page(doc, n);
+        if (!page) {
+            continue;
+        }
+        hg = poppler_page_get_bounding_box(page, &bb);
+        if (hg) {
+            annot = poppler_annot_text_new(doc, &bb);
+            poppler_page_add_annot(page, annot);
+            poppler_annot_set_contents(annot, data);
+            poppler_annot_markup_set_label(annot, data);
+        }
+        g_object_unref(page);
+    }
+    return 0;
+}
diff --git a/glib/tests/fuzzing/doc_attr_fuzzer.c b/glib/tests/fuzzing/doc_attr_fuzzer.c
new file mode 100644
index 00000000..bf4531b2
--- /dev/null
+++ b/glib/tests/fuzzing/doc_attr_fuzzer.c
@@ -0,0 +1,23 @@
+#include <stdint.h>
+#include <poppler.h>
+#include <cairo.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    GError *err = NULL;
+    PopplerDocument *doc;
+    PopplerPage *page;
+    int npages, n;
+
+    doc = poppler_document_new_from_data(data, size, NULL, &err);
+    if (doc == NULL) {
+        g_error_free(err);
+        return 0;
+    }
+    poppler_document_set_author(doc, data);
+    poppler_document_set_creator(doc, data);
+    poppler_document_set_keywords(doc, data);
+    poppler_document_set_producer(doc, data);
+    poppler_document_set_subject(doc, data);
+    poppler_document_set_title(doc, data);
+    return 0;
+}
diff --git a/glib/tests/fuzzing/find_text_fuzzer.c b/glib/tests/fuzzing/find_text_fuzzer.c
new file mode 100644
index 00000000..f1611328
--- /dev/null
+++ b/glib/tests/fuzzing/find_text_fuzzer.c
@@ -0,0 +1,31 @@
+#include <stdint.h>
+#include <poppler.h>
+#include <cairo.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    GError *err = NULL;
+    PopplerDocument *doc;
+    PopplerPage *page;
+    int npages, n;
+
+    doc = poppler_document_new_from_data(data, size, NULL, &err);
+    if (doc == NULL) {
+        g_error_free(err);
+        return 0;
+    }
+
+    npages = poppler_document_get_n_pages(doc);
+    if (npages < 1) {
+        return 0;
+    }
+
+    for (n = 0; n < poppler_document_get_n_pages(doc); n++) {
+        page = poppler_document_get_page(doc, n);
+        if (!page) {
+            continue;
+        }
+        poppler_page_find_text(page, data);
+        g_object_unref(page);
+    }
+    return 0;
+}
diff --git a/glib/tests/fuzzing/fuzzer_temp_file.h b/glib/tests/fuzzing/fuzzer_temp_file.h
new file mode 100644
index 00000000..fe25caba
--- /dev/null
+++ b/glib/tests/fuzzing/fuzzer_temp_file.h
@@ -0,0 +1,81 @@
+// Copyright 2018 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Adapter utility from fuzzer input to a temporary file, for fuzzing APIs that
+// require a file instead of an input buffer.
+
+#ifndef FUZZER_TEMP_FILE_H_
+#define FUZZER_TEMP_FILE_H_
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+// Pure-C interface for creating and cleaning up temporary files.
+
+static char* fuzzer_get_tmpfile(const uint8_t* data, size_t size) {
+  char* filename_buffer = strdup("/tmp/generate_temporary_file.XXXXXX");
+  if (!filename_buffer) {
+    perror("Failed to allocate file name buffer.");
+    abort();
+  }
+  const int file_descriptor = mkstemp(filename_buffer);
+  if (file_descriptor < 0) {
+    perror("Failed to make temporary file.");
+    abort();
+  }
+  FILE* file = fdopen(file_descriptor, "wb");
+  if (!file) {
+    perror("Failed to open file descriptor.");
+    close(file_descriptor);
+    abort();
+  }
+  const size_t bytes_written = fwrite(data, sizeof(uint8_t), size, file);
+  if (bytes_written < size) {
+    close(file_descriptor);
+    fprintf(stderr, "Failed to write all bytes to file (%zu out of %zu)",
+            bytes_written, size);
+    abort();
+  }
+  fclose(file);
+  return filename_buffer;
+}
+
+static void fuzzer_release_tmpfile(char* filename) {
+  if (unlink(filename) != 0) {
+    perror("WARNING: Failed to delete temporary file.");
+  }
+  free(filename);
+}
+
+// C++ RAII object for creating temporary files.
+
+#ifdef __cplusplus
+class FuzzerTemporaryFile {
+ public:
+  FuzzerTemporaryFile(const uint8_t* data, size_t size)
+      : filename_(fuzzer_get_tmpfile(data, size)) {}
+
+  ~FuzzerTemporaryFile() { fuzzer_release_tmpfile(filename_); }
+
+  const char* filename() const { return filename_; }
+
+ private:
+  char* filename_;
+};
+#endif
+
+#endif  // FUZZER_TEMP_FILE_H_
diff --git a/glib/tests/fuzzing/label_fuzzer.c b/glib/tests/fuzzing/label_fuzzer.c
new file mode 100644
index 00000000..e70f6644
--- /dev/null
+++ b/glib/tests/fuzzing/label_fuzzer.c
@@ -0,0 +1,30 @@
+#include <stdint.h>
+#include <poppler.h>
+#include <cairo.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    GError *err = NULL;
+    PopplerDocument *doc;
+    PopplerPage *page;
+    int npages, n;
+
+    doc = poppler_document_new_from_data(data, size, NULL, &err);
+    if (doc == NULL) {
+        g_error_free(err);
+        return 0;
+    }
+
+    npages = poppler_document_get_n_pages(doc);
+    if (npages < 1) {
+        return 0;
+    }
+
+    for (n = 0; n < poppler_document_get_n_pages(doc); n++) {
+        page = poppler_document_get_page_by_label(doc, data);
+        if (!page) {
+            continue;
+        }
+        g_object_unref(page);
+    }
+    return 0;
+}
diff --git a/glib/tests/fuzzing/pdf_draw_fuzzer.c b/glib/tests/fuzzing/pdf_draw_fuzzer.c
new file mode 100644
index 00000000..24abdc43
--- /dev/null
+++ b/glib/tests/fuzzing/pdf_draw_fuzzer.c
@@ -0,0 +1,61 @@
+#include <stdint.h>
+#include <poppler.h>
+#include <cairo.h>
+#include <cairo-pdf.h>
+
+#include "fuzzer_temp_file.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    GError *err = NULL;
+    PopplerDocument *doc;
+    PopplerPage *page;
+    PopplerRectangle bb;
+    gdouble width, height;
+    gboolean hg;
+    int npages, n;
+
+    cairo_surface_t *surface;
+    cairo_t *cr;
+
+    doc = poppler_document_new_from_data(data, size, NULL, &err);
+    if (doc == NULL) {
+        g_error_free(err);
+        return 0;
+    }
+
+    npages = poppler_document_get_n_pages(doc);
+    if (npages < 1) {
+        g_object_unref(doc);
+        return 0;
+    }
+
+    char *tmpfile = fuzzer_get_tmpfile(data, size);
+    surface = cairo_pdf_surface_create(tmpfile, 1.0, 1.0);
+
+    for (n = 0; n < poppler_document_get_n_pages(doc); n++) {
+        page = poppler_document_get_page(doc, n);
+        if (!page) {
+            continue;
+        }
+        poppler_page_get_size(page, &width, &height);
+        cairo_pdf_surface_set_size(surface, width, height);
+        hg = poppler_page_get_bounding_box(page, &bb);
+
+        cr = cairo_create(surface);
+        poppler_page_render_for_printing(page, cr);
+        if (hg) {
+            cairo_set_source_rgb(cr, 1.6, 1.6, 1.6);
+            cairo_rectangle(cr, bb.x1, bb.y1, bb.x2 - bb.x1, bb.y2 - bb.y1);
+            cairo_stroke(cr);
+        }
+        cairo_destroy(cr);
+        cairo_surface_show_page(surface);
+
+        g_object_unref(page);
+    }
+
+    g_object_unref(doc);
+    cairo_surface_destroy(surface);
+    fuzzer_release_tmpfile(tmpfile);
+    return 0;
+}
diff --git a/glib/tests/fuzzing/util_fuzzer.c b/glib/tests/fuzzing/util_fuzzer.c
new file mode 100644
index 00000000..3514cd73
--- /dev/null
+++ b/glib/tests/fuzzing/util_fuzzer.c
@@ -0,0 +1,12 @@
+#include <stdint.h>
+#include <poppler.h>
+#include <cairo.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    gsize length;
+    poppler_named_dest_from_bytestring(data, size);
+    poppler_named_dest_to_bytestring(data, &length);
+    /*poppler_named_dest_from_bytestring((const guint8*)data, size);*/
+    /*poppler_named_dest_to_bytestring((const char*)data, &length);*/
+    return 0;
+}
commit c6a50e4f2334d130061b03c31ad96387ba86dbea
Author: Ceyhun Alp <ceyhunalp at google.com>
Date:   Sat Oct 10 20:19:39 2020 +0000

    Fuzzers for cpp

diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt
index f5be4213..9517b39a 100644
--- a/cpp/tests/CMakeLists.txt
+++ b/cpp/tests/CMakeLists.txt
@@ -22,4 +22,7 @@ cpp_add_simpletest(poppler-render poppler-render.cpp ${CMAKE_SOURCE_DIR}/utils/p
 
 if(ENABLE_FUZZER)
   cpp_add_simpletest(pdf_fuzzer pdf_fuzzer.cc)
+  cpp_add_simpletest(pdf_file_fuzzer ./fuzzing/pdf_file_fuzzer.cc)
+  cpp_add_simpletest(page_label_fuzzer ./fuzzing/page_label_fuzzer.cc)
+  cpp_add_simpletest(page_search_fuzzer ./fuzzing/page_search_fuzzer.cc)
 endif()
diff --git a/cpp/tests/fuzzing/fuzzer_temp_file.h b/cpp/tests/fuzzing/fuzzer_temp_file.h
new file mode 100644
index 00000000..fe25caba
--- /dev/null
+++ b/cpp/tests/fuzzing/fuzzer_temp_file.h
@@ -0,0 +1,81 @@
+// Copyright 2018 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Adapter utility from fuzzer input to a temporary file, for fuzzing APIs that
+// require a file instead of an input buffer.
+
+#ifndef FUZZER_TEMP_FILE_H_
+#define FUZZER_TEMP_FILE_H_
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+// Pure-C interface for creating and cleaning up temporary files.
+
+static char* fuzzer_get_tmpfile(const uint8_t* data, size_t size) {
+  char* filename_buffer = strdup("/tmp/generate_temporary_file.XXXXXX");
+  if (!filename_buffer) {
+    perror("Failed to allocate file name buffer.");
+    abort();
+  }
+  const int file_descriptor = mkstemp(filename_buffer);
+  if (file_descriptor < 0) {
+    perror("Failed to make temporary file.");
+    abort();
+  }
+  FILE* file = fdopen(file_descriptor, "wb");
+  if (!file) {
+    perror("Failed to open file descriptor.");
+    close(file_descriptor);
+    abort();
+  }
+  const size_t bytes_written = fwrite(data, sizeof(uint8_t), size, file);
+  if (bytes_written < size) {
+    close(file_descriptor);
+    fprintf(stderr, "Failed to write all bytes to file (%zu out of %zu)",
+            bytes_written, size);
+    abort();
+  }
+  fclose(file);
+  return filename_buffer;
+}
+
+static void fuzzer_release_tmpfile(char* filename) {
+  if (unlink(filename) != 0) {
+    perror("WARNING: Failed to delete temporary file.");
+  }
+  free(filename);
+}
+
+// C++ RAII object for creating temporary files.
+
+#ifdef __cplusplus
+class FuzzerTemporaryFile {
+ public:
+  FuzzerTemporaryFile(const uint8_t* data, size_t size)
+      : filename_(fuzzer_get_tmpfile(data, size)) {}
+
+  ~FuzzerTemporaryFile() { fuzzer_release_tmpfile(filename_); }
+
+  const char* filename() const { return filename_; }
+
+ private:
+  char* filename_;
+};
+#endif
+
+#endif  // FUZZER_TEMP_FILE_H_
diff --git a/cpp/tests/fuzzing/page_label_fuzzer.cc b/cpp/tests/fuzzing/page_label_fuzzer.cc
new file mode 100644
index 00000000..ca168da3
--- /dev/null
+++ b/cpp/tests/fuzzing/page_label_fuzzer.cc
@@ -0,0 +1,51 @@
+/*
+# Copyright 2018 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+*/
+
+#include <cstdint>
+
+#include <poppler-global.h>
+#include <poppler-document.h>
+#include <poppler-page.h>
+#include <poppler-page-renderer.h>
+
+static void dummy_error_function(const std::string &, void *) { }
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+    poppler::set_debug_error_function(dummy_error_function, nullptr);
+
+    poppler::document *doc = poppler::document::load_from_raw_data((const char *)data, size);
+    if (!doc || doc->is_locked()) {
+        delete doc;
+        return 0;
+    }
+
+    poppler::page_renderer r;
+    for (int i = 0; i < doc->pages(); i++) {
+        poppler::ustring label = poppler::ustring::from_utf8((const char*)data, size);
+        poppler::page *p = doc->create_page(label);
+        if (!p) {
+            continue;
+        }
+        r.render_page(p);
+        delete p;
+    }
+
+    delete doc;
+    return 0;
+}
diff --git a/cpp/tests/fuzzing/page_search_fuzzer.cc b/cpp/tests/fuzzing/page_search_fuzzer.cc
new file mode 100644
index 00000000..99fc99aa
--- /dev/null
+++ b/cpp/tests/fuzzing/page_search_fuzzer.cc
@@ -0,0 +1,53 @@
+/*
+# Copyright 2018 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+*/
+
+#include <cstdint>
+
+#include <poppler-global.h>
+#include <poppler-document.h>
+#include <poppler-page.h>
+#include <poppler-page-renderer.h>
+
+static void dummy_error_function(const std::string &, void *) { }
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+    poppler::set_debug_error_function(dummy_error_function, nullptr);
+
+    poppler::document *doc = poppler::document::load_from_raw_data((const char *)data, size);
+    if (!doc || doc->is_locked()) {
+        delete doc;
+        return 0;
+    }
+
+    poppler::page_renderer r;
+    for (int i = 0; i < doc->pages(); i++) {
+        poppler::page *p = doc->create_page(i);
+        if (!p) {
+            continue;
+        }
+        poppler::rectf rect = p->page_rect();
+        poppler::ustring text = poppler::ustring::from_utf8((const char*)data, size);
+        p->search(text, rect, poppler::page::search_from_top, poppler::case_insensitive, poppler::rotate_0);
+        r.render_page(p);
+        delete p;
+    }
+
+    delete doc;
+    return 0;
+}
diff --git a/cpp/tests/fuzzing/pdf_file_fuzzer.cc b/cpp/tests/fuzzing/pdf_file_fuzzer.cc
new file mode 100644
index 00000000..6ee40e29
--- /dev/null
+++ b/cpp/tests/fuzzing/pdf_file_fuzzer.cc
@@ -0,0 +1,57 @@
+/*
+# Copyright 2018 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+*/
+
+#include <cstdint>
+#include <string>
+
+#include <poppler-global.h>
+#include <poppler-document.h>
+#include <poppler-page.h>
+#include <poppler-page-renderer.h>
+
+#include "fuzzer_temp_file.h"
+
+static void dummy_error_function(const std::string &, void *) { }
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+    poppler::set_debug_error_function(dummy_error_function, nullptr);
+
+    char *tmpfile = fuzzer_get_tmpfile(data, size);
+    std::string fname(tmpfile);
+    poppler::document *doc = poppler::document::load_from_file(fname);
+    if (!doc || doc->is_locked()) {
+        delete doc;
+        fuzzer_release_tmpfile(tmpfile);
+        return 0;
+    }
+
+    poppler::page_renderer r;
+    for (int i = 0; i < doc->pages(); i++) {
+        poppler::page *p = doc->create_page(i);
+        if (!p) {
+            continue;
+        }
+        r.render_page(p);
+        delete p;
+    }
+
+    delete doc;
+    fuzzer_release_tmpfile(tmpfile);
+    return 0;
+}


More information about the poppler mailing list