132785Speter/* $OpenBSD: test_sshbuf_fuzz.c,v 1.4 2021/12/18 06:53:59 anton Exp $ */ 232785Speter/* 332785Speter * Regress test for sshbuf.h buffer API 432785Speter * 532785Speter * Placed in the public domain 632785Speter */ 732785Speter 832785Speter#include "includes.h" 932785Speter 1032785Speter#include <sys/types.h> 1132785Speter#include <stdio.h> 1232785Speter#ifdef HAVE_STDINT_H 1332785Speter# include <stdint.h> 1432785Speter#endif 1532785Speter#include <stdlib.h> 1632785Speter#include <string.h> 1732785Speter 1832785Speter#include "../test_helper/test_helper.h" 1932785Speter 2032785Speter#include "ssherr.h" 2132785Speter#include "sshbuf.h" 2232785Speter 2332785Speter#define NUM_FUZZ_TESTS (1 << 18) 2432785Speter 2532785Spetervoid sshbuf_fuzz_tests(void); 2632785Speter 2732785Spetervoid 2832785Spetersshbuf_fuzz_tests(void) 2932785Speter{ 3032785Speter struct sshbuf *p1; 3132785Speter u_char *dp; 3232785Speter size_t sz, sz2, i, ntests = NUM_FUZZ_TESTS; 3332785Speter u_int32_t r; 3432785Speter int ret; 3532785Speter 3632785Speter if (test_is_fast()) 3732785Speter ntests >>= 2; 3832785Speter if (test_is_slow()) 3932785Speter ntests <<= 2; 4032785Speter 4132785Speter /* NB. uses sshbuf internals */ 4232785Speter TEST_START("fuzz alloc/dealloc"); 4332785Speter p1 = sshbuf_new(); 4432785Speter ASSERT_INT_EQ(sshbuf_set_max_size(p1, 16 * 1024), 0); 4532785Speter ASSERT_PTR_NE(p1, NULL); 4632785Speter ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); 4732785Speter ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1)); 4832785Speter for (i = 0; i < ntests; i++) { 4932785Speter r = arc4random_uniform(10); 5032785Speter if (r == 0) { 5132785Speter /* 10% chance: small reserve */ 5232785Speter r = arc4random_uniform(10); 5332785Speter fuzz_reserve: 5432785Speter sz = sshbuf_avail(p1); 5532785Speter sz2 = sshbuf_len(p1); 5632785Speter ret = sshbuf_reserve(p1, r, &dp); 5732785Speter if (ret < 0) { 5832785Speter ASSERT_PTR_EQ(dp, NULL); 5932785Speter ASSERT_SIZE_T_LT(sz, r); 6032785Speter ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz); 6132785Speter ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2); 6232785Speter } else { 6332785Speter ASSERT_PTR_NE(dp, NULL); 6432785Speter ASSERT_SIZE_T_GE(sz, r); 6532785Speter ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz - r); 6632785Speter ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 + r); 6732785Speter memset(dp, arc4random_uniform(255) + 1, r); 6832785Speter } 6932785Speter } else if (r < 3) { 7032785Speter /* 20% chance: big reserve */ 7132785Speter r = arc4random_uniform(8 * 1024); 7232785Speter goto fuzz_reserve; 7332785Speter } else if (r == 3) { 7432785Speter /* 10% chance: small consume */ 7532785Speter r = arc4random_uniform(10); 7632785Speter fuzz_consume: 7732785Speter sz = sshbuf_avail(p1); 7832785Speter sz2 = sshbuf_len(p1); 7932785Speter /* 50% change consume from end, otherwise start */ 8032785Speter ret = ((arc4random() & 1) ? 8132785Speter sshbuf_consume : sshbuf_consume_end)(p1, r); 8232785Speter if (ret < 0) { 8332785Speter ASSERT_SIZE_T_LT(sz2, r); 8432785Speter ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz); 8532785Speter ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2); 8632785Speter } else { 8732785Speter ASSERT_SIZE_T_GE(sz2, r); 8832785Speter ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz + r); 8932785Speter ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 - r); 9032785Speter } 9132785Speter } else if (r < 8) { 9232785Speter /* 40% chance: big consume */ 9332785Speter r = arc4random_uniform(2 * 1024); 9432785Speter goto fuzz_consume; 9532785Speter } else if (r == 8) { 9632785Speter /* 10% chance: reset max size */ 9732785Speter r = arc4random_uniform(16 * 1024); 9832785Speter sz = sshbuf_max_size(p1); 9932785Speter if (sshbuf_set_max_size(p1, r) < 0) 10032785Speter ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), sz); 10132785Speter else 10232785Speter ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), r); 10332785Speter } else { 10432785Speter if (arc4random_uniform(8192) == 0) { 10532785Speter /* tiny chance: new buffer */ 10632785Speter ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); 10732785Speter ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1)); 10832785Speter sshbuf_free(p1); 10932785Speter p1 = sshbuf_new(); 11032785Speter ASSERT_PTR_NE(p1, NULL); 11132785Speter ASSERT_INT_EQ(sshbuf_set_max_size(p1, 11232785Speter 16 * 1024), 0); 11332785Speter } else { 11432785Speter /* Almost 10%: giant reserve */ 11532785Speter /* use arc4random_buf for r > 2^32 on 64 bit */ 11632785Speter arc4random_buf(&r, sizeof(r)); 11732785Speter while (r < SSHBUF_SIZE_MAX / 2) { 11832785Speter r <<= 1; 11932785Speter r |= arc4random() & 1; 12032785Speter } 12132785Speter goto fuzz_reserve; 12232785Speter } 12332785Speter } 12432785Speter ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); 12532785Speter ASSERT_SIZE_T_LE(sshbuf_max_size(p1), 16 * 1024); 12632785Speter } 12732785Speter ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); 12832785Speter ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1)); 12932785Speter sshbuf_free(p1); 13032785Speter TEST_DONE(); 13132785Speter} 13232785Speter