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