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