From d531405ca9f96787856bd0fea340fc9e9e23b4c0 Mon Sep 17 00:00:00 2001 From: djm Date: Tue, 13 Jan 2015 14:51:51 +0000 Subject: [PATCH] implement a SIGINFO handler so we can discern a stuck fuzz test from a merely glacial one; prompted by and ok markus --- .../usr.bin/ssh/unittests/test_helper/fuzz.c | 83 ++++++++++++++----- .../ssh/unittests/test_helper/test_helper.c | 26 +++++- .../ssh/unittests/test_helper/test_helper.h | 3 +- 3 files changed, 91 insertions(+), 21 deletions(-) diff --git a/regress/usr.bin/ssh/unittests/test_helper/fuzz.c b/regress/usr.bin/ssh/unittests/test_helper/fuzz.c index 3ccab7d2461..b9a2fecace1 100644 --- a/regress/usr.bin/ssh/unittests/test_helper/fuzz.c +++ b/regress/usr.bin/ssh/unittests/test_helper/fuzz.c @@ -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 * @@ -18,6 +18,7 @@ /* Utility functions/framework for fuzz tests */ #include +#include #include #include @@ -25,8 +26,11 @@ #include #include #include +#include +#include #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); diff --git a/regress/usr.bin/ssh/unittests/test_helper/test_helper.c b/regress/usr.bin/ssh/unittests/test_helper/test_helper.c index 8f0bbdec992..796f72ef3aa 100644 --- a/regress/usr.bin/ssh/unittests/test_helper/test_helper.c +++ b/regress/usr.bin/ssh/unittests/test_helper/test_helper.c @@ -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 * @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -27,12 +28,14 @@ #include #include #include +#include #include #include #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 ? "" : 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 diff --git a/regress/usr.bin/ssh/unittests/test_helper/test_helper.h b/regress/usr.bin/ssh/unittests/test_helper/test_helper.h index 6ead92a1ccf..127d41afa25 100644 --- a/regress/usr.bin/ssh/unittests/test_helper/test_helper.h +++ b/regress/usr.bin/ssh/unittests/test_helper/test_helper.h @@ -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 * @@ -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); -- 2.20.1