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