implement a SIGINFO handler so we can discern a stuck fuzz test
authordjm <djm@openbsd.org>
Tue, 13 Jan 2015 14:51:51 +0000 (14:51 +0000)
committerdjm <djm@openbsd.org>
Tue, 13 Jan 2015 14:51:51 +0000 (14:51 +0000)
from a merely glacial one; prompted by and ok markus

regress/usr.bin/ssh/unittests/test_helper/fuzz.c
regress/usr.bin/ssh/unittests/test_helper/test_helper.c
regress/usr.bin/ssh/unittests/test_helper/test_helper.h

index 3ccab7d..b9a2fec 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: fuzz.c,v 1.4 2014/11/19 13:35:37 krw Exp $    */
+/*     $OpenBSD: fuzz.c,v 1.5 2015/01/13 14:51:51 djm Exp $    */
 /*
  * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
  *
@@ -18,6 +18,7 @@
 /* Utility functions/framework for fuzz tests */
 
 #include <sys/types.h>
+#include <sys/uio.h>
 
 #include <assert.h>
 #include <ctype.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <signal.h>
+#include <unistd.h>
 
 #include "test_helper.h"
+#include "atomicio.h"
 
 /* #define FUZZ_DEBUG */
 
@@ -91,59 +95,73 @@ fuzz_ntop(u_int n)
        }
 }
 
-void
-fuzz_dump(struct fuzz *fuzz)
+static int
+fuzz_fmt(struct fuzz *fuzz, char *s, size_t n)
 {
-       u_char *p = fuzz_ptr(fuzz);
-       size_t i, j, len = fuzz_len(fuzz);
+       if (fuzz == NULL)
+               return -1;
 
        switch (fuzz->strategy) {
        case FUZZ_1_BIT_FLIP:
-               fprintf(stderr, "%s case %zu of %zu (bit: %zu)\n",
+               snprintf(s, n, "%s case %zu of %zu (bit: %zu)\n",
                    fuzz_ntop(fuzz->strategy),
                    fuzz->o1, fuzz->slen * 8, fuzz->o1);
-               break;
+               return 0;
        case FUZZ_2_BIT_FLIP:
-               fprintf(stderr, "%s case %llu of %llu (bits: %zu, %zu)\n",
+               snprintf(s, n, "%s case %llu of %llu (bits: %zu, %zu)\n",
                    fuzz_ntop(fuzz->strategy),
                    (((fuzz_ullong)fuzz->o2) * fuzz->slen * 8) + fuzz->o1,
                    ((fuzz_ullong)fuzz->slen * 8) * fuzz->slen * 8,
                    fuzz->o1, fuzz->o2);
-               break;
+               return 0;
        case FUZZ_1_BYTE_FLIP:
-               fprintf(stderr, "%s case %zu of %zu (byte: %zu)\n",
+               snprintf(s, n, "%s case %zu of %zu (byte: %zu)\n",
                    fuzz_ntop(fuzz->strategy),
                    fuzz->o1, fuzz->slen, fuzz->o1);
-               break;
+               return 0;
        case FUZZ_2_BYTE_FLIP:
-               fprintf(stderr, "%s case %llu of %llu (bytes: %zu, %zu)\n",
+               snprintf(s, n, "%s case %llu of %llu (bytes: %zu, %zu)\n",
                    fuzz_ntop(fuzz->strategy),
                    (((fuzz_ullong)fuzz->o2) * fuzz->slen) + fuzz->o1,
                    ((fuzz_ullong)fuzz->slen) * fuzz->slen,
                    fuzz->o1, fuzz->o2);
-               break;
+               return 0;
        case FUZZ_TRUNCATE_START:
-               fprintf(stderr, "%s case %zu of %zu (offset: %zu)\n",
+               snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n",
                    fuzz_ntop(fuzz->strategy),
                    fuzz->o1, fuzz->slen, fuzz->o1);
-               break;
+               return 0;
        case FUZZ_TRUNCATE_END:
-               fprintf(stderr, "%s case %zu of %zu (offset: %zu)\n",
+               snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n",
                    fuzz_ntop(fuzz->strategy),
                    fuzz->o1, fuzz->slen, fuzz->o1);
-               break;
+               return 0;
        case FUZZ_BASE64:
                assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1);
-               fprintf(stderr, "%s case %llu of %llu (offset: %zu char: %c)\n",
+               snprintf(s, n, "%s case %llu of %llu (offset: %zu char: %c)\n",
                    fuzz_ntop(fuzz->strategy),
                    (fuzz->o1 * (fuzz_ullong)64) + fuzz->o2,
                    fuzz->slen * (fuzz_ullong)64, fuzz->o1,
                    fuzz_b64chars[fuzz->o2]);
-               break;
+               return 0;
        default:
+               return -1;
                abort();
        }
+}
+
+void
+fuzz_dump(struct fuzz *fuzz)
+{
+       u_char *p = fuzz_ptr(fuzz);
+       size_t i, j, len = fuzz_len(fuzz);
+       char buf[256];
 
+       if (fuzz_fmt(fuzz, buf, sizeof(buf)) != 0) {
+               fprintf(stderr, "%s: fuzz invalid\n", __func__);
+               abort();
+       }
+       fputs(buf, stderr);
        fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, len);
        for (i = 0; i < len; i += 16) {
                fprintf(stderr, "%.4zd: ", i);
@@ -166,6 +184,23 @@ fuzz_dump(struct fuzz *fuzz)
        }
 }
 
+#ifdef SIGINFO
+static struct fuzz *last_fuzz;
+
+static void
+siginfo(int unused __unused)
+{
+       char buf[256];
+
+       test_info(buf, sizeof(buf));
+       atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
+       if (last_fuzz != NULL) {
+               fuzz_fmt(last_fuzz, buf, sizeof(buf));
+               atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
+       }
+}
+#endif
+
 struct fuzz *
 fuzz_begin(u_int strategies, const void *p, size_t l)
 {
@@ -185,6 +220,12 @@ fuzz_begin(u_int strategies, const void *p, size_t l)
        FUZZ_DBG(("begin, ret = %p", ret));
 
        fuzz_next(ret);
+
+#ifdef SIGINFO
+       last_fuzz = ret;
+       signal(SIGINFO, siginfo);
+#endif
+
        return ret;
 }
 
@@ -192,6 +233,10 @@ void
 fuzz_cleanup(struct fuzz *fuzz)
 {
        FUZZ_DBG(("cleanup, fuzz = %p", fuzz));
+#ifdef SIGINFO
+       last_fuzz = NULL;
+       signal(SIGINFO, SIG_DFL);
+#endif
        assert(fuzz != NULL);
        assert(fuzz->seed != NULL);
        assert(fuzz->fuzzed != NULL);
index 8f0bbde..796f72e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: test_helper.c,v 1.2 2014/05/02 09:41:32 andre Exp $   */
+/*     $OpenBSD: test_helper.c,v 1.3 2015/01/13 14:51:51 djm Exp $     */
 /*
  * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
  *
@@ -19,6 +19,7 @@
 
 #include <sys/types.h>
 #include <sys/param.h>
+#include <sys/uio.h>
 
 #include <fcntl.h>
 #include <stdio.h>
 #include <string.h>
 #include <assert.h>
 #include <unistd.h>
+#include <signal.h>
 
 #include <openssl/bn.h>
 
 #include <vis.h>
 
 #include "test_helper.h"
+#include "atomicio.h"
 
 #define TEST_CHECK_INT(r, pred) do {           \
                switch (pred) {                 \
@@ -160,6 +163,24 @@ test_data_file(const char *name)
        return ret;
 }
 
+void
+test_info(char *s, size_t len)
+{
+       snprintf(s, len, "In test %u - \"%s\"\n", test_number,
+           active_test_name == NULL ? "<none>" : active_test_name);
+}
+
+#ifdef SIGINFO
+static void
+siginfo(int unused __unused)
+{
+       char buf[256];
+
+       test_info(buf, sizeof(buf));
+       atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
+}
+#endif
+
 void
 test_start(const char *n)
 {
@@ -168,6 +189,9 @@ test_start(const char *n)
        if (verbose_mode)
                printf("test %u - \"%s\": ", test_number, active_test_name);
        test_number++;
+#ifdef SIGINFO
+       signal(SIGINFO, siginfo);
+#endif
 }
 
 void
index 6ead92a..127d41a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: test_helper.h,v 1.3 2014/05/02 09:41:32 andre Exp $   */
+/*     $OpenBSD: test_helper.h,v 1.4 2015/01/13 14:51:51 djm Exp $     */
 /*
  * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
  *
@@ -36,6 +36,7 @@ void tests(void);
 
 const char *test_data_file(const char *name);
 void test_start(const char *n);
+void test_info(char *s, size_t len);
 void set_onerror_func(test_onerror_func_t *f, void *ctx);
 void test_done(void);
 void ssl_err_check(const char *file, int line);