1 /* 	$OpenBSD: test_sshbuf.c,v 1.2 2021/12/14 21:25:27 deraadt Exp $ */
2 /*
3  * Regress test for sshbuf.h buffer API
4  *
5  * Placed in the public domain
6  */
7 
8 #define SSHBUF_INTERNAL 1	/* access internals for testing */
9 #include "includes.h"
10 
11 #include <sys/types.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 void sshbuf_tests(void);
25 
26 #ifndef roundup
27 #define roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
28 #endif
29 
30 void
sshbuf_tests(void)31 sshbuf_tests(void)
32 {
33 	struct sshbuf *p1;
34 	const u_char *cdp;
35 	u_char *dp;
36 	size_t sz;
37 	int r;
38 
39 	TEST_START("allocate sshbuf");
40 	p1 = sshbuf_new();
41 	ASSERT_PTR_NE(p1, NULL);
42 	TEST_DONE();
43 
44 	TEST_START("max size on fresh buffer");
45 	ASSERT_SIZE_T_GT(sshbuf_max_size(p1), 0);
46 	TEST_DONE();
47 
48 	TEST_START("available on fresh buffer");
49 	ASSERT_SIZE_T_GT(sshbuf_avail(p1), 0);
50 	TEST_DONE();
51 
52 	TEST_START("len = 0 on empty buffer");
53 	ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
54 	TEST_DONE();
55 
56 	TEST_START("set valid max size");
57 	ASSERT_INT_EQ(sshbuf_set_max_size(p1, 65536), 0);
58 	ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 65536);
59 	TEST_DONE();
60 
61 	TEST_START("available on limited buffer");
62 	ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 65536);
63 	TEST_DONE();
64 
65 	TEST_START("free");
66 	sshbuf_free(p1);
67 	TEST_DONE();
68 
69 	TEST_START("consume on empty buffer");
70 	p1 = sshbuf_new();
71 	ASSERT_PTR_NE(p1, NULL);
72 	ASSERT_INT_EQ(sshbuf_consume(p1, 0), 0);
73 	ASSERT_INT_EQ(sshbuf_consume(p1, 1), SSH_ERR_MESSAGE_INCOMPLETE);
74 	sshbuf_free(p1);
75 	TEST_DONE();
76 
77 	TEST_START("consume_end on empty buffer");
78 	p1 = sshbuf_new();
79 	ASSERT_PTR_NE(p1, NULL);
80 	ASSERT_INT_EQ(sshbuf_consume_end(p1, 0), 0);
81 	ASSERT_INT_EQ(sshbuf_consume_end(p1, 1), SSH_ERR_MESSAGE_INCOMPLETE);
82 	sshbuf_free(p1);
83 	TEST_DONE();
84 
85 	TEST_START("reserve space");
86 	p1 = sshbuf_new();
87 	ASSERT_PTR_NE(p1, NULL);
88 	r = sshbuf_reserve(p1, 1, &dp);
89 	ASSERT_INT_EQ(r, 0);
90 	ASSERT_PTR_NE(dp, NULL);
91 	*dp = 0x11;
92 	r = sshbuf_reserve(p1, 3, &dp);
93 	ASSERT_INT_EQ(r, 0);
94 	ASSERT_PTR_NE(dp, NULL);
95 	*dp++ = 0x22;
96 	*dp++ = 0x33;
97 	*dp++ = 0x44;
98 	TEST_DONE();
99 
100 	TEST_START("sshbuf_len on filled buffer");
101 	ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
102 	TEST_DONE();
103 
104 	TEST_START("sshbuf_ptr on filled buffer");
105 	cdp = sshbuf_ptr(p1);
106 	ASSERT_PTR_NE(cdp, NULL);
107 	ASSERT_U8_EQ(cdp[0], 0x11);
108 	ASSERT_U8_EQ(cdp[1], 0x22);
109 	ASSERT_U8_EQ(cdp[2], 0x33);
110 	ASSERT_U8_EQ(cdp[3], 0x44);
111 	TEST_DONE();
112 
113 	TEST_START("consume on filled buffer");
114 	ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
115 	ASSERT_INT_EQ(sshbuf_consume(p1, 0), 0);
116 	ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
117 	r = sshbuf_consume(p1, 64);
118 	ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
119 	ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
120 	ASSERT_INT_EQ(sshbuf_consume(p1, 1), 0);
121 	ASSERT_SIZE_T_EQ(sshbuf_len(p1), 3);
122 	cdp = sshbuf_ptr(p1);
123 	ASSERT_PTR_NE(p1, NULL);
124 	ASSERT_U8_EQ(cdp[0], 0x22);
125 	ASSERT_INT_EQ(sshbuf_consume(p1, 2), 0);
126 	ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
127 	cdp = sshbuf_ptr(p1);
128 	ASSERT_PTR_NE(p1, NULL);
129 	ASSERT_U8_EQ(cdp[0], 0x44);
130 	r = sshbuf_consume(p1, 2);
131 	ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
132 	ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
133 	ASSERT_INT_EQ(sshbuf_consume(p1, 1), 0);
134 	ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
135 	r = sshbuf_consume(p1, 1);
136 	ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
137 	sshbuf_free(p1);
138 	TEST_DONE();
139 
140 	TEST_START("consume_end on filled buffer");
141 	p1 = sshbuf_new();
142 	ASSERT_PTR_NE(p1, NULL);
143 	r = sshbuf_reserve(p1, 4, &dp);
144 	ASSERT_INT_EQ(r, 0);
145 	ASSERT_PTR_NE(dp, NULL);
146 	*dp++ = 0x11;
147 	*dp++ = 0x22;
148 	*dp++ = 0x33;
149 	*dp++ = 0x44;
150 	ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
151 	r = sshbuf_consume_end(p1, 5);
152 	ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
153 	ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
154 	ASSERT_INT_EQ(sshbuf_consume_end(p1, 3), 0);
155 	ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
156 	cdp = sshbuf_ptr(p1);
157 	ASSERT_PTR_NE(cdp, NULL);
158 	ASSERT_U8_EQ(*cdp, 0x11);
159 	r = sshbuf_consume_end(p1, 2);
160 	ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
161 	ASSERT_INT_EQ(sshbuf_consume_end(p1, 1), 0);
162 	ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
163 	sshbuf_free(p1);
164 	TEST_DONE();
165 
166 	TEST_START("fill limited buffer");
167 	p1 = sshbuf_new();
168 	ASSERT_PTR_NE(p1, NULL);
169 	ASSERT_INT_EQ(sshbuf_set_max_size(p1, 1223), 0);
170 	ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 1223);
171 	ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 1223);
172 	r = sshbuf_reserve(p1, 1223, &dp);
173 	ASSERT_INT_EQ(r, 0);
174 	ASSERT_PTR_NE(dp, NULL);
175 	memset(dp, 0xd7, 1223);
176 	ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1223);
177 	ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 0);
178 	r = sshbuf_reserve(p1, 1, &dp);
179 	ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
180 	ASSERT_PTR_EQ(dp, NULL);
181 	TEST_DONE();
182 
183 	TEST_START("consume and force compaction");
184 	ASSERT_INT_EQ(sshbuf_consume(p1, 223), 0);
185 	ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1000);
186 	ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 223);
187 	r = sshbuf_reserve(p1, 224, &dp);
188 	ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
189 	ASSERT_PTR_EQ(dp, NULL);
190 	ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1000);
191 	ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 223);
192 	r = sshbuf_reserve(p1, 223, &dp);
193 	ASSERT_INT_EQ(r, 0);
194 	ASSERT_PTR_NE(dp, NULL);
195 	memset(dp, 0x7d, 223);
196 	cdp = sshbuf_ptr(p1);
197 	ASSERT_PTR_NE(cdp, NULL);
198 	ASSERT_MEM_FILLED_EQ(cdp, 0xd7, 1000);
199 	ASSERT_MEM_FILLED_EQ(cdp + 1000, 0x7d, 223);
200 	TEST_DONE();
201 
202 	TEST_START("resize full buffer");
203 	r = sshbuf_set_max_size(p1, 1000);
204 	ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
205 	sz = roundup(1223 + SSHBUF_SIZE_INC * 3, SSHBUF_SIZE_INC);
206 	ASSERT_INT_EQ(sshbuf_set_max_size(p1, sz), 0);
207 	ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), sz);
208 	ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz - 1223);
209 	ASSERT_INT_EQ(sshbuf_len(p1), 1223);
210 	TEST_DONE();
211 
212 	/* NB. uses sshbuf internals */
213 	TEST_START("alloc chunking");
214 	r = sshbuf_reserve(p1, 1, &dp);
215 	ASSERT_INT_EQ(r, 0);
216 	ASSERT_PTR_NE(dp, NULL);
217 	*dp = 0xff;
218 	cdp = sshbuf_ptr(p1);
219 	ASSERT_PTR_NE(cdp, NULL);
220 	ASSERT_MEM_FILLED_EQ(cdp, 0xd7, 1000);
221 	ASSERT_MEM_FILLED_EQ(cdp + 1000, 0x7d, 223);
222 	ASSERT_MEM_FILLED_EQ(cdp + 1223, 0xff, 1);
223 	ASSERT_SIZE_T_EQ(sshbuf_alloc(p1) % SSHBUF_SIZE_INC, 0);
224 	sshbuf_free(p1);
225 	TEST_DONE();
226 
227 	TEST_START("reset buffer");
228 	p1 = sshbuf_new();
229 	ASSERT_PTR_NE(p1, NULL);
230 	ASSERT_INT_EQ(sshbuf_set_max_size(p1, 1223), 0);
231 	ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 1223);
232 	r = sshbuf_reserve(p1, 1223, &dp);
233 	ASSERT_INT_EQ(r, 0);
234 	ASSERT_PTR_NE(dp, NULL);
235 	memset(dp, 0xd7, 1223);
236 	ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1223);
237 	sshbuf_reset(p1);
238 	ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 1223);
239 	ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
240 	ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 1223);
241 	sshbuf_free(p1);
242 	TEST_DONE();
243 }
244