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 arbitrary data into Simple TLV */
102 : 1 : static void test_encode_simple(void)
103 : : {
104 : 1 : unsigned char *result = NULL;
105 : : int result_len = 0;
106 : 1 : unsigned char simple_value[] = "\x10\x11";
107 : 1 : unsigned char simple_encoded[] = "\x25\x02\x10\x11";
108 : 1 : unsigned char long_value[256] = "Long data value";
109 : 1 : unsigned char long_encoded[261] = "\x25\xFF\x00\x01Long data value";
110 : : static struct simpletlv_member simple[1] = {
111 : : {0x25, 2, {/*.value = simple_value*/}, SIMPLETLV_TYPE_LEAF}
112 : : };
113 : 1 : simple[0].value.value = simple_value;
114 : :
115 : : /* Encode simple short TLV with automatic allocation */
116 : : result = NULL;
117 : 1 : result_len = simpletlv_encode(simple, 1, &result, 0, NULL);
118 [ - + - + : 1 : g_assert_cmpmem(result, result_len, simple_encoded, 4);
- + ]
119 : 1 : g_free(result);
120 : :
121 : : /* Encode simple short TLV with pre-allocated buffer (long enough) */
122 : 1 : result = g_malloc(10);
123 : 1 : result_len = simpletlv_encode(simple, 1, &result, 10, NULL);
124 [ - + - + : 1 : g_assert_cmpmem(result, result_len, simple_encoded, 4);
- + ]
125 : 1 : g_free(result);
126 : :
127 : : /* Encode simple short TLV with pre-allocated buffer (too short) */
128 : 1 : result = g_malloc(2);
129 : 1 : result_len = simpletlv_encode(simple, 1, &result, 2, NULL);
130 [ - + ]: 1 : g_assert_cmpint(result_len, ==, -1);
131 : 1 : g_free(result);
132 : :
133 : : /* Encode only TL part */
134 : 1 : result = NULL;
135 : 1 : result_len = simpletlv_encode_tl(simple, 1, &result, 0, NULL);
136 [ - + - + : 1 : g_assert_cmpmem(result, result_len, "\x25\x02", 2);
- + ]
137 : 1 : g_free(result);
138 : :
139 : : /* Encode only VALUE part (equals to the value itself) */
140 : 1 : result = NULL;
141 : 1 : result_len = simpletlv_encode_val(simple, 1, &result, 0, NULL);
142 [ - + - + : 1 : g_assert_cmpmem(result, result_len, simple_value, 2);
- + ]
143 : 1 : g_free(result);
144 : :
145 : :
146 : : /* Prepare long value */
147 : 1 : memset(long_value+15, '\x00', 256-15);
148 : 1 : memset(long_encoded+19, '\x00', 256-15);
149 : 1 : simple[0].value.value = long_value;
150 : 1 : simple[0].length = 256;
151 : :
152 : :
153 : : /* Encode simple long TLV with automatic allocation */
154 : 1 : result = NULL;
155 : 1 : result_len = simpletlv_encode(simple, 1, &result, 0, NULL);
156 [ - + - + : 1 : g_assert_cmpmem(result, result_len, long_encoded, 260);
- + ]
157 : 1 : g_free(result);
158 : :
159 : : /* Encode simple long TLV with pre-allocated buffer (long enough) */
160 : 1 : result = g_malloc(300);
161 : 1 : result_len = simpletlv_encode(simple, 1, &result, 300, NULL);
162 [ - + - + : 1 : g_assert_cmpmem(result, result_len, long_encoded, 260);
- + ]
163 : 1 : g_free(result);
164 : :
165 : 1 : }
166 : :
167 : : /* Test that we can encode nested data into Simple TLV */
168 : 1 : static void test_encode_nested(void)
169 : : {
170 : 1 : unsigned char *result = NULL;
171 : : int result_len = 0;
172 : 1 : unsigned char simple_value[] = "\x12\x14";
173 : 1 : unsigned char encoded[] = "\x72\x04\x25\x02\x12\x14";
174 : : static struct simpletlv_member simple[1] = {
175 : : {0x25, 2, {/*.value = simple_value*/}, SIMPLETLV_TYPE_LEAF}
176 : : };
177 : : static struct simpletlv_member nested[1] = {
178 : : {0x72, 1, {/*.child = simple*/}, SIMPLETLV_TYPE_COMPOUND}
179 : : };
180 : 1 : simple[0].value.value = simple_value;
181 : 1 : nested[0].value.child = simple;
182 : :
183 : : /* Encode nested TLV with automatic allocation */
184 : : result = NULL;
185 : 1 : result_len = simpletlv_encode(nested, 1, &result, 0, NULL);
186 [ - + - + : 1 : g_assert_cmpmem(result, result_len, encoded, 6);
- + ]
187 : 1 : g_free(result);
188 : :
189 : : /* Encode nested TLV with pre-allocated buffer (long enough) */
190 : 1 : result = g_malloc(10);
191 : 1 : result_len = simpletlv_encode(nested, 1, &result, 10, NULL);
192 [ - + - + : 1 : g_assert_cmpmem(result, result_len, encoded, 6);
- + ]
193 : 1 : g_free(result);
194 : :
195 : : /* Encode simple short TLV with pre-allocated buffer (too short) */
196 : 1 : result = g_malloc(4);
197 : 1 : result_len = simpletlv_encode(nested, 1, &result, 4, NULL);
198 [ - + ]: 1 : g_assert_cmpint(result_len, ==, -1);
199 : 1 : g_free(result);
200 : :
201 : : /* Encode only TL part */
202 : 1 : result = NULL;
203 : 1 : result_len = simpletlv_encode_tl(nested, 1, &result, 0, NULL);
204 [ - + ]: 1 : g_assert_cmpint(result_len, ==, -1);
205 : :
206 : : /* Encode only VALUE part (equals to the value itself) */
207 : 1 : result = NULL;
208 : 1 : result_len = simpletlv_encode_val(nested, 1, &result, 0, NULL);
209 [ - + ]: 1 : g_assert_cmpint(result_len, ==, -1);
210 : 1 : }
211 : :
212 : 1 : static void test_encode_skipped(void)
213 : : {
214 : 1 : unsigned char *result = NULL;
215 : : size_t result_len = 0;
216 : 1 : unsigned char simple_value[] = "\x12\x14";
217 : 1 : unsigned char simple_value2[] = "\x16\x18";
218 : : static struct simpletlv_member simple[2] = {
219 : : {0x25, 2, {/*.value = simple_value*/}, SIMPLETLV_TYPE_LEAF},
220 : : {0x30, 2, {/*.value = simple_value2*/}, SIMPLETLV_TYPE_NONE}
221 : : };
222 : 1 : unsigned char encoded[] = "\x25\x02\x12\x14";
223 : :
224 : 1 : simple[0].value.value = simple_value;
225 : 1 : simple[1].value.value = simple_value2;
226 : :
227 : : /* Simple short value to TLV */
228 : : result = NULL;
229 : 1 : result_len = simpletlv_encode(simple, 2, &result, 0, NULL);
230 [ - + - + : 1 : g_assert_cmpmem(result, result_len, encoded, 4);
- + ]
231 : 1 : g_free(result);
232 : :
233 : : /* Simple short value to TL */
234 : 1 : result = NULL;
235 : 1 : result_len = simpletlv_encode_tl(simple, 2, &result, 0, NULL);
236 [ - + - + : 1 : g_assert_cmpmem(result, result_len, "\x25\x02", 2);
- + ]
237 : 1 : g_free(result);
238 : :
239 : : /* Simple short value to V */
240 : 1 : result = NULL;
241 : 1 : result_len = simpletlv_encode_val(simple, 2, &result, 0, NULL);
242 [ - + - + : 1 : g_assert_cmpmem(result, result_len, "\x12\x14", 2);
- + ]
243 : 1 : g_free(result);
244 : 1 : }
245 : :
246 : 1 : static void test_clone_simple(void)
247 : : {
248 : 1 : unsigned char *result = NULL;
249 : : size_t result_len = 0;
250 : 1 : unsigned char simple_value[] = "\x14\x18";
251 : 1 : unsigned char simple_value2[] = "\x64\x24\x44";
252 : : static struct simpletlv_member simple[2] = {
253 : : {0x13, 2, {/*.value = simple_value*/}, SIMPLETLV_TYPE_LEAF},
254 : : {0xDD, 3, {/*.value = simple_value2*/}, SIMPLETLV_TYPE_LEAF}
255 : : };
256 : 1 : unsigned char encoded[] = "\x13\x02\x14\x18\xDD\x03\x64\x24\x44";
257 : : struct simpletlv_member *clone;
258 : :
259 : 1 : simple[0].value.value = simple_value;
260 : 1 : simple[1].value.value = simple_value2;
261 : :
262 : 1 : clone = simpletlv_clone(simple, 2);
263 [ - + - + ]: 1 : g_assert_nonnull(clone);
264 : :
265 : 1 : result = NULL;
266 : 1 : result_len = simpletlv_encode(clone, 2, &result, 0, NULL);
267 [ - + - + : 1 : g_assert_cmpmem(result, result_len, encoded, 9);
- + ]
268 : 1 : g_free(result);
269 : 1 : simpletlv_free(clone, 2);
270 : 1 : }
271 : :
272 : 1 : static void test_parse_simple(void)
273 : : {
274 : 1 : unsigned char data[] = "\x13\x02\x14\x18\xDD\x03\x64\x24\x44";
275 : 1 : size_t data_len = 9, tlv_len = 0;
276 : : struct simpletlv_member *tlv;
277 : :
278 : 1 : tlv = simpletlv_parse(data, data_len, &tlv_len);
279 [ - + ]: 1 : g_assert_cmpint(tlv_len, ==, 2);
280 : :
281 [ - + ]: 1 : g_assert_cmpint(tlv[0].tag, ==, 0x13);
282 [ - + ]: 1 : g_assert_cmpint(tlv[0].length, ==, 0x02);
283 [ - + ]: 1 : g_assert_cmpint(tlv[0].type, ==, SIMPLETLV_TYPE_LEAF);
284 [ - + - + : 1 : g_assert_cmpmem(tlv[0].value.value, tlv[0].length, "\x14\x18", 2);
- + ]
285 : :
286 [ - + ]: 1 : g_assert_cmpint(tlv[1].tag, ==, 0xDD);
287 [ - + ]: 1 : g_assert_cmpint(tlv[1].length, ==, 0x03);
288 [ - + ]: 1 : g_assert_cmpint(tlv[1].type, ==, SIMPLETLV_TYPE_LEAF);
289 [ - + - + : 1 : g_assert_cmpmem(tlv[1].value.value, tlv[1].length, "\x64\x24\x44", 3);
- + ]
290 : :
291 : 1 : simpletlv_free(tlv, tlv_len);
292 : 1 : }
293 : :
294 : : /* If there is some gargabe in the end of buffer, we would like to
295 : : * return at least what was properly parsed, rahter than to fail
296 : : * hard.
297 : : * Also makes sure we do not leak memory or crash on bad data.
298 : : *
299 : : * This is an issue for OpenSC at this moment, which fails to encode
300 : : * last TLV into the compound buffer for data objects.
301 : : */
302 : 1 : static void test_parse_last_bad(void)
303 : : {
304 : : size_t data_len = 9;
305 : 1 : unsigned char data[] = "\x13\x02\x14\x18\x28\x13\x64\x24\x44";
306 : : /* this length is oveflow -^ */
307 : : size_t data2_len = 7;
308 : 1 : unsigned char data2[] = "\x13\x02\x14\x18\x28\xFF\xFF";
309 : : /* this length is missing last byte -^ */
310 : : size_t data3_len = 5;
311 : 1 : unsigned char data3[] = "\x13\x02\x14\x18\x12";
312 : : /* this length is missed completely -^ */
313 : 1 : size_t tlv_len = 0;
314 : : struct simpletlv_member *tlv;
315 : :
316 : : /* Test the overflow length in the last member */
317 : 1 : tlv = simpletlv_parse(data, data_len, &tlv_len);
318 [ - + ]: 1 : g_assert_cmpint(tlv_len, ==, 1);
319 : :
320 [ - + ]: 1 : g_assert_cmpint(tlv[0].tag, ==, 0x13);
321 [ - + ]: 1 : g_assert_cmpint(tlv[0].length, ==, 0x02);
322 [ - + ]: 1 : g_assert_cmpint(tlv[0].type, ==, SIMPLETLV_TYPE_LEAF);
323 [ - + - + : 1 : g_assert_cmpmem(tlv[0].value.value, tlv[0].length, "\x14\x18", 2);
- + ]
324 : :
325 : 1 : simpletlv_free(tlv, tlv_len);
326 : :
327 : : /* Test the truncated length item in last member */
328 : 1 : tlv = simpletlv_parse(data2, data2_len, &tlv_len);
329 [ - + ]: 1 : g_assert_cmpint(tlv_len, ==, 1);
330 : :
331 [ - + ]: 1 : g_assert_cmpint(tlv[0].tag, ==, 0x13);
332 [ - + ]: 1 : g_assert_cmpint(tlv[0].length, ==, 0x02);
333 [ - + ]: 1 : g_assert_cmpint(tlv[0].type, ==, SIMPLETLV_TYPE_LEAF);
334 [ - + - + : 1 : g_assert_cmpmem(tlv[0].value.value, tlv[0].length, "\x14\x18", 2);
- + ]
335 : :
336 : 1 : simpletlv_free(tlv, tlv_len);
337 : :
338 : : /* Test the missing length item in last member */
339 : 1 : tlv = simpletlv_parse(data3, data3_len, &tlv_len);
340 [ - + ]: 1 : g_assert_cmpint(tlv_len, ==, 1);
341 : :
342 [ - + ]: 1 : g_assert_cmpint(tlv[0].tag, ==, 0x13);
343 [ - + ]: 1 : g_assert_cmpint(tlv[0].length, ==, 0x02);
344 [ - + ]: 1 : g_assert_cmpint(tlv[0].type, ==, SIMPLETLV_TYPE_LEAF);
345 [ - + - + : 1 : g_assert_cmpmem(tlv[0].value.value, tlv[0].length, "\x14\x18", 2);
- + ]
346 : :
347 : 1 : simpletlv_free(tlv, tlv_len);
348 : 1 : }
349 : :
350 : 1 : int main(int argc, char *argv[])
351 : : {
352 : : int ret;
353 : :
354 : 1 : g_test_init(&argc, &argv, NULL);
355 : :
356 : 1 : loop = g_main_loop_new(NULL, TRUE);
357 : :
358 : 1 : g_test_add_func("/simpletlv/length/simple", test_length_simple);
359 : 1 : g_test_add_func("/simpletlv/length/nested", test_length_nested);
360 : 1 : g_test_add_func("/simpletlv/length/skipped", test_length_skipped);
361 : 1 : g_test_add_func("/simpletlv/encode/simple", test_encode_simple);
362 : 1 : g_test_add_func("/simpletlv/encode/nested", test_encode_nested);
363 : 1 : g_test_add_func("/simpletlv/encode/skipped", test_encode_skipped);
364 : 1 : g_test_add_func("/simpletlv/parse/simple", test_parse_simple);
365 : 1 : g_test_add_func("/simpletlv/parse/last_bad", test_parse_last_bad);
366 : 1 : g_test_add_func("/simpletlv/clone/simple", test_clone_simple);
367 : :
368 : 1 : ret = g_test_run();
369 : :
370 : 1 : g_main_loop_unref(loop);
371 : :
372 : : return ret;
373 : : }
374 : :
375 : : /* vim: set ts=4 sw=4 tw=0 noet expandtab: */
|