1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* util/support/t_k5buf.c - Test the k5buf string buffer module */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert * Copyright 2008 Massachusetts Institute of Technology.
5*7f2fe78bSCy Schubert * All Rights Reserved.
6*7f2fe78bSCy Schubert *
7*7f2fe78bSCy Schubert * Export of this software from the United States of America may
8*7f2fe78bSCy Schubert * require a specific license from the United States Government.
9*7f2fe78bSCy Schubert * It is the responsibility of any person or organization contemplating
10*7f2fe78bSCy Schubert * export to obtain such a license before exporting.
11*7f2fe78bSCy Schubert *
12*7f2fe78bSCy Schubert * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*7f2fe78bSCy Schubert * distribute this software and its documentation for any purpose and
14*7f2fe78bSCy Schubert * without fee is hereby granted, provided that the above copyright
15*7f2fe78bSCy Schubert * notice appear in all copies and that both that copyright notice and
16*7f2fe78bSCy Schubert * this permission notice appear in supporting documentation, and that
17*7f2fe78bSCy Schubert * the name of M.I.T. not be used in advertising or publicity pertaining
18*7f2fe78bSCy Schubert * to distribution of the software without specific, written prior
19*7f2fe78bSCy Schubert * permission. Furthermore if you modify this software you must label
20*7f2fe78bSCy Schubert * your software as modified software and not distribute it in such a
21*7f2fe78bSCy Schubert * fashion that it might be confused with the original M.I.T. software.
22*7f2fe78bSCy Schubert * M.I.T. makes no representations about the suitability of
23*7f2fe78bSCy Schubert * this software for any purpose. It is provided "as is" without express
24*7f2fe78bSCy Schubert * or implied warranty.
25*7f2fe78bSCy Schubert */
26*7f2fe78bSCy Schubert
27*7f2fe78bSCy Schubert #include "k5-platform.h"
28*7f2fe78bSCy Schubert #include "k5-buf.h"
29*7f2fe78bSCy Schubert #include <stdio.h>
30*7f2fe78bSCy Schubert #include <stdlib.h>
31*7f2fe78bSCy Schubert
32*7f2fe78bSCy Schubert static void
fail_if(int condition,const char * name)33*7f2fe78bSCy Schubert fail_if(int condition, const char *name)
34*7f2fe78bSCy Schubert {
35*7f2fe78bSCy Schubert if (condition) {
36*7f2fe78bSCy Schubert fprintf(stderr, "%s failed\n", name);
37*7f2fe78bSCy Schubert exit(1);
38*7f2fe78bSCy Schubert }
39*7f2fe78bSCy Schubert }
40*7f2fe78bSCy Schubert
41*7f2fe78bSCy Schubert /* Test the invariants of a buffer. */
42*7f2fe78bSCy Schubert static void
check_buf(struct k5buf * buf,const char * name)43*7f2fe78bSCy Schubert check_buf(struct k5buf *buf, const char *name)
44*7f2fe78bSCy Schubert {
45*7f2fe78bSCy Schubert fail_if(buf->buftype != K5BUF_FIXED && buf->buftype != K5BUF_DYNAMIC &&
46*7f2fe78bSCy Schubert buf->buftype != K5BUF_ERROR, name);
47*7f2fe78bSCy Schubert if (buf->buftype == K5BUF_ERROR) {
48*7f2fe78bSCy Schubert fail_if(buf->data != NULL, name);
49*7f2fe78bSCy Schubert fail_if(buf->space != 0 || buf->len != 0, name);
50*7f2fe78bSCy Schubert } else {
51*7f2fe78bSCy Schubert fail_if(buf->space == 0, name);
52*7f2fe78bSCy Schubert fail_if(buf->len >= buf->space, name);
53*7f2fe78bSCy Schubert }
54*7f2fe78bSCy Schubert }
55*7f2fe78bSCy Schubert
56*7f2fe78bSCy Schubert static void
test_basic()57*7f2fe78bSCy Schubert test_basic()
58*7f2fe78bSCy Schubert {
59*7f2fe78bSCy Schubert struct k5buf buf;
60*7f2fe78bSCy Schubert char storage[1024];
61*7f2fe78bSCy Schubert
62*7f2fe78bSCy Schubert k5_buf_init_fixed(&buf, storage, sizeof(storage));
63*7f2fe78bSCy Schubert k5_buf_add(&buf, "Hello ");
64*7f2fe78bSCy Schubert k5_buf_add_len(&buf, "world", 5);
65*7f2fe78bSCy Schubert check_buf(&buf, "basic fixed");
66*7f2fe78bSCy Schubert fail_if(buf.data == NULL || buf.len != 11, "basic fixed");
67*7f2fe78bSCy Schubert fail_if(memcmp(buf.data, "Hello world", 11) != 0, "basic fixed");
68*7f2fe78bSCy Schubert
69*7f2fe78bSCy Schubert k5_buf_init_dynamic(&buf);
70*7f2fe78bSCy Schubert k5_buf_add_len(&buf, "Hello", 5);
71*7f2fe78bSCy Schubert k5_buf_add(&buf, " world");
72*7f2fe78bSCy Schubert check_buf(&buf, "basic dynamic");
73*7f2fe78bSCy Schubert fail_if(buf.data == NULL || buf.len != 11, "basic dynamic");
74*7f2fe78bSCy Schubert fail_if(memcmp(buf.data, "Hello world", 11) != 0, "basic dynamic");
75*7f2fe78bSCy Schubert k5_buf_free(&buf);
76*7f2fe78bSCy Schubert }
77*7f2fe78bSCy Schubert
78*7f2fe78bSCy Schubert static void
test_realloc()79*7f2fe78bSCy Schubert test_realloc()
80*7f2fe78bSCy Schubert {
81*7f2fe78bSCy Schubert struct k5buf buf;
82*7f2fe78bSCy Schubert char data[1024];
83*7f2fe78bSCy Schubert size_t i;
84*7f2fe78bSCy Schubert
85*7f2fe78bSCy Schubert for (i = 0; i < sizeof(data); i++)
86*7f2fe78bSCy Schubert data[i] = 'a';
87*7f2fe78bSCy Schubert
88*7f2fe78bSCy Schubert /* Cause the buffer size to double from 128 to 256 bytes. */
89*7f2fe78bSCy Schubert k5_buf_init_dynamic(&buf);
90*7f2fe78bSCy Schubert k5_buf_add_len(&buf, data, 10);
91*7f2fe78bSCy Schubert k5_buf_add_len(&buf, data, 128);
92*7f2fe78bSCy Schubert fail_if(buf.space != 256, "realloc 1");
93*7f2fe78bSCy Schubert check_buf(&buf, "realloc 1");
94*7f2fe78bSCy Schubert fail_if(buf.data == NULL || buf.len != 138, "realloc 1");
95*7f2fe78bSCy Schubert fail_if(memcmp(buf.data, data, buf.len) != 0, "realloc 1");
96*7f2fe78bSCy Schubert
97*7f2fe78bSCy Schubert /* Cause the same buffer to double in size to 512 bytes. */
98*7f2fe78bSCy Schubert k5_buf_add_len(&buf, data, 128);
99*7f2fe78bSCy Schubert fail_if(buf.space != 512, "realloc 2");
100*7f2fe78bSCy Schubert check_buf(&buf, "realloc 2");
101*7f2fe78bSCy Schubert fail_if(buf.data == NULL || buf.len != 266, "realloc 2");
102*7f2fe78bSCy Schubert fail_if(memcmp(buf.data, data, buf.len) != 0, "realloc 2");
103*7f2fe78bSCy Schubert k5_buf_free(&buf);
104*7f2fe78bSCy Schubert
105*7f2fe78bSCy Schubert /* Cause a buffer to increase from 128 to 512 bytes directly. */
106*7f2fe78bSCy Schubert k5_buf_init_dynamic(&buf);
107*7f2fe78bSCy Schubert k5_buf_add_len(&buf, data, 10);
108*7f2fe78bSCy Schubert k5_buf_add_len(&buf, data, 256);
109*7f2fe78bSCy Schubert fail_if(buf.space != 512, "realloc 3");
110*7f2fe78bSCy Schubert check_buf(&buf, "realloc 3");
111*7f2fe78bSCy Schubert fail_if(buf.data == NULL || buf.len != 266, "realloc 3");
112*7f2fe78bSCy Schubert fail_if(memcmp(buf.data, data, buf.len) != 0, "realloc 3");
113*7f2fe78bSCy Schubert k5_buf_free(&buf);
114*7f2fe78bSCy Schubert
115*7f2fe78bSCy Schubert /* Cause a buffer to increase from 128 to 1024 bytes directly. */
116*7f2fe78bSCy Schubert k5_buf_init_dynamic(&buf);
117*7f2fe78bSCy Schubert k5_buf_add_len(&buf, data, 10);
118*7f2fe78bSCy Schubert k5_buf_add_len(&buf, data, 512);
119*7f2fe78bSCy Schubert fail_if(buf.space != 1024, "realloc 4");
120*7f2fe78bSCy Schubert check_buf(&buf, "realloc 4");
121*7f2fe78bSCy Schubert fail_if(buf.data == NULL || buf.len != 522, "realloc 4");
122*7f2fe78bSCy Schubert fail_if(memcmp(buf.data, data, buf.len) != 0, "realloc 4");
123*7f2fe78bSCy Schubert k5_buf_free(&buf);
124*7f2fe78bSCy Schubert
125*7f2fe78bSCy Schubert /* Cause a reallocation to fail by integer overflow. */
126*7f2fe78bSCy Schubert k5_buf_init_dynamic(&buf);
127*7f2fe78bSCy Schubert k5_buf_add_len(&buf, data, 100);
128*7f2fe78bSCy Schubert k5_buf_add_len(&buf, NULL, SIZE_MAX);
129*7f2fe78bSCy Schubert check_buf(&buf, "realloc 5");
130*7f2fe78bSCy Schubert fail_if(buf.buftype != K5BUF_ERROR, "realloc 5");
131*7f2fe78bSCy Schubert k5_buf_free(&buf);
132*7f2fe78bSCy Schubert }
133*7f2fe78bSCy Schubert
134*7f2fe78bSCy Schubert static void
test_overflow()135*7f2fe78bSCy Schubert test_overflow()
136*7f2fe78bSCy Schubert {
137*7f2fe78bSCy Schubert struct k5buf buf;
138*7f2fe78bSCy Schubert char storage[10];
139*7f2fe78bSCy Schubert
140*7f2fe78bSCy Schubert /* Cause a fixed-sized buffer overflow. */
141*7f2fe78bSCy Schubert k5_buf_init_fixed(&buf, storage, sizeof(storage));
142*7f2fe78bSCy Schubert k5_buf_add(&buf, "12345");
143*7f2fe78bSCy Schubert k5_buf_add(&buf, "123456");
144*7f2fe78bSCy Schubert check_buf(&buf, "overflow 1");
145*7f2fe78bSCy Schubert fail_if(buf.buftype != K5BUF_ERROR, "overflow 1");
146*7f2fe78bSCy Schubert
147*7f2fe78bSCy Schubert /* Cause a fixed-sized buffer overflow with integer overflow. */
148*7f2fe78bSCy Schubert k5_buf_init_fixed(&buf, storage, sizeof(storage));
149*7f2fe78bSCy Schubert k5_buf_add(&buf, "12345");
150*7f2fe78bSCy Schubert k5_buf_add_len(&buf, NULL, SIZE_MAX);
151*7f2fe78bSCy Schubert check_buf(&buf, "overflow 2");
152*7f2fe78bSCy Schubert fail_if(buf.buftype != K5BUF_ERROR, "overflow 2");
153*7f2fe78bSCy Schubert }
154*7f2fe78bSCy Schubert
155*7f2fe78bSCy Schubert static void
test_error()156*7f2fe78bSCy Schubert test_error()
157*7f2fe78bSCy Schubert {
158*7f2fe78bSCy Schubert struct k5buf buf;
159*7f2fe78bSCy Schubert char storage[1];
160*7f2fe78bSCy Schubert
161*7f2fe78bSCy Schubert /* Cause an overflow and then perform actions afterwards. */
162*7f2fe78bSCy Schubert k5_buf_init_fixed(&buf, storage, sizeof(storage));
163*7f2fe78bSCy Schubert k5_buf_add(&buf, "12");
164*7f2fe78bSCy Schubert fail_if(buf.buftype != K5BUF_ERROR, "error");
165*7f2fe78bSCy Schubert check_buf(&buf, "error");
166*7f2fe78bSCy Schubert k5_buf_add(&buf, "test");
167*7f2fe78bSCy Schubert check_buf(&buf, "error");
168*7f2fe78bSCy Schubert k5_buf_add_len(&buf, "test", 4);
169*7f2fe78bSCy Schubert check_buf(&buf, "error");
170*7f2fe78bSCy Schubert k5_buf_truncate(&buf, 3);
171*7f2fe78bSCy Schubert check_buf(&buf, "error");
172*7f2fe78bSCy Schubert fail_if(buf.buftype != K5BUF_ERROR, "error");
173*7f2fe78bSCy Schubert }
174*7f2fe78bSCy Schubert
175*7f2fe78bSCy Schubert static void
test_truncate()176*7f2fe78bSCy Schubert test_truncate()
177*7f2fe78bSCy Schubert {
178*7f2fe78bSCy Schubert struct k5buf buf;
179*7f2fe78bSCy Schubert
180*7f2fe78bSCy Schubert k5_buf_init_dynamic(&buf);
181*7f2fe78bSCy Schubert k5_buf_add(&buf, "abcde");
182*7f2fe78bSCy Schubert k5_buf_add(&buf, "fghij");
183*7f2fe78bSCy Schubert k5_buf_truncate(&buf, 7);
184*7f2fe78bSCy Schubert check_buf(&buf, "truncate");
185*7f2fe78bSCy Schubert fail_if(buf.data == NULL || buf.len != 7, "truncate");
186*7f2fe78bSCy Schubert fail_if(memcmp(buf.data, "abcdefg", 7) != 0, "truncate");
187*7f2fe78bSCy Schubert k5_buf_free(&buf);
188*7f2fe78bSCy Schubert }
189*7f2fe78bSCy Schubert
190*7f2fe78bSCy Schubert static void
test_binary()191*7f2fe78bSCy Schubert test_binary()
192*7f2fe78bSCy Schubert {
193*7f2fe78bSCy Schubert struct k5buf buf;
194*7f2fe78bSCy Schubert char data[] = { 'a', 0, 'b' }, *s;
195*7f2fe78bSCy Schubert
196*7f2fe78bSCy Schubert k5_buf_init_dynamic(&buf);
197*7f2fe78bSCy Schubert k5_buf_add_len(&buf, data, 3);
198*7f2fe78bSCy Schubert k5_buf_add_len(&buf, data, 3);
199*7f2fe78bSCy Schubert check_buf(&buf, "binary");
200*7f2fe78bSCy Schubert fail_if(buf.data == NULL || buf.len != 6, "binary");
201*7f2fe78bSCy Schubert s = buf.data;
202*7f2fe78bSCy Schubert fail_if(s[0] != 'a' || s[1] != 0 || s[2] != 'b', "binary");
203*7f2fe78bSCy Schubert fail_if(s[3] != 'a' || s[4] != 0 || s[5] != 'b', "binary");
204*7f2fe78bSCy Schubert k5_buf_free(&buf);
205*7f2fe78bSCy Schubert }
206*7f2fe78bSCy Schubert
207*7f2fe78bSCy Schubert static void
test_fmt()208*7f2fe78bSCy Schubert test_fmt()
209*7f2fe78bSCy Schubert {
210*7f2fe78bSCy Schubert struct k5buf buf;
211*7f2fe78bSCy Schubert char storage[10], data[1024];
212*7f2fe78bSCy Schubert size_t i;
213*7f2fe78bSCy Schubert
214*7f2fe78bSCy Schubert for (i = 0; i < sizeof(data) - 1; i++)
215*7f2fe78bSCy Schubert data[i] = 'a';
216*7f2fe78bSCy Schubert data[i] = '\0';
217*7f2fe78bSCy Schubert
218*7f2fe78bSCy Schubert /* Format some text into a non-empty fixed buffer. */
219*7f2fe78bSCy Schubert k5_buf_init_fixed(&buf, storage, sizeof(storage));
220*7f2fe78bSCy Schubert k5_buf_add(&buf, "foo");
221*7f2fe78bSCy Schubert k5_buf_add_fmt(&buf, " %d ", 3);
222*7f2fe78bSCy Schubert check_buf(&buf, "fmt 1");
223*7f2fe78bSCy Schubert fail_if(buf.data == NULL || buf.len != 6, "fmt 1");
224*7f2fe78bSCy Schubert fail_if(memcmp(buf.data, "foo 3 ", 6) != 0, "fmt 1");
225*7f2fe78bSCy Schubert
226*7f2fe78bSCy Schubert /* Overflow the same buffer with formatted text. */
227*7f2fe78bSCy Schubert k5_buf_add_fmt(&buf, "%d%d%d%d", 1, 2, 3, 4);
228*7f2fe78bSCy Schubert check_buf(&buf, "fmt 2");
229*7f2fe78bSCy Schubert fail_if(buf.buftype != K5BUF_ERROR, "fmt 2");
230*7f2fe78bSCy Schubert
231*7f2fe78bSCy Schubert /* Format some text into a non-empty dynamic buffer. */
232*7f2fe78bSCy Schubert k5_buf_init_dynamic(&buf);
233*7f2fe78bSCy Schubert k5_buf_add(&buf, "foo");
234*7f2fe78bSCy Schubert k5_buf_add_fmt(&buf, " %d ", 3);
235*7f2fe78bSCy Schubert check_buf(&buf, "fmt 3");
236*7f2fe78bSCy Schubert fail_if(buf.data == NULL || buf.len != 6, "fmt 3");
237*7f2fe78bSCy Schubert fail_if(memcmp(buf.data, "foo 3 ", 6) != 0, "fmt 3");
238*7f2fe78bSCy Schubert
239*7f2fe78bSCy Schubert /* Format more text into the same buffer, causing a big resize. */
240*7f2fe78bSCy Schubert k5_buf_add_fmt(&buf, "%s", data);
241*7f2fe78bSCy Schubert check_buf(&buf, "fmt 4");
242*7f2fe78bSCy Schubert fail_if(buf.space != 2048, "fmt 4");
243*7f2fe78bSCy Schubert fail_if(buf.data == NULL || buf.len != 1029, "fmt 4");
244*7f2fe78bSCy Schubert fail_if(memcmp((char *)buf.data + 6, data, 1023) != 0, "fmt 4");
245*7f2fe78bSCy Schubert k5_buf_free(&buf);
246*7f2fe78bSCy Schubert }
247*7f2fe78bSCy Schubert
248*7f2fe78bSCy Schubert int
main()249*7f2fe78bSCy Schubert main()
250*7f2fe78bSCy Schubert {
251*7f2fe78bSCy Schubert test_basic();
252*7f2fe78bSCy Schubert test_realloc();
253*7f2fe78bSCy Schubert test_overflow();
254*7f2fe78bSCy Schubert test_error();
255*7f2fe78bSCy Schubert test_truncate();
256*7f2fe78bSCy Schubert test_binary();
257*7f2fe78bSCy Schubert test_fmt();
258*7f2fe78bSCy Schubert return 0;
259*7f2fe78bSCy Schubert }
260