1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-marshal-validate-util.c Would be in dbus-marshal-validate.c, but only used by tests/bus
3 *
4 * Copyright (C) 2005 Red Hat, Inc.
5 *
6 * Licensed under the Academic Free License version 2.1
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 */
23
24 #include <config.h>
25 #ifdef DBUS_BUILD_TESTS
26
27 #ifndef DOXYGEN_SHOULD_SKIP_THIS
28
29 #include "dbus-internals.h"
30 #include "dbus-marshal-validate.h"
31 #include "dbus-marshal-recursive.h"
32
33 #include "dbus-test.h"
34 #include <stdio.h>
35
36 typedef struct
37 {
38 const char *data;
39 DBusValidity expected;
40 } ValidityTest;
41
42 static void
run_validity_tests(const ValidityTest * tests,int n_tests,DBusValidity (* func)(const DBusString *,int,int))43 run_validity_tests (const ValidityTest *tests,
44 int n_tests,
45 DBusValidity (* func) (const DBusString*,int,int))
46 {
47 int i;
48
49 for (i = 0; i < n_tests; i++)
50 {
51 DBusString str;
52 DBusValidity v;
53
54 _dbus_string_init_const (&str, tests[i].data);
55
56 v = (*func) (&str, 0, _dbus_string_get_length (&str));
57
58 if (v != tests[i].expected)
59 {
60 _dbus_warn ("Improper validation result %d for '%s'\n",
61 v, tests[i].data);
62 _dbus_assert_not_reached ("test failed");
63 }
64
65 ++i;
66 }
67 }
68
69 static const ValidityTest signature_tests[] = {
70 { "", DBUS_VALID },
71 { "i", DBUS_VALID },
72 { "ai", DBUS_VALID },
73 { "(i)", DBUS_VALID },
74 { "w", DBUS_INVALID_UNKNOWN_TYPECODE },
75 { "a", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
76 { "aaaaaa", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
77 { "ii(ii)a", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
78 { "ia", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
79 /* DBUS_INVALID_SIGNATURE_TOO_LONG, */ /* too hard to test this way */
80 { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
81 DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION },
82 { "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((ii))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))",
83 DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION },
84 { ")", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED },
85 { "i)", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED },
86 { "a)", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED },
87 { "(", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
88 { "(i", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
89 { "(iiiii", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
90 { "(ai", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
91 { "()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
92 { "(())", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
93 { "a()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
94 { "i()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
95 { "()i", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
96 { "(a)", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
97 { "a{ia}", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
98 { "a{}", DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS },
99 { "a{aii}", DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE },
100 /* { "a{i}", DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD }, */
101 /* { "{is}", DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY }, */
102 /* { "a{isi}", DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS }, */
103 };
104
105 dbus_bool_t
_dbus_marshal_validate_test(void)106 _dbus_marshal_validate_test (void)
107 {
108 DBusString str;
109 int i;
110
111 const char *valid_paths[] = {
112 "/",
113 "/foo/bar",
114 "/foo",
115 "/foo/bar/baz"
116 };
117 const char *invalid_paths[] = {
118 "bar",
119 "bar/baz",
120 "/foo/bar/",
121 "/foo/"
122 "foo/",
123 "boo//blah",
124 "//",
125 "///",
126 "foo///blah/",
127 "Hello World",
128 "",
129 " ",
130 "foo bar"
131 };
132
133 const char *valid_interfaces[] = {
134 "org.freedesktop.Foo",
135 "Bar.Baz",
136 "Blah.Blah.Blah.Blah.Blah",
137 "a.b",
138 "a.b.c.d.e.f.g",
139 "a0.b1.c2.d3.e4.f5.g6",
140 "abc123.foo27"
141 };
142 const char *invalid_interfaces[] = {
143 ".",
144 "",
145 "..",
146 ".Foo.Bar",
147 "..Foo.Bar",
148 "Foo.Bar.",
149 "Foo.Bar..",
150 "Foo",
151 "9foo.bar.baz",
152 "foo.bar..baz",
153 "foo.bar...baz",
154 "foo.bar.b..blah",
155 ":",
156 ":0-1",
157 "10",
158 ":11.34324",
159 "0.0.0",
160 "0..0",
161 "foo.Bar.%",
162 "foo.Bar!!",
163 "!Foo.bar.bz",
164 "foo.$.blah",
165 "",
166 " ",
167 "foo bar"
168 };
169
170 const char *valid_unique_names[] = {
171 ":0",
172 ":a",
173 ":",
174 ":.a",
175 ":.1",
176 ":0.1",
177 ":000.2222",
178 ":.blah",
179 ":abce.freedesktop.blah"
180 };
181 const char *invalid_unique_names[] = {
182 //":-",
183 ":!",
184 //":0-10",
185 ":blah.",
186 ":blah.",
187 ":blah..org",
188 ":blah.org..",
189 ":..blah.org",
190 "",
191 " ",
192 "foo bar"
193 };
194
195 const char *valid_members[] = {
196 "Hello",
197 "Bar",
198 "foobar",
199 "_foobar",
200 "foo89"
201 };
202
203 const char *invalid_members[] = {
204 "9Hello",
205 "10",
206 "1",
207 "foo-bar",
208 "blah.org",
209 ".blah",
210 "blah.",
211 "Hello.",
212 "!foo",
213 "",
214 " ",
215 "foo bar"
216 };
217
218 const char *valid_signatures[] = {
219 "",
220 "sss",
221 "i",
222 "b"
223 };
224
225 const char *invalid_signatures[] = {
226 " ",
227 "not a valid signature",
228 "123",
229 ".",
230 "(",
231 "a{(ii)i}" /* https://bugs.freedesktop.org/show_bug.cgi?id=17803 */
232 };
233
234 /* Signature with reason */
235
236 run_validity_tests (signature_tests, _DBUS_N_ELEMENTS (signature_tests),
237 _dbus_validate_signature_with_reason);
238
239 /* Path validation */
240 i = 0;
241 while (i < (int) _DBUS_N_ELEMENTS (valid_paths))
242 {
243 _dbus_string_init_const (&str, valid_paths[i]);
244
245 if (!_dbus_validate_path (&str, 0,
246 _dbus_string_get_length (&str)))
247 {
248 _dbus_warn ("Path \"%s\" should have been valid\n", valid_paths[i]);
249 _dbus_assert_not_reached ("invalid path");
250 }
251
252 ++i;
253 }
254
255 i = 0;
256 while (i < (int) _DBUS_N_ELEMENTS (invalid_paths))
257 {
258 _dbus_string_init_const (&str, invalid_paths[i]);
259
260 if (_dbus_validate_path (&str, 0,
261 _dbus_string_get_length (&str)))
262 {
263 _dbus_warn ("Path \"%s\" should have been invalid\n", invalid_paths[i]);
264 _dbus_assert_not_reached ("valid path");
265 }
266
267 ++i;
268 }
269
270 /* Interface validation */
271 i = 0;
272 while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
273 {
274 _dbus_string_init_const (&str, valid_interfaces[i]);
275
276 if (!_dbus_validate_interface (&str, 0,
277 _dbus_string_get_length (&str)))
278 {
279 _dbus_warn ("Interface \"%s\" should have been valid\n", valid_interfaces[i]);
280 _dbus_assert_not_reached ("invalid interface");
281 }
282
283 ++i;
284 }
285
286 i = 0;
287 while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
288 {
289 _dbus_string_init_const (&str, invalid_interfaces[i]);
290
291 if (_dbus_validate_interface (&str, 0,
292 _dbus_string_get_length (&str)))
293 {
294 _dbus_warn ("Interface \"%s\" should have been invalid\n", invalid_interfaces[i]);
295 _dbus_assert_not_reached ("valid interface");
296 }
297
298 ++i;
299 }
300
301 /* Bus name validation (check that valid interfaces are valid bus names,
302 * and invalid interfaces are invalid services except if they start with ':')
303 */
304 i = 0;
305 while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
306 {
307 _dbus_string_init_const (&str, valid_interfaces[i]);
308
309 if (!_dbus_validate_bus_name (&str, 0,
310 _dbus_string_get_length (&str)))
311 {
312 _dbus_warn ("Bus name \"%s\" should have been valid\n", valid_interfaces[i]);
313 _dbus_assert_not_reached ("invalid bus name");
314 }
315
316 ++i;
317 }
318
319 i = 0;
320 while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
321 {
322 if (invalid_interfaces[i][0] != ':')
323 {
324 _dbus_string_init_const (&str, invalid_interfaces[i]);
325
326 if (_dbus_validate_bus_name (&str, 0,
327 _dbus_string_get_length (&str)))
328 {
329 _dbus_warn ("Bus name \"%s\" should have been invalid\n", invalid_interfaces[i]);
330 _dbus_assert_not_reached ("valid bus name");
331 }
332 }
333
334 ++i;
335 }
336
337 /* unique name validation */
338 i = 0;
339 while (i < (int) _DBUS_N_ELEMENTS (valid_unique_names))
340 {
341 _dbus_string_init_const (&str, valid_unique_names[i]);
342
343 if (!_dbus_validate_bus_name (&str, 0,
344 _dbus_string_get_length (&str)))
345 {
346 _dbus_warn ("Bus name \"%s\" should have been valid\n", valid_unique_names[i]);
347 _dbus_assert_not_reached ("invalid unique name");
348 }
349
350 ++i;
351 }
352
353 i = 0;
354 while (i < (int) _DBUS_N_ELEMENTS (invalid_unique_names))
355 {
356 _dbus_string_init_const (&str, invalid_unique_names[i]);
357
358 if (_dbus_validate_bus_name (&str, 0,
359 _dbus_string_get_length (&str)))
360 {
361 _dbus_warn ("Bus name \"%s\" should have been invalid\n", invalid_unique_names[i]);
362 _dbus_assert_not_reached ("valid unique name");
363 }
364
365 ++i;
366 }
367
368
369 /* Error name validation (currently identical to interfaces)
370 */
371 i = 0;
372 while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
373 {
374 _dbus_string_init_const (&str, valid_interfaces[i]);
375
376 if (!_dbus_validate_error_name (&str, 0,
377 _dbus_string_get_length (&str)))
378 {
379 _dbus_warn ("Error name \"%s\" should have been valid\n", valid_interfaces[i]);
380 _dbus_assert_not_reached ("invalid error name");
381 }
382
383 ++i;
384 }
385
386 i = 0;
387 while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
388 {
389 if (invalid_interfaces[i][0] != ':')
390 {
391 _dbus_string_init_const (&str, invalid_interfaces[i]);
392
393 if (_dbus_validate_error_name (&str, 0,
394 _dbus_string_get_length (&str)))
395 {
396 _dbus_warn ("Error name \"%s\" should have been invalid\n", invalid_interfaces[i]);
397 _dbus_assert_not_reached ("valid error name");
398 }
399 }
400
401 ++i;
402 }
403
404 /* Member validation */
405 i = 0;
406 while (i < (int) _DBUS_N_ELEMENTS (valid_members))
407 {
408 _dbus_string_init_const (&str, valid_members[i]);
409
410 if (!_dbus_validate_member (&str, 0,
411 _dbus_string_get_length (&str)))
412 {
413 _dbus_warn ("Member \"%s\" should have been valid\n", valid_members[i]);
414 _dbus_assert_not_reached ("invalid member");
415 }
416
417 ++i;
418 }
419
420 i = 0;
421 while (i < (int) _DBUS_N_ELEMENTS (invalid_members))
422 {
423 _dbus_string_init_const (&str, invalid_members[i]);
424
425 if (_dbus_validate_member (&str, 0,
426 _dbus_string_get_length (&str)))
427 {
428 _dbus_warn ("Member \"%s\" should have been invalid\n", invalid_members[i]);
429 _dbus_assert_not_reached ("valid member");
430 }
431
432 ++i;
433 }
434
435 /* Signature validation */
436 i = 0;
437 while (i < (int) _DBUS_N_ELEMENTS (valid_signatures))
438 {
439 _dbus_string_init_const (&str, valid_signatures[i]);
440
441 if (!_dbus_validate_signature (&str, 0,
442 _dbus_string_get_length (&str)))
443 {
444 _dbus_warn ("Signature \"%s\" should have been valid\n", valid_signatures[i]);
445 _dbus_assert_not_reached ("invalid signature");
446 }
447
448 ++i;
449 }
450
451 i = 0;
452 while (i < (int) _DBUS_N_ELEMENTS (invalid_signatures))
453 {
454 _dbus_string_init_const (&str, invalid_signatures[i]);
455
456 if (_dbus_validate_signature (&str, 0,
457 _dbus_string_get_length (&str)))
458 {
459 _dbus_warn ("Signature \"%s\" should have been invalid\n", invalid_signatures[i]);
460 _dbus_assert_not_reached ("valid signature");
461 }
462
463 ++i;
464 }
465
466 /* Validate claimed length longer than real length */
467 _dbus_string_init_const (&str, "abc.efg");
468 if (_dbus_validate_bus_name (&str, 0, 8))
469 _dbus_assert_not_reached ("validated too-long string");
470 if (_dbus_validate_interface (&str, 0, 8))
471 _dbus_assert_not_reached ("validated too-long string");
472 if (_dbus_validate_error_name (&str, 0, 8))
473 _dbus_assert_not_reached ("validated too-long string");
474
475 _dbus_string_init_const (&str, "abc");
476 if (_dbus_validate_member (&str, 0, 4))
477 _dbus_assert_not_reached ("validated too-long string");
478
479 _dbus_string_init_const (&str, "sss");
480 if (_dbus_validate_signature (&str, 0, 4))
481 _dbus_assert_not_reached ("validated too-long signature");
482
483 /* Validate string exceeding max name length */
484 if (!_dbus_string_init (&str))
485 _dbus_assert_not_reached ("no memory");
486
487 while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
488 if (!_dbus_string_append (&str, "abc.def"))
489 _dbus_assert_not_reached ("no memory");
490
491 if (_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
492 _dbus_assert_not_reached ("validated overmax string");
493 if (_dbus_validate_interface (&str, 0, _dbus_string_get_length (&str)))
494 _dbus_assert_not_reached ("validated overmax string");
495 if (_dbus_validate_error_name (&str, 0, _dbus_string_get_length (&str)))
496 _dbus_assert_not_reached ("validated overmax string");
497
498 /* overlong member */
499 _dbus_string_set_length (&str, 0);
500 while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
501 if (!_dbus_string_append (&str, "abc"))
502 _dbus_assert_not_reached ("no memory");
503
504 if (_dbus_validate_member (&str, 0, _dbus_string_get_length (&str)))
505 _dbus_assert_not_reached ("validated overmax string");
506
507 /* overlong unique name */
508 _dbus_string_set_length (&str, 0);
509 _dbus_string_append (&str, ":");
510 while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
511 if (!_dbus_string_append (&str, "abc"))
512 _dbus_assert_not_reached ("no memory");
513
514 if (_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
515 _dbus_assert_not_reached ("validated overmax string");
516
517 _dbus_string_free (&str);
518
519 /* Body validation; test basic validation of valid bodies for both endian */
520
521 {
522 int sequence;
523 DBusString signature;
524 DBusString body;
525
526 if (!_dbus_string_init (&signature) || !_dbus_string_init (&body))
527 _dbus_assert_not_reached ("oom");
528
529 sequence = 0;
530 while (dbus_internal_do_not_use_generate_bodies (sequence,
531 DBUS_LITTLE_ENDIAN,
532 &signature, &body))
533 {
534 DBusValidity validity;
535
536 validity = _dbus_validate_body_with_reason (&signature, 0,
537 DBUS_LITTLE_ENDIAN,
538 NULL, &body, 0,
539 _dbus_string_get_length (&body));
540 if (validity != DBUS_VALID)
541 {
542 _dbus_warn ("invalid code %d expected valid on sequence %d little endian\n",
543 validity, sequence);
544 _dbus_verbose_bytes_of_string (&signature, 0, _dbus_string_get_length (&signature));
545 _dbus_verbose_bytes_of_string (&body, 0, _dbus_string_get_length (&body));
546 _dbus_assert_not_reached ("test failed");
547 }
548
549 _dbus_string_set_length (&signature, 0);
550 _dbus_string_set_length (&body, 0);
551 ++sequence;
552 }
553
554 sequence = 0;
555 while (dbus_internal_do_not_use_generate_bodies (sequence,
556 DBUS_BIG_ENDIAN,
557 &signature, &body))
558 {
559 DBusValidity validity;
560
561 validity = _dbus_validate_body_with_reason (&signature, 0,
562 DBUS_BIG_ENDIAN,
563 NULL, &body, 0,
564 _dbus_string_get_length (&body));
565 if (validity != DBUS_VALID)
566 {
567 _dbus_warn ("invalid code %d expected valid on sequence %d big endian\n",
568 validity, sequence);
569 _dbus_verbose_bytes_of_string (&signature, 0, _dbus_string_get_length (&signature));
570 _dbus_verbose_bytes_of_string (&body, 0, _dbus_string_get_length (&body));
571 _dbus_assert_not_reached ("test failed");
572 }
573
574 _dbus_string_set_length (&signature, 0);
575 _dbus_string_set_length (&body, 0);
576 ++sequence;
577 }
578
579 _dbus_string_free (&signature);
580 _dbus_string_free (&body);
581 }
582
583 return TRUE;
584 }
585
586 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */
587
588 #endif /* DBUS_BUILD_TESTS */
589