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