public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
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


  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).