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
24void sshbuf_tests(void);
25
26#ifndef roundup
27#define roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
28#endif
29
30void
31sshbuf_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