Branch data Line data Source code
1 : : #include <glib.h>
2 : : #include <string.h>
3 : : #include "simpletlv.h"
4 : :
5 : : static GMainLoop *loop;
6 : :
7 : : /* Test that length estimations are sane */
8 : 1 : static void test_length_simple(void)
9 : : {
10 : : size_t length = 0;
11 : 1 : unsigned char simple_value[] = "\x10\x11";
12 : 1 : unsigned char long_value[256] = "Long data value";
13 : : static struct simpletlv_member simple[1] = {
14 : : {0x25, 2, {/*.value = simple_value*/}, SIMPLETLV_TYPE_LEAF}
15 : : };
16 : 1 : simple[0].value.value = simple_value;
17 : :
18 : : /* Simple short value to TLV */
19 : 1 : length = simpletlv_get_length(simple, 1, SIMPLETLV_BOTH);
20 [ - + ]: 1 : g_assert_cmpint(length, ==, 4);
21 : :
22 : : /* Simple short value to TL */
23 : 1 : length = simpletlv_get_length(simple, 1, SIMPLETLV_TL);
24 [ - + ]: 1 : g_assert_cmpint(length, ==, 2);
25 : :
26 : : /* Simple short value to V */
27 : 1 : length = simpletlv_get_length(simple, 1, SIMPLETLV_VALUE);
28 [ - + ]: 1 : g_assert_cmpint(length, ==, 2);
29 : :
30 : :
31 : : /* Prepare long value */
32 : 1 : simple[0].value.value = long_value;
33 : 1 : simple[0].length = 256;
34 : :
35 : :
36 : : /* Simple long value to TLV */
37 : 1 : length = simpletlv_get_length(simple, 1, SIMPLETLV_BOTH);
38 [ - + ]: 1 : g_assert_cmpint(length, ==, 260);
39 : :
40 : : /* Simple long value to TL */
41 : 1 : length = simpletlv_get_length(simple, 1, SIMPLETLV_TL);
42 [ - + ]: 1 : g_assert_cmpint(length, ==, 4);
43 : :
44 : : /* Simple long value to V */
45 : 1 : length = simpletlv_get_length(simple, 1, SIMPLETLV_VALUE);
46 [ - + ]: 1 : g_assert_cmpint(length, ==, 256);
47 : 1 : }
48 : :
49 : 1 : static void test_length_nested(void)
50 : : {
51 : : int length = 0;
52 : 1 : unsigned char simple_value[] = "\x12\x14";
53 : : static struct simpletlv_member simple[1] = {
54 : : {0x25, 2, {/*.value = simple_value*/}, SIMPLETLV_TYPE_LEAF}
55 : : };
56 : : static struct simpletlv_member nested[1] = {
57 : : {0x72, 1, {/*.child = simple*/}, SIMPLETLV_TYPE_COMPOUND}
58 : : };
59 : 1 : simple[0].value.value = simple_value;
60 : 1 : nested[0].value.child = simple;
61 : :
62 : : /* Simple short value to TLV */
63 : 1 : length = simpletlv_get_length(nested, 1, SIMPLETLV_BOTH);
64 [ - + ]: 1 : g_assert_cmpint(length, ==, 6);
65 : :
66 : : /* Nested structures do not support splitting TL and V buffers ?? */
67 : : /* Simple short value to TL */
68 : 1 : length = simpletlv_get_length(nested, 1, SIMPLETLV_TL);
69 [ - + ]: 1 : g_assert_cmpint(length, ==, -1);
70 : :
71 : : /* Simple short value to V */
72 : 1 : length = simpletlv_get_length(nested, 1, SIMPLETLV_VALUE);
73 [ - + ]: 1 : g_assert_cmpint(length, ==, -1);
74 : 1 : }
75 : :
76 : 1 : static void test_length_skipped(void)
77 : : {
78 : : size_t length = 0;
79 : 1 : unsigned char simple_value[] = "\x12\x14";
80 : 1 : unsigned char simple_value2[] = "\x16\x18";
81 : : static struct simpletlv_member simple[2] = {
82 : : {0x25, 2, {/*.value = simple_value*/}, SIMPLETLV_TYPE_LEAF},
83 : : {0x30, 2, {/*.value = simple_value2*/}, SIMPLETLV_TYPE_NONE}
84 : : };
85 : 1 : simple[0].value.value = simple_value;
86 : 1 : simple[1].value.value = simple_value2;
87 : :
88 : : /* Simple short value to TLV */
89 : 1 : length = simpletlv_get_length(simple, 2, SIMPLETLV_BOTH);
90 [ - + ]: 1 : g_assert_cmpint(length, ==, 4);
91 : :
92 : : /* Simple short value to TL */
93 : 1 : length = simpletlv_get_length(simple, 2, SIMPLETLV_TL);
94 [ - + ]: 1 : g_assert_cmpint(length, ==, 2);
95 : :
96 : : /* Simple short value to V */
97 : 1 : length = simpletlv_get_length(simple, 2, SIMPLETLV_VALUE);
98 [ - + ]: 1 : g_assert_cmpint(length, ==, 2);
99 : 1 : }
100 : :
101 : : /* Test that we can encode zero-length values into Simple TLV */
102 : 1 : static void test_encode_zero(void)
103 : : {
104 : 1 : unsigned char *result = NULL, *p = NULL;
105 : : int result_len = 0;
106 : 1 : unsigned char empty_value[] = "";
107 : 1 : unsigned char empty_encoded[] = "\x25\x00";
108 : : static struct simpletlv_member simple[1] = {
109 : : {0x25, 0, {/*.value = empty_value*/}, SIMPLETLV_TYPE_LEAF}
110 : : };
111 : 1 : simple[0].value.value = empty_value;
112 : :
113 : : /* Encode simple short TLV with automatic allocation */
114 : : result = NULL;
115 : 1 : result_len = simpletlv_encode(simple, 1, &result, 0, NULL);
116 [ - + - + : 1 : g_assert_cmpmem(result, result_len, empty_encoded, 2);
- + ]
117 : 1 : g_free(result);
118 : :
119 : : /* Encode simple short TLV with pre-allocated buffer (long enough) */
120 : 1 : result = g_malloc(10);
121 : 1 : result_len = simpletlv_encode(simple, 1, &result, 10, NULL);
122 [ - + - + : 1 : g_assert_cmpmem(result, result_len, empty_encoded, 2);
- + ]
123 : 1 : g_free(result);
124 : :
125 : : /* Encode simple short TLV with pre-allocated buffer (too short) */
126 : 1 : result = g_malloc(1);
127 : 1 : result_len = simpletlv_encode(simple, 1, &result, 1, NULL);
128 [ - + ]: 1 : g_assert_cmpint(result_len, ==, -1);
129 : 1 : g_free(result);
130 : :
131 : : /* Encode only TL part */
132 : 1 : result = NULL;
133 : 1 : result_len = simpletlv_encode_tl(simple, 1, &result, 0, NULL);
134 [ - + - + : 1 : g_assert_cmpmem(result, result_len, "\x25\x00", 2);
- + ]
135 : 1 : g_free(result);
136 : :
137 : : /* Encode only VALUE part (equals to the value itself) */
138 : 1 : result = NULL;
139 : 1 : result_len = simpletlv_encode_val(simple, 1, &result, 0, NULL);
140 [ - + - + ]: 1 : g_assert_cmpmem(result, result_len, empty_value, 0);
141 : 1 : g_free(result);
142 : :
143 : : /* Encode only empty VALUE part with pre-allocated buffer (long enough) */
144 : 1 : result = g_malloc(10);
145 : 1 : result_len = simpletlv_encode_val(simple, 1, &result, 10, &p);
146 [ - + - + ]: 1 : g_assert_cmpmem(result, result_len, empty_value, 0);
147 : 1 : g_free(result);
148 : 1 : }
149 : :
150 : : /* Test that we can encode arbitrary data into Simple TLV */
151 : 1 : static void test_encode_simple(void)
152 : : {
153 : 1 : unsigned char *result = NULL;
154 : : int result_len = 0;
155 : 1 : unsigned char simple_value[] = "\x10\x11";
156 : 1 : unsigned char simple_encoded[] = "\x25\x02\x10\x11";
157 : 1 : unsigned char long_value[256] = "Long data value";
158 : 1 : unsigned char long_encoded[261] = "\x25\xFF\x00\x01Long data value";
159 : : static struct simpletlv_member simple[1] = {
160 : : {0x25, 2, {/*.value = simple_value*/}, SIMPLETLV_TYPE_LEAF}
161 : : };
162 : 1 : simple[0].value.value = simple_value;
163 : :
164 : : /* Encode simple short TLV with automatic allocation */
165 : : result = NULL;
166 : 1 : result_len = simpletlv_encode(simple, 1, &result, 0, NULL);
167 [ - + - + : 1 : g_assert_cmpmem(result, result_len, simple_encoded, 4);
- + ]
168 : 1 : g_free(result);
169 : :
170 : : /* Encode simple short TLV with pre-allocated buffer (long enough) */
171 : 1 : result = g_malloc(10);
172 : 1 : result_len = simpletlv_encode(simple, 1, &result, 10, NULL);
173 [ - + - + : 1 : g_assert_cmpmem(result, result_len, simple_encoded, 4);
- + ]
174 : 1 : g_free(result);
175 : :
176 : : /* Encode simple short TLV with pre-allocated buffer (too short) */
177 : 1 : result = g_malloc(2);
178 : 1 : result_len = simpletlv_encode(simple, 1, &result, 2, NULL);
179 [ - + ]: 1 : g_assert_cmpint(result_len, ==, -1);
180 : 1 : g_free(result);
181 : :
182 : : /* Encode only TL part */
183 : 1 : result = NULL;
184 : 1 : result_len = simpletlv_encode_tl(simple, 1, &result, 0, NULL);
185 [ - + - + : 1 : g_assert_cmpmem(result, result_len, "\x25\x02", 2);
- + ]
186 : 1 : g_free(result);
187 : :
188 : : /* Encode only VALUE part (equals to the value itself) */
189 : 1 : result = NULL;
190 : 1 : result_len = simpletlv_encode_val(simple, 1, &result, 0, NULL);
191 [ - + - + : 1 : g_assert_cmpmem(result, result_len, simple_value, 2);
- + ]
192 : 1 : g_free(result);
193 : :
194 : :
195 : : /* Prepare long value */
196 : 1 : memset(long_value+15, '\x00', 256-15);
197 : 1 : memset(long_encoded+19, '\x00', 256-15);
198 : 1 : simple[0].value.value = long_value;
199 : 1 : simple[0].length = 256;
200 : :
201 : :
202 : : /* Encode simple long TLV with automatic allocation */
203 : 1 : result = NULL;
204 : 1 : result_len = simpletlv_encode(simple, 1, &result, 0, NULL);
205 [ - + - + : 1 : g_assert_cmpmem(result, result_len, long_encoded, 260);
- + ]
206 : 1 : g_free(result);
207 : :
208 : : /* Encode simple long TLV with pre-allocated buffer (long enough) */
209 : 1 : result = g_malloc(300);
210 : 1 : result_len = simpletlv_encode(simple, 1, &result, 300, NULL);
211 [ - + - + : 1 : g_assert_cmpmem(result, result_len, long_encoded, 260);
- + ]
212 : 1 : g_free(result);
213 : :
214 : 1 : }
215 : :
216 : : /* Test that we can encode nested data into Simple TLV */
217 : 1 : static void test_encode_nested(void)
218 : : {
219 : 1 : unsigned char *result = NULL;
220 : : int result_len = 0;
221 : 1 : unsigned char simple_value[] = "\x12\x14";
222 : 1 : unsigned char encoded[] = "\x72\x04\x25\x02\x12\x14";
223 : : static struct simpletlv_member simple[1] = {
224 : : {0x25, 2, {/*.value = simple_value*/}, SIMPLETLV_TYPE_LEAF}
225 : : };
226 : : static struct simpletlv_member nested[1] = {
227 : : {0x72, 1, {/*.child = simple*/}, SIMPLETLV_TYPE_COMPOUND}
228 : : };
229 : 1 : simple[0].value.value = simple_value;
230 : 1 : nested[0].value.child = simple;
231 : :
232 : : /* Encode nested TLV with automatic allocation */
233 : : result = NULL;
234 : 1 : result_len = simpletlv_encode(nested, 1, &result, 0, NULL);
235 [ - + - + : 1 : g_assert_cmpmem(result, result_len, encoded, 6);
- + ]
236 : 1 : g_free(result);
237 : :
238 : : /* Encode nested TLV with pre-allocated buffer (long enough) */
239 : 1 : result = g_malloc(10);
240 : 1 : result_len = simpletlv_encode(nested, 1, &result, 10, NULL);
241 [ - + - + : 1 : g_assert_cmpmem(result, result_len, encoded, 6);
- + ]
242 : 1 : g_free(result);
243 : :
244 : : /* Encode simple short TLV with pre-allocated buffer (too short) */
245 : 1 : result = g_malloc(4);
246 : 1 : result_len = simpletlv_encode(nested, 1, &result, 4, NULL);
247 [ - + ]: 1 : g_assert_cmpint(result_len, ==, -1);
248 : 1 : g_free(result);
249 : :
250 : : /* Encode only TL part */
251 : 1 : result = NULL;
252 : 1 : result_len = simpletlv_encode_tl(nested, 1, &result, 0, NULL);
253 [ - + ]: 1 : g_assert_cmpint(result_len, ==, -1);
254 : :
255 : : /* Encode only VALUE part (equals to the value itself) */
256 : 1 : result = NULL;
257 : 1 : result_len = simpletlv_encode_val(nested, 1, &result, 0, NULL);
258 [ - + ]: 1 : g_assert_cmpint(result_len, ==, -1);
259 : 1 : }
260 : :
261 : 1 : static void test_encode_skipped(void)
262 : : {
263 : 1 : unsigned char *result = NULL;
264 : : size_t result_len = 0;
265 : 1 : unsigned char simple_value[] = "\x12\x14";
266 : 1 : unsigned char simple_value2[] = "\x16\x18";
267 : : static struct simpletlv_member simple[2] = {
268 : : {0x25, 2, {/*.value = simple_value*/}, SIMPLETLV_TYPE_LEAF},
269 : : {0x30, 2, {/*.value = simple_value2*/}, SIMPLETLV_TYPE_NONE}
270 : : };
271 : 1 : unsigned char encoded[] = "\x25\x02\x12\x14";
272 : :
273 : 1 : simple[0].value.value = simple_value;
274 : 1 : simple[1].value.value = simple_value2;
275 : :
276 : : /* Simple short value to TLV */
277 : : result = NULL;
278 : 1 : result_len = simpletlv_encode(simple, 2, &result, 0, NULL);
279 [ - + - + : 1 : g_assert_cmpmem(result, result_len, encoded, 4);
- + ]
280 : 1 : g_free(result);
281 : :
282 : : /* Simple short value to TL */
283 : 1 : result = NULL;
284 : 1 : result_len = simpletlv_encode_tl(simple, 2, &result, 0, NULL);
285 [ - + - + : 1 : g_assert_cmpmem(result, result_len, "\x25\x02", 2);
- + ]
286 : 1 : g_free(result);
287 : :
288 : : /* Simple short value to V */
289 : 1 : result = NULL;
290 : 1 : result_len = simpletlv_encode_val(simple, 2, &result, 0, NULL);
291 [ - + - + : 1 : g_assert_cmpmem(result, result_len, "\x12\x14", 2);
- + ]
292 : 1 : g_free(result);
293 : 1 : }
294 : :
295 : 1 : static void test_clone_simple(void)
296 : : {
297 : 1 : unsigned char *result = NULL;
298 : : size_t result_len = 0;
299 : 1 : unsigned char simple_value[] = "\x14\x18";
300 : 1 : unsigned char simple_value2[] = "\x64\x24\x44";
301 : : static struct simpletlv_member simple[2] = {
302 : : {0x13, 2, {/*.value = simple_value*/}, SIMPLETLV_TYPE_LEAF},
303 : : {0xDD, 3, {/*.value = simple_value2*/}, SIMPLETLV_TYPE_LEAF}
304 : : };
305 : 1 : unsigned char encoded[] = "\x13\x02\x14\x18\xDD\x03\x64\x24\x44";
306 : : struct simpletlv_member *clone;
307 : :
308 : 1 : simple[0].value.value = simple_value;
309 : 1 : simple[1].value.value = simple_value2;
310 : :
311 : 1 : clone = simpletlv_clone(simple, 2);
312 [ - + - + ]: 1 : g_assert_nonnull(clone);
313 : :
314 : 1 : result = NULL;
315 : 1 : result_len = simpletlv_encode(clone, 2, &result, 0, NULL);
316 [ - + - + : 1 : g_assert_cmpmem(result, result_len, encoded, 9);
- + ]
317 : 1 : g_free(result);
318 : 1 : simpletlv_free(clone, 2);
319 : 1 : }
320 : :
321 : 1 : static void test_parse_simple(void)
322 : : {
323 : 1 : unsigned char data[] = "\x13\x02\x14\x18\xDD\x03\x64\x24\x44";
324 : 1 : size_t data_len = 9, tlv_len = 0;
325 : : struct simpletlv_member *tlv;
326 : :
327 : 1 : tlv = simpletlv_parse(data, data_len, &tlv_len);
328 [ - + ]: 1 : g_assert_cmpint(tlv_len, ==, 2);
329 : :
330 [ - + ]: 1 : g_assert_cmpint(tlv[0].tag, ==, 0x13);
331 [ - + ]: 1 : g_assert_cmpint(tlv[0].length, ==, 0x02);
332 [ - + ]: 1 : g_assert_cmpint(tlv[0].type, ==, SIMPLETLV_TYPE_LEAF);
333 [ - + - + : 1 : g_assert_cmpmem(tlv[0].value.value, tlv[0].length, "\x14\x18", 2);
- + ]
334 : :
335 [ - + ]: 1 : g_assert_cmpint(tlv[1].tag, ==, 0xDD);
336 [ - + ]: 1 : g_assert_cmpint(tlv[1].length, ==, 0x03);
337 [ - + ]: 1 : g_assert_cmpint(tlv[1].type, ==, SIMPLETLV_TYPE_LEAF);
338 [ - + - + : 1 : g_assert_cmpmem(tlv[1].value.value, tlv[1].length, "\x64\x24\x44", 3);
- + ]
339 : :
340 : 1 : simpletlv_free(tlv, tlv_len);
341 : 1 : }
342 : :
343 : : /* If there is some gargabe in the end of buffer, we would like to
344 : : * return at least what was properly parsed, rahter than to fail
345 : : * hard.
346 : : * Also makes sure we do not leak memory or crash on bad data.
347 : : *
348 : : * This is an issue for OpenSC at this moment, which fails to encode
349 : : * last TLV into the compound buffer for data objects.
350 : : */
351 : 1 : static void test_parse_last_bad(void)
352 : : {
353 : : size_t data_len = 9;
354 : 1 : unsigned char data[] = "\x13\x02\x14\x18\x28\x13\x64\x24\x44";
355 : : /* this length is oveflow -^ */
356 : : size_t data2_len = 7;
357 : 1 : unsigned char data2[] = "\x13\x02\x14\x18\x28\xFF\xFF";
358 : : /* this length is missing last byte -^ */
359 : : size_t data3_len = 5;
360 : 1 : unsigned char data3[] = "\x13\x02\x14\x18\x12";
361 : : /* this length is missed completely -^ */
362 : 1 : size_t tlv_len = 0;
363 : : struct simpletlv_member *tlv;
364 : :
365 : : /* Test the overflow length in the last member */
366 : 1 : tlv = simpletlv_parse(data, data_len, &tlv_len);
367 [ - + ]: 1 : g_assert_cmpint(tlv_len, ==, 1);
368 : :
369 [ - + ]: 1 : g_assert_cmpint(tlv[0].tag, ==, 0x13);
370 [ - + ]: 1 : g_assert_cmpint(tlv[0].length, ==, 0x02);
371 [ - + ]: 1 : g_assert_cmpint(tlv[0].type, ==, SIMPLETLV_TYPE_LEAF);
372 [ - + - + : 1 : g_assert_cmpmem(tlv[0].value.value, tlv[0].length, "\x14\x18", 2);
- + ]
373 : :
374 : 1 : simpletlv_free(tlv, tlv_len);
375 : :
376 : : /* Test the truncated length item in last member */
377 : 1 : tlv = simpletlv_parse(data2, data2_len, &tlv_len);
378 [ - + ]: 1 : g_assert_cmpint(tlv_len, ==, 1);
379 : :
380 [ - + ]: 1 : g_assert_cmpint(tlv[0].tag, ==, 0x13);
381 [ - + ]: 1 : g_assert_cmpint(tlv[0].length, ==, 0x02);
382 [ - + ]: 1 : g_assert_cmpint(tlv[0].type, ==, SIMPLETLV_TYPE_LEAF);
383 [ - + - + : 1 : g_assert_cmpmem(tlv[0].value.value, tlv[0].length, "\x14\x18", 2);
- + ]
384 : :
385 : 1 : simpletlv_free(tlv, tlv_len);
386 : :
387 : : /* Test the missing length item in last member */
388 : 1 : tlv = simpletlv_parse(data3, data3_len, &tlv_len);
389 [ - + ]: 1 : g_assert_cmpint(tlv_len, ==, 1);
390 : :
391 [ - + ]: 1 : g_assert_cmpint(tlv[0].tag, ==, 0x13);
392 [ - + ]: 1 : g_assert_cmpint(tlv[0].length, ==, 0x02);
393 [ - + ]: 1 : g_assert_cmpint(tlv[0].type, ==, SIMPLETLV_TYPE_LEAF);
394 [ - + - + : 1 : g_assert_cmpmem(tlv[0].value.value, tlv[0].length, "\x14\x18", 2);
- + ]
395 : :
396 : 1 : simpletlv_free(tlv, tlv_len);
397 : 1 : }
398 : :
399 : 1 : int main(int argc, char *argv[])
400 : : {
401 : : int ret;
402 : :
403 : 1 : g_test_init(&argc, &argv, NULL);
404 : :
405 : 1 : loop = g_main_loop_new(NULL, TRUE);
406 : :
407 : 1 : g_test_add_func("/simpletlv/length/simple", test_length_simple);
408 : 1 : g_test_add_func("/simpletlv/length/nested", test_length_nested);
409 : 1 : g_test_add_func("/simpletlv/length/skipped", test_length_skipped);
410 : 1 : g_test_add_func("/simpletlv/encode/zero", test_encode_zero);
411 : 1 : g_test_add_func("/simpletlv/encode/simple", test_encode_simple);
412 : 1 : g_test_add_func("/simpletlv/encode/nested", test_encode_nested);
413 : 1 : g_test_add_func("/simpletlv/encode/skipped", test_encode_skipped);
414 : 1 : g_test_add_func("/simpletlv/parse/simple", test_parse_simple);
415 : 1 : g_test_add_func("/simpletlv/parse/last_bad", test_parse_last_bad);
416 : 1 : g_test_add_func("/simpletlv/clone/simple", test_clone_simple);
417 : :
418 : 1 : ret = g_test_run();
419 : :
420 : 1 : g_main_loop_unref(loop);
421 : :
422 : : return ret;
423 : : }
424 : :
425 : : /* vim: set ts=4 sw=4 tw=0 noet expandtab: */
|