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