D-Bus  1.12.16
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 
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),
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 
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");
449  _dbus_assert_not_reached ("validated overmax string");
451  _dbus_assert_not_reached ("validated overmax string");
452 
453  /* overlong member */
454  _dbus_string_set_length (&str, 0);
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, ":");
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,
487  &signature, &body))
488  {
489  DBusValidity validity;
490 
491  validity = _dbus_validate_body_with_reason (&signature, 0,
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));
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,
512  &signature, &body))
513  {
514  DBusValidity validity;
515 
516  validity = _dbus_validate_body_with_reason (&signature, 0,
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));
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 */