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