From: Ilya Leoshkevich <iii@linux.ibm.com>
To: Tom Tromey <tromey@adacore.com>,
Andrew Burgess <aburgess@redhat.com>,
Pedro Alves <pedro@palves.net>
Cc: Andreas Arnez <arnez@linux.ibm.com>,
gdb-patches@sourceware.org, Ilya Leoshkevich <iii@linux.ibm.com>
Subject: [PATCH 4/5] gdbsupport: Add interval_tree fuzzing harness
Date: Thu, 2 Jun 2022 15:35:45 +0200 [thread overview]
Message-ID: <20220602133546.2948282-5-iii@linux.ibm.com> (raw)
In-Reply-To: <20220602133546.2948282-1-iii@linux.ibm.com>
Add a libFuzzer harness that exercises additions, removals and lookups.
---
gdb/unittests/interval_tree-selftests.c | 137 ++++++++++++++++++++++++
1 file changed, 137 insertions(+)
diff --git a/gdb/unittests/interval_tree-selftests.c b/gdb/unittests/interval_tree-selftests.c
index 98a3f4c15bd..85cf376bbd0 100644
--- a/gdb/unittests/interval_tree-selftests.c
+++ b/gdb/unittests/interval_tree-selftests.c
@@ -23,6 +23,12 @@
#include <set>
#include <sstream>
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+#include <assert.h>
+#undef gdb_assert
+#define gdb_assert assert
+#endif
+
#include "gdbsupport/interval_tree.h"
/* A test type for storing in an interval tree. Interval tree must be able to
@@ -259,5 +265,136 @@ void _initialize_interval_tree_selftests ();
void
_initialize_interval_tree_selftests ()
{
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
selftests::register_test ("interval_tree", test_interval_tree);
+#endif
+}
+
+/* Fuzzing harness. */
+
+class FuzzerInput
+{
+public:
+ FuzzerInput (const unsigned char *data, size_t size)
+ : m_data (data), m_size (size)
+ {
+ }
+
+ bool
+ end () const
+ {
+ return m_size == 0;
+ }
+
+ template <typename T>
+ T
+ get ()
+ {
+ T result = 0;
+ for (size_t i = 0; i < sizeof (T); i++)
+ result |= read_byte () << (i * 8);
+ return result;
+ }
+
+private:
+ unsigned char
+ read_byte ()
+ {
+ if (end ())
+ return 0;
+ m_data++;
+ m_size--;
+ return m_data[-1];
+ }
+
+ const unsigned char *m_data;
+ size_t m_size;
+};
+
+extern "C" int LLVMFuzzerTestOneInput (const unsigned char *, size_t);
+extern "C" int
+LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
+{
+ FuzzerInput input (data, size);
+ interval_tree<test_interval> t;
+ std::vector<std::pair<decltype (t)::iterator, size_t> > t_iterators;
+ std::multiset<test_interval, cmp_test_interval> exp;
+ std::vector<decltype (exp)::iterator> exp_iterators;
+ size_t add_counter = 0;
+
+ static const char *debug_str = getenv ("DEBUG");
+ static int debug = debug_str == nullptr ? 0 : atoi (debug_str);
+
+ while (!input.end ())
+ {
+ switch (input.get<char> () % 3)
+ {
+ case 0:
+ {
+ /* Add. */
+ int low = input.get<int> (), high = input.get<int> ();
+ if (low > high)
+ std::swap (low, high);
+ if (debug)
+ std::cout << "auto it" << add_counter << " = check_emplace (t, "
+ << low << ", " << high << ");" << std::endl;
+ t_iterators.push_back (
+ std::make_pair (t.emplace (low, high), add_counter));
+ if (debug)
+ std::cout << "/*\n" << t << "*/" << std::endl;
+ else
+ std::ostringstream () << t;
+ exp_iterators.push_back (exp.emplace (low, high));
+ add_counter += 1;
+ break;
+ }
+ case 1:
+ {
+ /* Find. */
+ int low = input.get<int> (), high = input.get<int> ();
+ if (low > high)
+ std::swap (low, high);
+ if (debug)
+ std::cout << "check_iterator (t.find (" << low << ", " << high
+ << "), t.end ()" << std::flush;
+ auto it = t.find (low, high);
+ for (const test_interval &exp_interval : exp)
+ {
+ if (high < exp_interval.low || low > exp_interval.high)
+ continue;
+ if (debug)
+ std::cout << ", " << exp_interval.low << ", "
+ << exp_interval.high << std::flush;
+ gdb_assert (it->low == exp_interval.low
+ && it->high == exp_interval.high);
+ ++it;
+ }
+ if (debug)
+ std::cout << ");" << std::endl;
+ gdb_assert (it == t.end ());
+ break;
+ }
+ case 2:
+ {
+ /* Remove. */
+ if (!t_iterators.empty ())
+ {
+ int index = input.get<int> () % t_iterators.size ();
+ if (debug)
+ std::cout << "check_erase (t, it"
+ << t_iterators[index].second << ");" << std::endl;
+ t.erase (t_iterators[index].first);
+ t_iterators.erase (t_iterators.begin () + index);
+ exp.erase (exp_iterators[index]);
+ exp_iterators.erase (exp_iterators.begin () + index);
+ if (debug)
+ std::cout << "/*\n" << t << "*/" << std::endl;
+ else
+ std::ostringstream () << t;
+ }
+ break;
+ }
+ }
+ }
+ return 0;
}
--
2.35.3
next prev parent reply other threads:[~2022-06-02 13:36 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-02 13:35 [PATCH 0/5] gdb: Store section map in an interval tree Ilya Leoshkevich
2022-06-02 13:35 ` [PATCH 1/5] gdbsupport: Introduce obstack_newvec Ilya Leoshkevich
2022-06-02 14:31 ` Tom Tromey
2022-06-02 14:33 ` Ilya Leoshkevich
2022-06-02 13:35 ` [PATCH 2/5] gdbsupport: Introduce interval_tree Ilya Leoshkevich
2022-06-02 14:12 ` Pedro Alves
2022-06-02 14:17 ` Ilya Leoshkevich
2022-06-02 14:12 ` Pedro Alves
2022-06-02 14:37 ` Pedro Alves
2022-06-02 15:09 ` Ilya Leoshkevich
2022-06-02 18:04 ` Tom Tromey
2022-06-02 13:35 ` [PATCH 3/5] gdbsupport: Add interval_tree unit tests Ilya Leoshkevich
2022-06-02 13:35 ` Ilya Leoshkevich [this message]
2022-06-02 13:35 ` [PATCH 5/5] gdb: Optimize section map Ilya Leoshkevich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220602133546.2948282-5-iii@linux.ibm.com \
--to=iii@linux.ibm.com \
--cc=aburgess@redhat.com \
--cc=arnez@linux.ibm.com \
--cc=gdb-patches@sourceware.org \
--cc=pedro@palves.net \
--cc=tromey@adacore.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).