test_sshbuf_fuzz.c revision 323134
1/* 	$OpenBSD: test_sshbuf_fuzz.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */
2/*
3 * Regress test for sshbuf.h buffer API
4 *
5 * Placed in the public domain
6 */
7
8#include "includes.h"
9
10#include <sys/types.h>
11#include <sys/param.h>
12#include <stdio.h>
13#ifdef HAVE_STDINT_H
14# include <stdint.h>
15#endif
16#include <stdlib.h>
17#include <string.h>
18
19#include "../test_helper/test_helper.h"
20
21#include "ssherr.h"
22#include "sshbuf.h"
23
24#define NUM_FUZZ_TESTS (1 << 18)
25
26void sshbuf_fuzz_tests(void);
27
28void
29sshbuf_fuzz_tests(void)
30{
31	struct sshbuf *p1;
32	u_char *dp;
33	size_t sz, sz2, i;
34	u_int32_t r;
35	int ret;
36
37	/* NB. uses sshbuf internals */
38	TEST_START("fuzz alloc/dealloc");
39	p1 = sshbuf_new();
40	ASSERT_INT_EQ(sshbuf_set_max_size(p1, 16 * 1024), 0);
41	ASSERT_PTR_NE(p1, NULL);
42	ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
43	ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1));
44	for (i = 0; i < NUM_FUZZ_TESTS; i++) {
45		r = arc4random_uniform(10);
46		if (r == 0) {
47			/* 10% chance: small reserve */
48			r = arc4random_uniform(10);
49 fuzz_reserve:
50			sz = sshbuf_avail(p1);
51			sz2 = sshbuf_len(p1);
52			ret = sshbuf_reserve(p1, r, &dp);
53			if (ret < 0) {
54				ASSERT_PTR_EQ(dp, NULL);
55				ASSERT_SIZE_T_LT(sz, r);
56				ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz);
57				ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2);
58			} else {
59				ASSERT_PTR_NE(dp, NULL);
60				ASSERT_SIZE_T_GE(sz, r);
61				ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz - r);
62				ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 + r);
63				memset(dp, arc4random_uniform(255) + 1, r);
64			}
65		} else if (r < 3) {
66			/* 20% chance: big reserve */
67			r = arc4random_uniform(8 * 1024);
68			goto fuzz_reserve;
69		} else if (r == 3) {
70			/* 10% chance: small consume */
71			r = arc4random_uniform(10);
72 fuzz_consume:
73			sz = sshbuf_avail(p1);
74			sz2 = sshbuf_len(p1);
75			/* 50% change consume from end, otherwise start */
76			ret = ((arc4random() & 1) ?
77			    sshbuf_consume : sshbuf_consume_end)(p1, r);
78			if (ret < 0) {
79				ASSERT_SIZE_T_LT(sz2, r);
80				ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz);
81				ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2);
82			} else {
83				ASSERT_SIZE_T_GE(sz2, r);
84				ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz + r);
85				ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 - r);
86			}
87		} else if (r < 8) {
88			/* 40% chance: big consume */
89			r = arc4random_uniform(2 * 1024);
90			goto fuzz_consume;
91		} else if (r == 8) {
92			/* 10% chance: reset max size */
93			r = arc4random_uniform(16 * 1024);
94			sz = sshbuf_max_size(p1);
95			if (sshbuf_set_max_size(p1, r) < 0)
96				ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), sz);
97			else
98				ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), r);
99		} else {
100			if (arc4random_uniform(8192) == 0) {
101				/* tiny chance: new buffer */
102				ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
103				ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1));
104				sshbuf_free(p1);
105				p1 = sshbuf_new();
106				ASSERT_PTR_NE(p1, NULL);
107				ASSERT_INT_EQ(sshbuf_set_max_size(p1,
108				    16 * 1024), 0);
109			} else {
110				/* Almost 10%: giant reserve */
111				/* use arc4random_buf for r > 2^32 on 64 bit */
112				arc4random_buf(&r, sizeof(r));
113				while (r < SSHBUF_SIZE_MAX / 2) {
114					r <<= 1;
115					r |= arc4random() & 1;
116				}
117				goto fuzz_reserve;
118			}
119		}
120		ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
121		ASSERT_SIZE_T_LE(sshbuf_max_size(p1), 16 * 1024);
122	}
123	ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
124	ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1));
125	sshbuf_free(p1);
126	TEST_DONE();
127}
128