djm@openbsd.org 80603c0daa upstream commit
add a fuzz_matches_original() function to the fuzzer to
 detect fuzz cases that are identical to the original data. Hacky
 implementation, but very useful when you need the fuzz to be different, e.g.
 when verifying signature
2015-01-20 00:24:39 +11:00

304 lines
12 KiB
C

/* $OpenBSD: test_helper.h,v 1.6 2015/01/18 19:52:44 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Utility functions/framework for regress tests */
#ifndef _TEST_HELPER_H
#define _TEST_HELPER_H
#include "includes.h"
#include <sys/types.h>
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include <openssl/bn.h>
#include <openssl/err.h>
enum test_predicate {
TEST_EQ, TEST_NE, TEST_LT, TEST_LE, TEST_GT, TEST_GE
};
typedef void (test_onerror_func_t)(void *);
/* Supplied by test suite */
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 test_subtest_info(const char *fmt, ...)
__attribute__((format(printf, 1, 2)));
void ssl_err_check(const char *file, int line);
void assert_bignum(const char *file, int line,
const char *a1, const char *a2,
const BIGNUM *aa1, const BIGNUM *aa2, enum test_predicate pred);
void assert_string(const char *file, int line,
const char *a1, const char *a2,
const char *aa1, const char *aa2, enum test_predicate pred);
void assert_mem(const char *file, int line,
const char *a1, const char *a2,
const void *aa1, const void *aa2, size_t l, enum test_predicate pred);
void assert_mem_filled(const char *file, int line,
const char *a1,
const void *aa1, u_char v, size_t l, enum test_predicate pred);
void assert_int(const char *file, int line,
const char *a1, const char *a2,
int aa1, int aa2, enum test_predicate pred);
void assert_size_t(const char *file, int line,
const char *a1, const char *a2,
size_t aa1, size_t aa2, enum test_predicate pred);
void assert_u_int(const char *file, int line,
const char *a1, const char *a2,
u_int aa1, u_int aa2, enum test_predicate pred);
void assert_long_long(const char *file, int line,
const char *a1, const char *a2,
long long aa1, long long aa2, enum test_predicate pred);
void assert_char(const char *file, int line,
const char *a1, const char *a2,
char aa1, char aa2, enum test_predicate pred);
void assert_ptr(const char *file, int line,
const char *a1, const char *a2,
const void *aa1, const void *aa2, enum test_predicate pred);
void assert_u8(const char *file, int line,
const char *a1, const char *a2,
u_int8_t aa1, u_int8_t aa2, enum test_predicate pred);
void assert_u16(const char *file, int line,
const char *a1, const char *a2,
u_int16_t aa1, u_int16_t aa2, enum test_predicate pred);
void assert_u32(const char *file, int line,
const char *a1, const char *a2,
u_int32_t aa1, u_int32_t aa2, enum test_predicate pred);
void assert_u64(const char *file, int line,
const char *a1, const char *a2,
u_int64_t aa1, u_int64_t aa2, enum test_predicate pred);
#define TEST_START(n) test_start(n)
#define TEST_DONE() test_done()
#define TEST_ONERROR(f, c) set_onerror_func(f, c)
#define SSL_ERR_CHECK() ssl_err_check(__FILE__, __LINE__)
#define ASSERT_BIGNUM_EQ(a1, a2) \
assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_STRING_EQ(a1, a2) \
assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_MEM_EQ(a1, a2, l) \
assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_EQ)
#define ASSERT_MEM_FILLED_EQ(a1, c, l) \
assert_mem_filled(__FILE__, __LINE__, #a1, a1, c, l, TEST_EQ)
#define ASSERT_MEM_ZERO_EQ(a1, l) \
assert_mem_filled(__FILE__, __LINE__, #a1, a1, '\0', l, TEST_EQ)
#define ASSERT_INT_EQ(a1, a2) \
assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_SIZE_T_EQ(a1, a2) \
assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_U_INT_EQ(a1, a2) \
assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_LONG_LONG_EQ(a1, a2) \
assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_CHAR_EQ(a1, a2) \
assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_PTR_EQ(a1, a2) \
assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_U8_EQ(a1, a2) \
assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_U16_EQ(a1, a2) \
assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_U32_EQ(a1, a2) \
assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_U64_EQ(a1, a2) \
assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_BIGNUM_NE(a1, a2) \
assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_STRING_NE(a1, a2) \
assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_MEM_NE(a1, a2, l) \
assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_NE)
#define ASSERT_MEM_ZERO_NE(a1, l) \
assert_mem_filled(__FILE__, __LINE__, #a1, a1, '\0', l, TEST_NE)
#define ASSERT_INT_NE(a1, a2) \
assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_SIZE_T_NE(a1, a2) \
assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_U_INT_NE(a1, a2) \
assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_LONG_LONG_NE(a1, a2) \
assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_CHAR_NE(a1, a2) \
assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_PTR_NE(a1, a2) \
assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_U8_NE(a1, a2) \
assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_U16_NE(a1, a2) \
assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_U32_NE(a1, a2) \
assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_U64_NE(a1, a2) \
assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_BIGNUM_LT(a1, a2) \
assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_STRING_LT(a1, a2) \
assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_MEM_LT(a1, a2, l) \
assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_LT)
#define ASSERT_INT_LT(a1, a2) \
assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_SIZE_T_LT(a1, a2) \
assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_U_INT_LT(a1, a2) \
assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_LONG_LONG_LT(a1, a2) \
assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_CHAR_LT(a1, a2) \
assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_PTR_LT(a1, a2) \
assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_U8_LT(a1, a2) \
assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_U16_LT(a1, a2) \
assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_U32_LT(a1, a2) \
assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_U64_LT(a1, a2) \
assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_BIGNUM_LE(a1, a2) \
assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_STRING_LE(a1, a2) \
assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_MEM_LE(a1, a2, l) \
assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_LE)
#define ASSERT_INT_LE(a1, a2) \
assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_SIZE_T_LE(a1, a2) \
assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_U_INT_LE(a1, a2) \
assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_LONG_LONG_LE(a1, a2) \
assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_CHAR_LE(a1, a2) \
assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_PTR_LE(a1, a2) \
assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_U8_LE(a1, a2) \
assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_U16_LE(a1, a2) \
assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_U32_LE(a1, a2) \
assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_U64_LE(a1, a2) \
assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_BIGNUM_GT(a1, a2) \
assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_STRING_GT(a1, a2) \
assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_MEM_GT(a1, a2, l) \
assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_GT)
#define ASSERT_INT_GT(a1, a2) \
assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_SIZE_T_GT(a1, a2) \
assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_U_INT_GT(a1, a2) \
assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_LONG_LONG_GT(a1, a2) \
assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_CHAR_GT(a1, a2) \
assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_PTR_GT(a1, a2) \
assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_U8_GT(a1, a2) \
assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_U16_GT(a1, a2) \
assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_U32_GT(a1, a2) \
assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_U64_GT(a1, a2) \
assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_BIGNUM_GE(a1, a2) \
assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_STRING_GE(a1, a2) \
assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_MEM_GE(a1, a2, l) \
assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_GE)
#define ASSERT_INT_GE(a1, a2) \
assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_SIZE_T_GE(a1, a2) \
assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_U_INT_GE(a1, a2) \
assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_LONG_LONG_GE(a1, a2) \
assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_CHAR_GE(a1, a2) \
assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_PTR_GE(a1, a2) \
assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_U8_GE(a1, a2) \
assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_U16_GE(a1, a2) \
assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_U32_GE(a1, a2) \
assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_U64_GE(a1, a2) \
assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
/* Fuzzing support */
struct fuzz;
#define FUZZ_1_BIT_FLIP 0x00000001 /* Flip one bit at a time */
#define FUZZ_2_BIT_FLIP 0x00000002 /* Flip two bits at a time */
#define FUZZ_1_BYTE_FLIP 0x00000004 /* Flip one byte at a time */
#define FUZZ_2_BYTE_FLIP 0x00000008 /* Flip two bytes at a time */
#define FUZZ_TRUNCATE_START 0x00000010 /* Truncate from beginning */
#define FUZZ_TRUNCATE_END 0x00000020 /* Truncate from end */
#define FUZZ_BASE64 0x00000040 /* Try all base64 chars */
#define FUZZ_MAX FUZZ_BASE64
/* Start fuzzing a blob of data with selected strategies (bitmask) */
struct fuzz *fuzz_begin(u_int strategies, const void *p, size_t l);
/* Free a fuzz context */
void fuzz_cleanup(struct fuzz *fuzz);
/* Prepare the next fuzz case in the series */
void fuzz_next(struct fuzz *fuzz);
/*
* Check whether this fuzz case is identical to the original
* This is slow, but useful if the caller needs to ensure that all tests
* generated change the input (e.g. when fuzzing signatures).
*/
int fuzz_matches_original(struct fuzz *fuzz);
/* Determine whether the current fuzz sequence is exhausted (nonzero = yes) */
int fuzz_done(struct fuzz *fuzz);
/* Return the length and a pointer to the current fuzzed case */
size_t fuzz_len(struct fuzz *fuzz);
u_char *fuzz_ptr(struct fuzz *fuzz);
/* Dump the current fuzz case to stderr */
void fuzz_dump(struct fuzz *fuzz);
#endif /* _TEST_HELPER_H */