|  | /* 	$OpenBSD: test_sshbuf_fuzz.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */ | 
|  | /* | 
|  | * Regress test for sshbuf.h buffer API | 
|  | * | 
|  | * Placed in the public domain | 
|  | */ | 
|  |  | 
|  | #include "includes.h" | 
|  |  | 
|  | #include <sys/types.h> | 
|  | #include <sys/param.h> | 
|  | #include <stdio.h> | 
|  | #ifdef HAVE_STDINT_H | 
|  | # include <stdint.h> | 
|  | #endif | 
|  | #include <stdlib.h> | 
|  | #include <string.h> | 
|  |  | 
|  | #include "../test_helper/test_helper.h" | 
|  |  | 
|  | #include "ssherr.h" | 
|  | #include "sshbuf.h" | 
|  |  | 
|  | #define NUM_FUZZ_TESTS (1 << 18) | 
|  |  | 
|  | void sshbuf_fuzz_tests(void); | 
|  |  | 
|  | void | 
|  | sshbuf_fuzz_tests(void) | 
|  | { | 
|  | struct sshbuf *p1; | 
|  | u_char *dp; | 
|  | size_t sz, sz2, i; | 
|  | u_int32_t r; | 
|  | int ret; | 
|  |  | 
|  | /* NB. uses sshbuf internals */ | 
|  | TEST_START("fuzz alloc/dealloc"); | 
|  | p1 = sshbuf_new(); | 
|  | ASSERT_INT_EQ(sshbuf_set_max_size(p1, 16 * 1024), 0); | 
|  | ASSERT_PTR_NE(p1, NULL); | 
|  | ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); | 
|  | ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1)); | 
|  | for (i = 0; i < NUM_FUZZ_TESTS; i++) { | 
|  | r = arc4random_uniform(10); | 
|  | if (r == 0) { | 
|  | /* 10% chance: small reserve */ | 
|  | r = arc4random_uniform(10); | 
|  | fuzz_reserve: | 
|  | sz = sshbuf_avail(p1); | 
|  | sz2 = sshbuf_len(p1); | 
|  | ret = sshbuf_reserve(p1, r, &dp); | 
|  | if (ret < 0) { | 
|  | ASSERT_PTR_EQ(dp, NULL); | 
|  | ASSERT_SIZE_T_LT(sz, r); | 
|  | ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz); | 
|  | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2); | 
|  | } else { | 
|  | ASSERT_PTR_NE(dp, NULL); | 
|  | ASSERT_SIZE_T_GE(sz, r); | 
|  | ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz - r); | 
|  | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 + r); | 
|  | memset(dp, arc4random_uniform(255) + 1, r); | 
|  | } | 
|  | } else if (r < 3) { | 
|  | /* 20% chance: big reserve */ | 
|  | r = arc4random_uniform(8 * 1024); | 
|  | goto fuzz_reserve; | 
|  | } else if (r == 3) { | 
|  | /* 10% chance: small consume */ | 
|  | r = arc4random_uniform(10); | 
|  | fuzz_consume: | 
|  | sz = sshbuf_avail(p1); | 
|  | sz2 = sshbuf_len(p1); | 
|  | /* 50% change consume from end, otherwise start */ | 
|  | ret = ((arc4random() & 1) ? | 
|  | sshbuf_consume : sshbuf_consume_end)(p1, r); | 
|  | if (ret < 0) { | 
|  | ASSERT_SIZE_T_LT(sz2, r); | 
|  | ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz); | 
|  | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2); | 
|  | } else { | 
|  | ASSERT_SIZE_T_GE(sz2, r); | 
|  | ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz + r); | 
|  | ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 - r); | 
|  | } | 
|  | } else if (r < 8) { | 
|  | /* 40% chance: big consume */ | 
|  | r = arc4random_uniform(2 * 1024); | 
|  | goto fuzz_consume; | 
|  | } else if (r == 8) { | 
|  | /* 10% chance: reset max size */ | 
|  | r = arc4random_uniform(16 * 1024); | 
|  | sz = sshbuf_max_size(p1); | 
|  | if (sshbuf_set_max_size(p1, r) < 0) | 
|  | ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), sz); | 
|  | else | 
|  | ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), r); | 
|  | } else { | 
|  | if (arc4random_uniform(8192) == 0) { | 
|  | /* tiny chance: new buffer */ | 
|  | ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); | 
|  | ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1)); | 
|  | sshbuf_free(p1); | 
|  | p1 = sshbuf_new(); | 
|  | ASSERT_PTR_NE(p1, NULL); | 
|  | ASSERT_INT_EQ(sshbuf_set_max_size(p1, | 
|  | 16 * 1024), 0); | 
|  | } else { | 
|  | /* Almost 10%: giant reserve */ | 
|  | /* use arc4random_buf for r > 2^32 on 64 bit */ | 
|  | arc4random_buf(&r, sizeof(r)); | 
|  | while (r < SSHBUF_SIZE_MAX / 2) { | 
|  | r <<= 1; | 
|  | r |= arc4random() & 1; | 
|  | } | 
|  | goto fuzz_reserve; | 
|  | } | 
|  | } | 
|  | ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); | 
|  | ASSERT_SIZE_T_LE(sshbuf_max_size(p1), 16 * 1024); | 
|  | } | 
|  | ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); | 
|  | ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1)); | 
|  | sshbuf_free(p1); | 
|  | TEST_DONE(); | 
|  | } |