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