1276707Sdes/* $OpenBSD: test_sshbuf_fuzz.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */ 2276707Sdes/* 3276707Sdes * Regress test for sshbuf.h buffer API 4276707Sdes * 5276707Sdes * Placed in the public domain 6276707Sdes */ 7276707Sdes 8276707Sdes#include "includes.h" 9276707Sdes 10276707Sdes#include <sys/types.h> 11276707Sdes#include <sys/param.h> 12276707Sdes#include <stdio.h> 13276707Sdes#ifdef HAVE_STDINT_H 14276707Sdes# include <stdint.h> 15276707Sdes#endif 16276707Sdes#include <stdlib.h> 17276707Sdes#include <string.h> 18276707Sdes 19276707Sdes#include "../test_helper/test_helper.h" 20276707Sdes 21276707Sdes#include "ssherr.h" 22276707Sdes#include "sshbuf.h" 23276707Sdes 24276707Sdes#define NUM_FUZZ_TESTS (1 << 18) 25276707Sdes 26276707Sdesvoid sshbuf_fuzz_tests(void); 27276707Sdes 28276707Sdesvoid 29276707Sdessshbuf_fuzz_tests(void) 30276707Sdes{ 31276707Sdes struct sshbuf *p1; 32276707Sdes u_char *dp; 33276707Sdes size_t sz, sz2, i; 34276707Sdes u_int32_t r; 35276707Sdes int ret; 36276707Sdes 37276707Sdes /* NB. uses sshbuf internals */ 38276707Sdes TEST_START("fuzz alloc/dealloc"); 39276707Sdes p1 = sshbuf_new(); 40276707Sdes ASSERT_INT_EQ(sshbuf_set_max_size(p1, 16 * 1024), 0); 41276707Sdes ASSERT_PTR_NE(p1, NULL); 42276707Sdes ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); 43276707Sdes ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1)); 44276707Sdes for (i = 0; i < NUM_FUZZ_TESTS; i++) { 45276707Sdes r = arc4random_uniform(10); 46276707Sdes if (r == 0) { 47276707Sdes /* 10% chance: small reserve */ 48276707Sdes r = arc4random_uniform(10); 49276707Sdes fuzz_reserve: 50276707Sdes sz = sshbuf_avail(p1); 51276707Sdes sz2 = sshbuf_len(p1); 52276707Sdes ret = sshbuf_reserve(p1, r, &dp); 53276707Sdes if (ret < 0) { 54276707Sdes ASSERT_PTR_EQ(dp, NULL); 55276707Sdes ASSERT_SIZE_T_LT(sz, r); 56276707Sdes ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz); 57276707Sdes ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2); 58276707Sdes } else { 59276707Sdes ASSERT_PTR_NE(dp, NULL); 60276707Sdes ASSERT_SIZE_T_GE(sz, r); 61276707Sdes ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz - r); 62276707Sdes ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 + r); 63276707Sdes memset(dp, arc4random_uniform(255) + 1, r); 64276707Sdes } 65276707Sdes } else if (r < 3) { 66276707Sdes /* 20% chance: big reserve */ 67276707Sdes r = arc4random_uniform(8 * 1024); 68276707Sdes goto fuzz_reserve; 69276707Sdes } else if (r == 3) { 70276707Sdes /* 10% chance: small consume */ 71276707Sdes r = arc4random_uniform(10); 72276707Sdes fuzz_consume: 73276707Sdes sz = sshbuf_avail(p1); 74276707Sdes sz2 = sshbuf_len(p1); 75276707Sdes /* 50% change consume from end, otherwise start */ 76276707Sdes ret = ((arc4random() & 1) ? 77276707Sdes sshbuf_consume : sshbuf_consume_end)(p1, r); 78276707Sdes if (ret < 0) { 79276707Sdes ASSERT_SIZE_T_LT(sz2, r); 80276707Sdes ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz); 81276707Sdes ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2); 82276707Sdes } else { 83276707Sdes ASSERT_SIZE_T_GE(sz2, r); 84276707Sdes ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz + r); 85276707Sdes ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 - r); 86276707Sdes } 87276707Sdes } else if (r < 8) { 88276707Sdes /* 40% chance: big consume */ 89276707Sdes r = arc4random_uniform(2 * 1024); 90276707Sdes goto fuzz_consume; 91276707Sdes } else if (r == 8) { 92276707Sdes /* 10% chance: reset max size */ 93276707Sdes r = arc4random_uniform(16 * 1024); 94276707Sdes sz = sshbuf_max_size(p1); 95276707Sdes if (sshbuf_set_max_size(p1, r) < 0) 96276707Sdes ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), sz); 97276707Sdes else 98276707Sdes ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), r); 99276707Sdes } else { 100276707Sdes if (arc4random_uniform(8192) == 0) { 101276707Sdes /* tiny chance: new buffer */ 102276707Sdes ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); 103276707Sdes ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1)); 104276707Sdes sshbuf_free(p1); 105276707Sdes p1 = sshbuf_new(); 106276707Sdes ASSERT_PTR_NE(p1, NULL); 107276707Sdes ASSERT_INT_EQ(sshbuf_set_max_size(p1, 108276707Sdes 16 * 1024), 0); 109276707Sdes } else { 110276707Sdes /* Almost 10%: giant reserve */ 111276707Sdes /* use arc4random_buf for r > 2^32 on 64 bit */ 112276707Sdes arc4random_buf(&r, sizeof(r)); 113276707Sdes while (r < SSHBUF_SIZE_MAX / 2) { 114276707Sdes r <<= 1; 115276707Sdes r |= arc4random() & 1; 116276707Sdes } 117276707Sdes goto fuzz_reserve; 118276707Sdes } 119276707Sdes } 120276707Sdes ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); 121276707Sdes ASSERT_SIZE_T_LE(sshbuf_max_size(p1), 16 * 1024); 122276707Sdes } 123276707Sdes ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); 124276707Sdes ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1)); 125276707Sdes sshbuf_free(p1); 126276707Sdes TEST_DONE(); 127276707Sdes} 128