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