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 26 void sshbuf_fuzz_tests(void); 27 28 void 29 sshbuf_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