diff mbox

Demangler fuzzer

Message ID 20140811160420.GA3355@blade.nx
State New
Headers show

Commit Message

Gary Benson Aug. 11, 2014, 4:04 p.m. UTC
David Malcolm wrote:
> On Mon, 2014-08-11 at 08:06 -0700, Andi Kleen wrote:
> > Gary Benson <gbenson@redhat.com> writes:
> > > srand(time(NULL));
> > 
> > That's really bad, can never be reproduced.  If you use a random
> > seed like this you need to at least print it.
> 
> How about taking the random seed and the number of iterations as
> command-line arguments?  (with defaults for each)

Well, the reproducer ends up in the corefile, but I take your point.
How about this patch?

Thanks,
Gary

--

Comments

Andi Kleen Aug. 11, 2014, 4:39 p.m. UTC | #1
Looks good.
-Andi
Jakub Jelinek Aug. 11, 2014, 5:57 p.m. UTC | #2
On Mon, Aug 11, 2014 at 05:04:20PM +0100, Gary Benson wrote:
> +	case 's':
> +	  seed = atoi (optarg);
> +	  break;
> +
> +	case 't':
> +	  timeout = atoi (optarg);
> +	  break;
> +
> +	case 'm':
> +	  maxcount = atoi (optarg);
> +	  break;
> +	}
> +    }
> +  while (optchr != -1);
> +
> +  if (seed == -1)
> +    seed = time (NULL);
> +  srand (seed);
> +  printf ("%s: seed = %d\n", program_name, seed);

That will still make it non-reproduceable if time returns -1
(well, as you cast time_t to int, that can be e.g. on 64-bit arches
any time which has 0xffffffff in the low 32 bits).  So perhaps do
  if (seed == -1)
    {
      seed = time (NULL);
      if (seed == -1) seed = 0;
    }
or something similar?

> +  if (timeout != -1)
> +    {
> +      signal (SIGALRM, alarm_handler);
> +      alarm (timeout);
> +    }

Not sure how much portable signal/alarm is.  So probably should be guarded
by the existence of signal.h, SIGALRM being defined etc.

	Jakub
Mike Stump Aug. 11, 2014, 6:44 p.m. UTC | #3
On Aug 11, 2014, at 10:57 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> 
>> +  if (timeout != -1)
>> +    {
>> +      signal (SIGALRM, alarm_handler);
>> +      alarm (timeout);
>> +    }
> 
> Not sure how much portable signal/alarm is.  So probably should be guarded
> by the existence of signal.h, SIGALRM being defined etc.

Generally speaking, newlib doesn’t have it (and I use newlib to build gcc for testing).  Autoconf and HAVE_alarm is better, newlib has a SIGALRM.
diff mbox

Patch

Index: libiberty/ChangeLog
===================================================================
--- libiberty/ChangeLog	(revision 213809)
+++ libiberty/ChangeLog	(working copy)
@@ -1,3 +1,10 @@ 
+2014-08-11  Gary Benson  <gbenson@redhat.com>
+
+	* testsuite/demangler-fuzzer.c: New file.
+	* testsuite/Makefile.in (fuzz-demangler): New rule.
+	(demangler-fuzzer): Likewise.
+	(mostlyclean): Clean up demangler fuzzer.
+
 2014-06-11  Andrew Burgess  <aburgess@broadcom.com>
 
 	* cplus-dem.c (do_type): Call string_delete even if the call to
Index: libiberty/testsuite/Makefile.in
===================================================================
--- libiberty/testsuite/Makefile.in	(revision 213809)
+++ libiberty/testsuite/Makefile.in	(working copy)
@@ -59,6 +59,10 @@ 
 check-expandargv: test-expandargv
 	./test-expandargv
 
+# Run the demangler fuzzer
+fuzz-demangler: demangler-fuzzer
+	./demangler-fuzzer -m 50000000
+
 TEST_COMPILE = $(CC) @DEFS@ $(LIBCFLAGS) -I.. -I$(INCDIR) $(HDEFINES)
 test-demangle: $(srcdir)/test-demangle.c ../libiberty.a
 	$(TEST_COMPILE) -o test-demangle \
@@ -72,6 +76,10 @@ 
 	$(TEST_COMPILE) -DHAVE_CONFIG_H -I.. -o test-expandargv \
 		$(srcdir)/test-expandargv.c ../libiberty.a
 
+demangler-fuzzer: $(srcdir)/demangler-fuzzer.c ../libiberty.a
+	$(TEST_COMPILE) -o demangler-fuzzer \
+		$(srcdir)/demangler-fuzzer.c ../libiberty.a
+
 # Standard (either GNU or Cygnus) rules we don't use.
 html install-html info install-info clean-info dvi pdf install-pdf \
 install etags tags installcheck:
@@ -81,6 +89,7 @@ 
 	rm -f test-demangle
 	rm -f test-pexecute
 	rm -f test-expandargv
+	rm -f demangler-fuzzer
 	rm -f core
 clean: mostlyclean
 distclean: clean
Index: libiberty/testsuite/demangler-fuzzer.c
===================================================================
--- libiberty/testsuite/demangler-fuzzer.c	(revision 0)
+++ libiberty/testsuite/demangler-fuzzer.c	(revision 0)
@@ -0,0 +1,121 @@ 
+/* Demangler fuzzer.
+
+   Copyright (C) 2014 Free Software Foundation, Inc.
+
+   This file is part of GNU libiberty.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <time.h>
+#include <demangle.h>
+
+#define MAXLEN 253
+#define ALPMIN 33
+#define ALPMAX 127
+
+static char *program_name;
+
+static void
+print_usage (FILE *fp, int exit_value)
+{
+  fprintf (fp, "Usage: %s [OPTION]...\n", program_name);
+  fprintf (fp, "Options:\n");
+  fprintf (fp, "  -h           Display this message.\n");
+  fprintf (fp, "  -s SEED      Select the random seed to be used.\n");
+  fprintf (fp, "  -t TIMEOUT   Exit after TIMEOUT seconds.\n");
+  fprintf (fp, "  -m MAXCOUNT  Exit after MAXCOUNT symbols.\n");
+
+  exit (exit_value);
+}
+
+static int quit_flag;
+
+static void
+alarm_handler (int signum)
+{
+  quit_flag = 1;
+}
+
+int
+main (int argc, char *argv[])
+{
+  char symbol[2 + MAXLEN + 1] = "_Z";
+  int optchr;
+  int seed = -1, maxcount = -1, timeout = -1;
+  int count = 0;
+
+  program_name = argv[0];
+
+  do
+    {
+      optchr = getopt (argc, argv, "hs:m:t:");
+      switch (optchr)
+	{
+	case '?':  /* Unrecognized option.  */
+	  print_usage (stderr, 1);
+	  break;
+
+	case 'h':
+	  print_usage (stdout, 0);
+	  break;
+
+	case 's':
+	  seed = atoi (optarg);
+	  break;
+
+	case 't':
+	  timeout = atoi (optarg);
+	  break;
+
+	case 'm':
+	  maxcount = atoi (optarg);
+	  break;
+	}
+    }
+  while (optchr != -1);
+
+  if (seed == -1)
+    seed = time (NULL);
+  srand (seed);
+  printf ("%s: seed = %d\n", program_name, seed);
+
+  if (timeout != -1)
+    {
+      signal (SIGALRM, alarm_handler);
+      alarm (timeout);
+    }
+
+  while (!quit_flag && (maxcount < 0 || count < maxcount))
+    {
+      char *buffer = symbol + 2;
+      int length, i;
+
+      length = rand () % MAXLEN;
+      for (i = 0; i < length; i++)
+	*buffer++ = (rand () % (ALPMAX - ALPMIN)) + ALPMIN;
+
+      *buffer++ = '\0';
+
+      cplus_demangle (symbol, DMGL_AUTO | DMGL_ANSI | DMGL_PARAMS);
+
+      count++;
+    }
+
+  printf ("%s: successfully demangled %d symbols\n", program_name, count);
+  exit (0);
+}