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