D-Bus  1.13.7
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 #include <dbus/dbus-test-tap.h>
33 
34 #include "dbus-test.h"
35 #include <stdio.h>
36 
37 typedef struct
38 {
39  const char *data;
40  DBusValidity expected;
41 } ValidityTest;
42 
43 static void
44 run_validity_tests (const ValidityTest *tests,
45  int n_tests,
46  DBusValidity (* func) (const DBusString*,int,int))
47 {
48  int i;
49 
50  for (i = 0; i < n_tests; i++)
51  {
52  DBusString str;
53  DBusValidity v;
54 
55  _dbus_string_init_const (&str, tests[i].data);
56 
57  v = (*func) (&str, 0, _dbus_string_get_length (&str));
58 
59  if (v != tests[i].expected)
60  _dbus_test_fatal ("Improper validation result %d for '%s'", v, tests[i].data);
61  }
62 }
63 
64 static const ValidityTest signature_tests[] = {
65  { "", DBUS_VALID },
66  { "sss", DBUS_VALID },
67  { "i", DBUS_VALID },
68  { "b", 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_MISSING_ARRAY_ELEMENT_TYPE },
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  { " ", DBUS_INVALID_UNKNOWN_TYPECODE },
98  { "not a valid signature", DBUS_INVALID_UNKNOWN_TYPECODE },
99  { "123", DBUS_INVALID_UNKNOWN_TYPECODE },
100  { ".", DBUS_INVALID_UNKNOWN_TYPECODE },
101  /* https://bugs.freedesktop.org/show_bug.cgi?id=17803 */
102  { "a{(ii)i}", DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE },
103  { "a{i}", DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD },
104  { "{is}", DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY },
105  { "a{isi}", DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS },
106 };
107 
109 _dbus_marshal_validate_test (void)
110 {
111  DBusString str;
112  int i;
113 
114  const char *valid_paths[] = {
115  "/",
116  "/foo/bar",
117  "/foo",
118  "/foo/bar/baz"
119  };
120  const char *invalid_paths[] = {
121  "bar",
122  "bar/baz",
123  "/foo/bar/",
124  "/foo/",
125  "foo/",
126  "boo//blah",
127  "//",
128  "///",
129  "foo///blah/",
130  "Hello World",
131  "",
132  " ",
133  "foo bar"
134  };
135 
136  const char *valid_interfaces[] = {
137  "org.freedesktop.Foo",
138  "Bar.Baz",
139  "Blah.Blah.Blah.Blah.Blah",
140  "a.b",
141  "a.b.c.d.e.f.g",
142  "a0.b1.c2.d3.e4.f5.g6",
143  "abc123.foo27"
144  };
145  const char *invalid_interfaces[] = {
146  ".",
147  "",
148  "..",
149  ".Foo.Bar",
150  "..Foo.Bar",
151  "Foo.Bar.",
152  "Foo.Bar..",
153  "Foo",
154  "9foo.bar.baz",
155  "foo.bar..baz",
156  "foo.bar...baz",
157  "foo.bar.b..blah",
158  ":",
159  ":0-1",
160  "10",
161  ":11.34324",
162  "0.0.0",
163  "0..0",
164  "foo.Bar.%",
165  "foo.Bar!!",
166  "!Foo.bar.bz",
167  "foo.$.blah",
168  "",
169  " ",
170  "foo bar"
171  };
172 
173  const char *valid_unique_names[] = {
174  ":0",
175  ":a",
176  ":",
177  ":.a",
178  ":.1",
179  ":0.1",
180  ":000.2222",
181  ":.blah",
182  ":abce.freedesktop.blah"
183  };
184  const char *invalid_unique_names[] = {
185  //":-",
186  ":!",
187  //":0-10",
188  ":blah.",
189  ":blah.",
190  ":blah..org",
191  ":blah.org..",
192  ":..blah.org",
193  "",
194  " ",
195  "foo bar"
196  };
197 
198  const char *valid_members[] = {
199  "Hello",
200  "Bar",
201  "foobar",
202  "_foobar",
203  "foo89"
204  };
205 
206  const char *invalid_members[] = {
207  "9Hello",
208  "10",
209  "1",
210  "foo-bar",
211  "blah.org",
212  ".blah",
213  "blah.",
214  "Hello.",
215  "!foo",
216  "",
217  " ",
218  "foo bar"
219  };
220 
221  /* Signature with reason */
222 
223  run_validity_tests (signature_tests, _DBUS_N_ELEMENTS (signature_tests),
225 
226  /* Path validation */
227  i = 0;
228  while (i < (int) _DBUS_N_ELEMENTS (valid_paths))
229  {
230  _dbus_string_init_const (&str, valid_paths[i]);
231 
232  if (!_dbus_validate_path (&str, 0,
233  _dbus_string_get_length (&str)))
234  _dbus_test_fatal ("Path \"%s\" should have been valid", valid_paths[i]);
235 
236  ++i;
237  }
238 
239  i = 0;
240  while (i < (int) _DBUS_N_ELEMENTS (invalid_paths))
241  {
242  _dbus_string_init_const (&str, invalid_paths[i]);
243 
244  if (_dbus_validate_path (&str, 0,
245  _dbus_string_get_length (&str)))
246  _dbus_test_fatal ("Path \"%s\" should have been invalid", invalid_paths[i]);
247 
248  ++i;
249  }
250 
251  /* Interface validation */
252  i = 0;
253  while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
254  {
255  _dbus_string_init_const (&str, valid_interfaces[i]);
256 
257  if (!_dbus_validate_interface (&str, 0,
258  _dbus_string_get_length (&str)))
259  _dbus_test_fatal ("Interface \"%s\" should have been valid", valid_interfaces[i]);
260 
261  ++i;
262  }
263 
264  i = 0;
265  while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
266  {
267  _dbus_string_init_const (&str, invalid_interfaces[i]);
268 
269  if (_dbus_validate_interface (&str, 0,
270  _dbus_string_get_length (&str)))
271  _dbus_test_fatal ("Interface \"%s\" should have been invalid", invalid_interfaces[i]);
272 
273  ++i;
274  }
275 
276  /* Bus name validation (check that valid interfaces are valid bus names,
277  * and invalid interfaces are invalid services except if they start with ':')
278  */
279  i = 0;
280  while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
281  {
282  _dbus_string_init_const (&str, valid_interfaces[i]);
283 
284  if (!_dbus_validate_bus_name (&str, 0,
285  _dbus_string_get_length (&str)))
286  _dbus_test_fatal ("Bus name \"%s\" should have been valid", valid_interfaces[i]);
287 
288  ++i;
289  }
290 
291  i = 0;
292  while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
293  {
294  if (invalid_interfaces[i][0] != ':')
295  {
296  _dbus_string_init_const (&str, invalid_interfaces[i]);
297 
298  if (_dbus_validate_bus_name (&str, 0,
299  _dbus_string_get_length (&str)))
300  _dbus_test_fatal ("Bus name \"%s\" should have been invalid", invalid_interfaces[i]);
301  }
302 
303  ++i;
304  }
305 
306  /* unique name validation */
307  i = 0;
308  while (i < (int) _DBUS_N_ELEMENTS (valid_unique_names))
309  {
310  _dbus_string_init_const (&str, valid_unique_names[i]);
311 
312  if (!_dbus_validate_bus_name (&str, 0,
313  _dbus_string_get_length (&str)))
314  _dbus_test_fatal ("Bus name \"%s\" should have been valid", valid_unique_names[i]);
315 
316  ++i;
317  }
318 
319  i = 0;
320  while (i < (int) _DBUS_N_ELEMENTS (invalid_unique_names))
321  {
322  _dbus_string_init_const (&str, invalid_unique_names[i]);
323 
324  if (_dbus_validate_bus_name (&str, 0,
325  _dbus_string_get_length (&str)))
326  _dbus_test_fatal ("Bus name \"%s\" should have been invalid", invalid_unique_names[i]);
327 
328  ++i;
329  }
330 
331 
332  /* Error name validation (currently identical to interfaces)
333  */
334  i = 0;
335  while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
336  {
337  _dbus_string_init_const (&str, valid_interfaces[i]);
338 
339  if (!_dbus_validate_error_name (&str, 0,
340  _dbus_string_get_length (&str)))
341  _dbus_test_fatal ("Error name \"%s\" should have been valid", valid_interfaces[i]);
342 
343  ++i;
344  }
345 
346  i = 0;
347  while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
348  {
349  if (invalid_interfaces[i][0] != ':')
350  {
351  _dbus_string_init_const (&str, invalid_interfaces[i]);
352 
353  if (_dbus_validate_error_name (&str, 0,
354  _dbus_string_get_length (&str)))
355  _dbus_test_fatal ("Error name \"%s\" should have been invalid", invalid_interfaces[i]);
356  }
357 
358  ++i;
359  }
360 
361  /* Member validation */
362  i = 0;
363  while (i < (int) _DBUS_N_ELEMENTS (valid_members))
364  {
365  _dbus_string_init_const (&str, valid_members[i]);
366 
367  if (!_dbus_validate_member (&str, 0,
368  _dbus_string_get_length (&str)))
369  _dbus_test_fatal ("Member \"%s\" should have been valid", valid_members[i]);
370 
371  ++i;
372  }
373 
374  i = 0;
375  while (i < (int) _DBUS_N_ELEMENTS (invalid_members))
376  {
377  _dbus_string_init_const (&str, invalid_members[i]);
378 
379  if (_dbus_validate_member (&str, 0,
380  _dbus_string_get_length (&str)))
381  _dbus_test_fatal ("Member \"%s\" should have been invalid", invalid_members[i]);
382 
383  ++i;
384  }
385 
386  /* Validate claimed length longer than real length */
387  _dbus_string_init_const (&str, "abc.efg");
388  if (_dbus_validate_bus_name (&str, 0, 8))
389  _dbus_test_fatal ("validated too-long string");
390  if (_dbus_validate_interface (&str, 0, 8))
391  _dbus_test_fatal ("validated too-long string");
392  if (_dbus_validate_error_name (&str, 0, 8))
393  _dbus_test_fatal ("validated too-long string");
394 
395  _dbus_string_init_const (&str, "abc");
396  if (_dbus_validate_member (&str, 0, 4))
397  _dbus_test_fatal ("validated too-long string");
398 
399  /* Validate string exceeding max name length */
400  if (!_dbus_string_init (&str))
401  _dbus_test_fatal ("no memory");
402 
403  while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
404  if (!_dbus_string_append (&str, "abc.def"))
405  _dbus_test_fatal ("no memory");
406 
407  if (_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
408  _dbus_test_fatal ("validated overmax string");
409  if (_dbus_validate_interface (&str, 0, _dbus_string_get_length (&str)))
410  _dbus_test_fatal ("validated overmax string");
411  if (_dbus_validate_error_name (&str, 0, _dbus_string_get_length (&str)))
412  _dbus_test_fatal ("validated overmax string");
413 
414  /* overlong member */
415  _dbus_string_set_length (&str, 0);
416  while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
417  if (!_dbus_string_append (&str, "abc"))
418  _dbus_test_fatal ("no memory");
419 
420  if (_dbus_validate_member (&str, 0, _dbus_string_get_length (&str)))
421  _dbus_test_fatal ("validated overmax string");
422 
423  /* overlong unique name */
424  _dbus_string_set_length (&str, 0);
425  _dbus_string_append (&str, ":");
426  while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
427  if (!_dbus_string_append (&str, "abc"))
428  _dbus_test_fatal ("no memory");
429 
430  if (_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
431  _dbus_test_fatal ("validated overmax string");
432 
433  _dbus_string_free (&str);
434 
435  /* Body validation; test basic validation of valid bodies for both endian */
436 
437  {
438  int sequence;
439  DBusString signature;
440  DBusString body;
441 
442  if (!_dbus_string_init (&signature) || !_dbus_string_init (&body))
443  _dbus_test_fatal ("oom");
444 
445  sequence = 0;
446  while (_dbus_test_generate_bodies (sequence, DBUS_LITTLE_ENDIAN,
447  &signature, &body))
448  {
449  DBusValidity validity;
450 
451  validity = _dbus_validate_body_with_reason (&signature, 0,
453  NULL, &body, 0,
454  _dbus_string_get_length (&body));
455  if (validity != DBUS_VALID)
456  {
457  _dbus_warn ("invalid code %d expected valid on sequence %d little endian",
458  validity, sequence);
459  _dbus_verbose_bytes_of_string (&signature, 0, _dbus_string_get_length (&signature));
460  _dbus_verbose_bytes_of_string (&body, 0, _dbus_string_get_length (&body));
461  _dbus_test_fatal ("test failed");
462  }
463 
464  _dbus_string_set_length (&signature, 0);
465  _dbus_string_set_length (&body, 0);
466  ++sequence;
467  }
468 
469  sequence = 0;
470  while (_dbus_test_generate_bodies (sequence, DBUS_BIG_ENDIAN,
471  &signature, &body))
472  {
473  DBusValidity validity;
474 
475  validity = _dbus_validate_body_with_reason (&signature, 0,
477  NULL, &body, 0,
478  _dbus_string_get_length (&body));
479  if (validity != DBUS_VALID)
480  {
481  _dbus_warn ("invalid code %d expected valid on sequence %d big endian",
482  validity, sequence);
483  _dbus_verbose_bytes_of_string (&signature, 0, _dbus_string_get_length (&signature));
484  _dbus_verbose_bytes_of_string (&body, 0, _dbus_string_get_length (&body));
485  _dbus_test_fatal ("test failed");
486  }
487 
488  _dbus_string_set_length (&signature, 0);
489  _dbus_string_set_length (&body, 0);
490  ++sequence;
491  }
492 
493  _dbus_string_free (&signature);
494  _dbus_string_free (&body);
495  }
496 
497  return TRUE;
498 }
499 
500 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */
501 
502 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */
dbus_bool_t _dbus_string_append(DBusString *str, const char *buffer)
Appends a nul-terminated C-style string to a DBusString.
Definition: dbus-string.c:952
DBusValidity _dbus_validate_body_with_reason(const DBusString *expected_signature, int expected_signature_start, int byte_order, int *bytes_remaining, const DBusString *value_str, int value_pos, int len)
Verifies that the range of value_str from value_pos to value_end is a legitimate value of type expect...
#define NULL
A null pointer, defined appropriately for C or C++.
#define DBUS_MAXIMUM_NAME_LENGTH
Max length in bytes of a bus name, interface, or member (not object path, paths are unlimited)...
dbus_bool_t _dbus_validate_interface(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid interface name in the D-Bus protocol.
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
DBusValidity
This is primarily used in unit testing, so we can verify that each invalid message is invalid for the...
dbus_bool_t _dbus_validate_member(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid member name in the D-Bus protocol.
dbus_bool_t _dbus_validate_path(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid object path name in the D-Bus protocol...
dbus_bool_t _dbus_validate_error_name(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid error name in the D-Bus protocol.
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:190
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
#define DBUS_BIG_ENDIAN
Code marking MSB-first byte order in the wire protocol.
Definition: dbus-protocol.h:54
dbus_bool_t _dbus_validate_bus_name(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid bus name in the D-Bus protocol.
#define _DBUS_N_ELEMENTS(array)
Computes the number of elements in a fixed-size array using sizeof().
the data is valid
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as #_DBUS_STRING_I...
Definition: dbus-string.c:264
#define TRUE
Expands to "1".
DBusValidity _dbus_validate_signature_with_reason(const DBusString *type_str, int type_pos, int len)
Verifies that the range of type_str from type_pos to type_end is a valid signature.
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition: dbus-string.c:819
DBUS_PRIVATE_EXPORT void _dbus_verbose_bytes_of_string(const DBusString *str, int start, int len)
Dump the given part of the string to verbose log.
#define DBUS_LITTLE_ENDIAN
Code marking LSB-first byte order in the wire protocol.
Definition: dbus-protocol.h:53