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