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
20void sshbuf_tests(void);
21
22#define roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
23
24void
25sshbuf_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