D-Bus  1.14.10
dbus-marshal-validate.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-marshal-validate.c Validation routines for marshaled data
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 #include "dbus-internals.h"
26 #include "dbus-marshal-validate.h"
27 #include "dbus-marshal-recursive.h"
28 #include "dbus-marshal-basic.h"
29 #include "dbus-signature.h"
30 #include "dbus-string.h"
31 
52  int type_pos,
53  int len)
54 {
55  const unsigned char *p;
56  const unsigned char *end;
57  int last;
58  int struct_depth;
59  int array_depth;
60  int dict_entry_depth;
61  DBusValidity result;
62 
63  int element_count;
64  DBusList *element_count_stack;
65  char opened_brackets[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH * 2 + 1] = { '\0' };
66  char last_bracket;
67 
68  result = DBUS_VALID;
69  element_count_stack = NULL;
70 
71  if (!_dbus_list_append (&element_count_stack, _DBUS_INT_TO_POINTER (0)))
72  {
74  goto out;
75  }
76 
77  _dbus_assert (type_str != NULL);
78  _dbus_assert (type_pos < _DBUS_INT32_MAX - len);
79  _dbus_assert (len >= 0);
80  _dbus_assert (type_pos >= 0);
81 
83  {
84  result = DBUS_INVALID_SIGNATURE_TOO_LONG;
85  goto out;
86  }
87 
88  p = _dbus_string_get_const_udata_len (type_str, type_pos, 0);
89 
90  end = _dbus_string_get_const_udata_len (type_str, type_pos + len, 0);
91  struct_depth = 0;
92  array_depth = 0;
93  dict_entry_depth = 0;
94  last = DBUS_TYPE_INVALID;
95 
96  while (p != end)
97  {
98  _dbus_assert (struct_depth + dict_entry_depth >= 0);
99  _dbus_assert (struct_depth + dict_entry_depth < _DBUS_N_ELEMENTS (opened_brackets));
100  _dbus_assert (opened_brackets[struct_depth + dict_entry_depth] == '\0');
101 
102  switch (*p)
103  {
104  case DBUS_TYPE_BYTE:
105  case DBUS_TYPE_BOOLEAN:
106  case DBUS_TYPE_INT16:
107  case DBUS_TYPE_UINT16:
108  case DBUS_TYPE_INT32:
109  case DBUS_TYPE_UINT32:
110  case DBUS_TYPE_UNIX_FD:
111  case DBUS_TYPE_INT64:
112  case DBUS_TYPE_UINT64:
113  case DBUS_TYPE_DOUBLE:
114  case DBUS_TYPE_STRING:
116  case DBUS_TYPE_SIGNATURE:
117  case DBUS_TYPE_VARIANT:
118  break;
119 
120  case DBUS_TYPE_ARRAY:
121  array_depth += 1;
122  if (array_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH)
123  {
124  result = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION;
125  goto out;
126  }
127  break;
128 
130  struct_depth += 1;
131 
132  if (struct_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH)
133  {
134  result = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION;
135  goto out;
136  }
137 
138  if (!_dbus_list_append (&element_count_stack,
140  {
142  goto out;
143  }
144 
145  _dbus_assert (struct_depth + dict_entry_depth >= 1);
146  _dbus_assert (struct_depth + dict_entry_depth < _DBUS_N_ELEMENTS (opened_brackets));
147  _dbus_assert (opened_brackets[struct_depth + dict_entry_depth - 1] == '\0');
148  opened_brackets[struct_depth + dict_entry_depth - 1] = DBUS_STRUCT_BEGIN_CHAR;
149  break;
150 
152  if (struct_depth == 0)
153  {
154  result = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED;
155  goto out;
156  }
157 
158  if (last == DBUS_STRUCT_BEGIN_CHAR)
159  {
160  result = DBUS_INVALID_STRUCT_HAS_NO_FIELDS;
161  goto out;
162  }
163 
164  _dbus_assert (struct_depth + dict_entry_depth >= 1);
165  _dbus_assert (struct_depth + dict_entry_depth < _DBUS_N_ELEMENTS (opened_brackets));
166  last_bracket = opened_brackets[struct_depth + dict_entry_depth - 1];
167 
168  if (last_bracket != DBUS_STRUCT_BEGIN_CHAR)
169  {
170  result = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED;
171  goto out;
172  }
173 
174  _dbus_list_pop_last (&element_count_stack);
175 
176  struct_depth -= 1;
177  opened_brackets[struct_depth + dict_entry_depth] = '\0';
178  break;
179 
181  if (last != DBUS_TYPE_ARRAY)
182  {
183  result = DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY;
184  goto out;
185  }
186 
187  dict_entry_depth += 1;
188 
189  if (dict_entry_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH)
190  {
191  result = DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION;
192  goto out;
193  }
194 
195  if (!_dbus_list_append (&element_count_stack,
197  {
199  goto out;
200  }
201 
202  _dbus_assert (struct_depth + dict_entry_depth >= 1);
203  _dbus_assert (struct_depth + dict_entry_depth < _DBUS_N_ELEMENTS (opened_brackets));
204  _dbus_assert (opened_brackets[struct_depth + dict_entry_depth - 1] == '\0');
205  opened_brackets[struct_depth + dict_entry_depth - 1] = DBUS_DICT_ENTRY_BEGIN_CHAR;
206  break;
207 
209  if (dict_entry_depth == 0)
210  {
211  result = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED;
212  goto out;
213  }
214 
215  _dbus_assert (struct_depth + dict_entry_depth >= 1);
216  _dbus_assert (struct_depth + dict_entry_depth < _DBUS_N_ELEMENTS (opened_brackets));
217  last_bracket = opened_brackets[struct_depth + dict_entry_depth - 1];
218 
219  if (last_bracket != DBUS_DICT_ENTRY_BEGIN_CHAR)
220  {
221  result = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED;
222  goto out;
223  }
224 
225  dict_entry_depth -= 1;
226  opened_brackets[struct_depth + dict_entry_depth] = '\0';
227 
228  element_count =
229  _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack));
230 
231  if (element_count != 2)
232  {
233  if (element_count == 0)
234  result = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS;
235  else if (element_count == 1)
236  result = DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD;
237  else
238  result = DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS;
239 
240  goto out;
241  }
242  break;
243 
244  case DBUS_TYPE_STRUCT: /* doesn't appear in signatures */
245  case DBUS_TYPE_DICT_ENTRY: /* ditto */
246  default:
247  result = DBUS_INVALID_UNKNOWN_TYPECODE;
248  goto out;
249  }
250 
251  if (*p != DBUS_TYPE_ARRAY &&
253  *p != DBUS_STRUCT_BEGIN_CHAR)
254  {
255  element_count =
256  _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack));
257 
258  ++element_count;
259 
260  if (!_dbus_list_append (&element_count_stack,
261  _DBUS_INT_TO_POINTER (element_count)))
262  {
264  goto out;
265  }
266  }
267 
268  if (array_depth > 0)
269  {
270  if (*p == DBUS_TYPE_ARRAY && p != end)
271  {
272  const unsigned char *p1;
273  p1 = p + 1;
274  if (*p1 == DBUS_STRUCT_END_CHAR ||
276  {
277  result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE;
278  goto out;
279  }
280  }
281  else
282  {
283  array_depth = 0;
284  }
285  }
286 
287  if (last == DBUS_DICT_ENTRY_BEGIN_CHAR)
288  {
289  if (!(dbus_type_is_valid (*p) && dbus_type_is_basic (*p)))
290  {
291  result = DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE;
292  goto out;
293  }
294  }
295 
296  last = *p;
297  ++p;
298  }
299 
300 
301  if (array_depth > 0)
302  {
303  result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE;
304  goto out;
305  }
306 
307  if (struct_depth > 0)
308  {
309  result = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED;
310  goto out;
311  }
312 
313  if (dict_entry_depth > 0)
314  {
315  result = DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED;
316  goto out;
317  }
318 
319  _dbus_assert (last != DBUS_TYPE_ARRAY);
322 
323  result = DBUS_VALID;
324 
325 out:
326  _dbus_list_clear (&element_count_stack);
327  return result;
328 }
329 
330 /* note: this function is also used to validate the header's values,
331  * since the header is a valid body with a particular signature.
332  */
333 static DBusValidity
334 validate_body_helper (DBusTypeReader *reader,
335  int byte_order,
336  dbus_bool_t walk_reader_to_end,
337  int total_depth,
338  const unsigned char *p,
339  const unsigned char *end,
340  const unsigned char **new_p)
341 {
342  int current_type;
343 
344  /* The spec allows arrays and structs to each nest 32, for total
345  * nesting of 2*32. We want to impose the same limit on "dynamic"
346  * value nesting (not visible in the signature) which is introduced
347  * by DBUS_TYPE_VARIANT.
348  */
349  if (total_depth > (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH * 2))
350  {
351  return DBUS_INVALID_NESTED_TOO_DEEPLY;
352  }
353 
354  while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID)
355  {
356  const unsigned char *a;
357  int alignment;
358 
359 #if 0
360  _dbus_verbose (" validating value of type %s type reader %p type_pos %d p %p end %p %d remain\n",
361  _dbus_type_to_string (current_type), reader, reader->type_pos, p, end,
362  (int) (end - p));
363 #endif
364 
365  /* Guarantee that p has one byte to look at */
366  if (p == end)
367  return DBUS_INVALID_NOT_ENOUGH_DATA;
368 
369  switch (current_type)
370  {
371  case DBUS_TYPE_BYTE:
372  ++p;
373  break;
374 
375  case DBUS_TYPE_BOOLEAN:
376  case DBUS_TYPE_INT16:
377  case DBUS_TYPE_UINT16:
378  case DBUS_TYPE_INT32:
379  case DBUS_TYPE_UINT32:
380  case DBUS_TYPE_UNIX_FD:
381  case DBUS_TYPE_INT64:
382  case DBUS_TYPE_UINT64:
383  case DBUS_TYPE_DOUBLE:
384  alignment = _dbus_type_get_alignment (current_type);
385  a = _DBUS_ALIGN_ADDRESS (p, alignment);
386  if (a >= end)
387  return DBUS_INVALID_NOT_ENOUGH_DATA;
388  while (p != a)
389  {
390  if (*p != '\0')
391  return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
392  ++p;
393  }
394 
395  if (current_type == DBUS_TYPE_BOOLEAN)
396  {
397  dbus_uint32_t v;
398 
399  if (p + 4 > end)
400  return DBUS_INVALID_NOT_ENOUGH_DATA;
401 
402  v = _dbus_unpack_uint32 (byte_order, p);
403 
404  if (!(v == 0 || v == 1))
405  return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE;
406  }
407 
408  p += alignment;
409  break;
410 
411  case DBUS_TYPE_ARRAY:
412  case DBUS_TYPE_STRING:
414  {
415  dbus_uint32_t claimed_len;
416 
417  a = _DBUS_ALIGN_ADDRESS (p, 4);
418  if (a + 4 > end)
419  return DBUS_INVALID_NOT_ENOUGH_DATA;
420  while (p != a)
421  {
422  if (*p != '\0')
423  return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
424  ++p;
425  }
426 
427  claimed_len = _dbus_unpack_uint32 (byte_order, p);
428  p += 4;
429 
430  /* p may now be == end */
431  _dbus_assert (p <= end);
432 
433  if (current_type == DBUS_TYPE_ARRAY)
434  {
435  int array_elem_type = _dbus_type_reader_get_element_type (reader);
436 
437  if (!dbus_type_is_valid (array_elem_type))
438  {
439  return DBUS_INVALID_UNKNOWN_TYPECODE;
440  }
441 
442  alignment = _dbus_type_get_alignment (array_elem_type);
443 
444  a = _DBUS_ALIGN_ADDRESS (p, alignment);
445 
446  /* a may now be == end */
447  if (a > end)
448  return DBUS_INVALID_NOT_ENOUGH_DATA;
449 
450  while (p != a)
451  {
452  if (*p != '\0')
453  return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
454  ++p;
455  }
456  }
457 
458  if (claimed_len > (unsigned long) (end - p))
459  return DBUS_INVALID_LENGTH_OUT_OF_BOUNDS;
460 
461  if (current_type == DBUS_TYPE_OBJECT_PATH)
462  {
463  DBusString str;
464  _dbus_string_init_const_len (&str, (const char *) p, claimed_len);
465  if (!_dbus_validate_path (&str, 0,
466  _dbus_string_get_length (&str)))
467  return DBUS_INVALID_BAD_PATH;
468 
469  p += claimed_len;
470  }
471  else if (current_type == DBUS_TYPE_STRING)
472  {
473  DBusString str;
474  _dbus_string_init_const_len (&str, (const char *) p, claimed_len);
475  if (!_dbus_string_validate_utf8 (&str, 0,
476  _dbus_string_get_length (&str)))
477  return DBUS_INVALID_BAD_UTF8_IN_STRING;
478 
479  p += claimed_len;
480  }
481  else if (current_type == DBUS_TYPE_ARRAY && claimed_len > 0)
482  {
483  DBusTypeReader sub;
484  DBusValidity validity;
485  const unsigned char *array_end;
486  int array_elem_type;
487 
488  if (claimed_len > DBUS_MAXIMUM_ARRAY_LENGTH)
489  return DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM;
490 
491  /* Remember that the reader is types only, so we can't
492  * use it to iterate over elements. It stays the same
493  * for all elements.
494  */
495  _dbus_type_reader_recurse (reader, &sub);
496 
497  array_end = p + claimed_len;
498 
499  array_elem_type = _dbus_type_reader_get_element_type (reader);
500 
501  /* avoid recursive call to validate_body_helper if this is an array
502  * of fixed-size elements
503  */
504  if (dbus_type_is_fixed (array_elem_type))
505  {
506  /* Note that fixed-size types all have sizes equal to
507  * their alignments, so this is really the item size. */
508  alignment = _dbus_type_get_alignment (array_elem_type);
509  _dbus_assert (alignment == 1 || alignment == 2 ||
510  alignment == 4 || alignment == 8);
511 
512  /* Because the alignment is a power of 2, this is
513  * equivalent to: (claimed_len % alignment) != 0,
514  * but avoids slower integer division */
515  if ((claimed_len & (alignment - 1)) != 0)
516  return DBUS_INVALID_ARRAY_LENGTH_INCORRECT;
517 
518  /* bools need to be handled differently, because they can
519  * have an invalid value
520  */
521  if (array_elem_type == DBUS_TYPE_BOOLEAN)
522  {
523  dbus_uint32_t v;
524 
525  while (p < array_end)
526  {
527  v = _dbus_unpack_uint32 (byte_order, p);
528 
529  if (!(v == 0 || v == 1))
530  return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE;
531 
532  p += alignment;
533  }
534  }
535 
536  else
537  {
538  p = array_end;
539  }
540  }
541 
542  else
543  {
544  while (p < array_end)
545  {
546  validity = validate_body_helper (&sub, byte_order, FALSE,
547  total_depth + 1,
548  p, end, &p);
549  if (validity != DBUS_VALID)
550  return validity;
551  }
552  }
553 
554  if (p != array_end)
555  return DBUS_INVALID_ARRAY_LENGTH_INCORRECT;
556  }
557 
558  /* check nul termination */
559  if (current_type != DBUS_TYPE_ARRAY)
560  {
561  if (p == end)
562  return DBUS_INVALID_NOT_ENOUGH_DATA;
563 
564  if (*p != '\0')
565  return DBUS_INVALID_STRING_MISSING_NUL;
566  ++p;
567  }
568  }
569  break;
570 
571  case DBUS_TYPE_SIGNATURE:
572  {
573  dbus_uint32_t claimed_len;
574  DBusString str;
575  DBusValidity validity;
576 
577  claimed_len = *p;
578  ++p;
579 
580  /* 1 is for nul termination */
581  if (claimed_len + 1 > (unsigned long) (end - p))
582  return DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS;
583 
584  _dbus_string_init_const_len (&str, (const char *) p, claimed_len);
585  validity =
587  _dbus_string_get_length (&str));
588 
589  if (validity != DBUS_VALID)
590  return validity;
591 
592  p += claimed_len;
593 
594  _dbus_assert (p < end);
595  if (*p != DBUS_TYPE_INVALID)
596  return DBUS_INVALID_SIGNATURE_MISSING_NUL;
597 
598  ++p;
599 
600  _dbus_verbose ("p = %p end = %p claimed_len %u\n", p, end, claimed_len);
601  }
602  break;
603 
604  case DBUS_TYPE_VARIANT:
605  {
606  /* 1 byte sig len, sig typecodes, align to
607  * contained-type-boundary, values.
608  */
609 
610  /* In addition to normal signature validation, we need to be sure
611  * the signature contains only a single (possibly container) type.
612  */
613  dbus_uint32_t claimed_len;
614  DBusString sig;
615  DBusTypeReader sub;
616  DBusValidity validity;
617  int contained_alignment;
618  int contained_type;
619  DBusValidity reason;
620 
621  claimed_len = *p;
622  ++p;
623 
624  /* + 1 for nul */
625  if (claimed_len + 1 > (unsigned long) (end - p))
626  return DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS;
627 
628  _dbus_string_init_const_len (&sig, (const char *) p, claimed_len);
629  reason = _dbus_validate_signature_with_reason (&sig, 0,
630  _dbus_string_get_length (&sig));
631  if (!(reason == DBUS_VALID))
632  {
633  if (reason == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
634  return reason;
635  else
636  return DBUS_INVALID_VARIANT_SIGNATURE_BAD;
637  }
638 
639  p += claimed_len;
640 
641  if (*p != DBUS_TYPE_INVALID)
642  return DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL;
643  ++p;
644 
645  contained_type = _dbus_first_type_in_signature (&sig, 0);
646  if (contained_type == DBUS_TYPE_INVALID)
647  return DBUS_INVALID_VARIANT_SIGNATURE_EMPTY;
648 
649  contained_alignment = _dbus_type_get_alignment (contained_type);
650 
651  a = _DBUS_ALIGN_ADDRESS (p, contained_alignment);
652  if (a > end)
653  return DBUS_INVALID_NOT_ENOUGH_DATA;
654  while (p != a)
655  {
656  if (*p != '\0')
657  return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
658  ++p;
659  }
660 
661  _dbus_type_reader_init_types_only (&sub, &sig, 0);
662 
664 
665  validity = validate_body_helper (&sub, byte_order, FALSE,
666  total_depth + 1,
667  p, end, &p);
668  if (validity != DBUS_VALID)
669  return validity;
670 
671  if (_dbus_type_reader_next (&sub))
672  return DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES;
673 
675  }
676  break;
677 
679  case DBUS_TYPE_STRUCT:
680  {
681  DBusTypeReader sub;
682  DBusValidity validity;
683 
684  a = _DBUS_ALIGN_ADDRESS (p, 8);
685  if (a > end)
686  return DBUS_INVALID_NOT_ENOUGH_DATA;
687  while (p != a)
688  {
689  if (*p != '\0')
690  return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
691  ++p;
692  }
693 
694  _dbus_type_reader_recurse (reader, &sub);
695 
696  validity = validate_body_helper (&sub, byte_order, TRUE,
697  total_depth + 1,
698  p, end, &p);
699  if (validity != DBUS_VALID)
700  return validity;
701  }
702  break;
703 
704  default:
705  _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature");
706  break;
707  }
708 
709 #if 0
710  _dbus_verbose (" validated value of type %s type reader %p type_pos %d p %p end %p %d remain\n",
711  _dbus_type_to_string (current_type), reader, reader->type_pos, p, end,
712  (int) (end - p));
713 #endif
714 
715  if (p > end)
716  {
717  _dbus_verbose ("not enough data!!! p = %p end = %p end-p = %d\n",
718  p, end, (int) (end - p));
719  return DBUS_INVALID_NOT_ENOUGH_DATA;
720  }
721 
722  if (walk_reader_to_end)
723  _dbus_type_reader_next (reader);
724  else
725  break;
726  }
727 
728  if (new_p)
729  *new_p = p;
730 
731  return DBUS_VALID;
732 }
733 
755 _dbus_validate_body_with_reason (const DBusString *expected_signature,
756  int expected_signature_start,
757  int byte_order,
758  int *bytes_remaining,
759  const DBusString *value_str,
760  int value_pos,
761  int len)
762 {
763  DBusTypeReader reader;
764  const unsigned char *p;
765  const unsigned char *end;
766  DBusValidity validity;
767 
768  _dbus_assert (len >= 0);
769  _dbus_assert (value_pos >= 0);
770  _dbus_assert (value_pos <= _dbus_string_get_length (value_str) - len);
771 
772  _dbus_verbose ("validating body from pos %d len %d sig '%s'\n",
773  value_pos, len, _dbus_string_get_const_data_len (expected_signature,
774  expected_signature_start,
775  0));
776 
778  expected_signature, expected_signature_start);
779 
780  p = _dbus_string_get_const_udata_len (value_str, value_pos, len);
781  end = p + len;
782 
783  validity = validate_body_helper (&reader, byte_order, TRUE, 0, p, end, &p);
784  if (validity != DBUS_VALID)
785  return validity;
786 
787  if (bytes_remaining)
788  {
789  *bytes_remaining = end - p;
790  return DBUS_VALID;
791  }
792  else if (p < end)
794  else
795  {
796  _dbus_assert (p == end);
797  return DBUS_VALID;
798  }
799 }
800 
805 #define VALID_INITIAL_NAME_CHARACTER(c) \
806  ( ((c) >= 'A' && (c) <= 'Z') || \
807  ((c) >= 'a' && (c) <= 'z') || \
808  ((c) == '_') )
809 
814 #define VALID_NAME_CHARACTER(c) \
815  ( ((c) >= '0' && (c) <= '9') || \
816  ((c) >= 'A' && (c) <= 'Z') || \
817  ((c) >= 'a' && (c) <= 'z') || \
818  ((c) == '_') )
819 
838  int start,
839  int len)
840 {
841  const unsigned char *s;
842  const unsigned char *end;
843  const unsigned char *last_slash;
844 
845  _dbus_assert (start >= 0);
846  _dbus_assert (len >= 0);
847  _dbus_assert (start <= _dbus_string_get_length (str));
848 
849  if (len > _dbus_string_get_length (str) - start)
850  return FALSE;
851 
852  if (len == 0)
853  return FALSE;
854 
855  s = _dbus_string_get_const_udata (str) + start;
856  end = s + len;
857 
858  if (*s != '/')
859  return FALSE;
860  last_slash = s;
861  ++s;
862 
863  while (s != end)
864  {
865  if (*s == '/')
866  {
867  if ((s - last_slash) < 2)
868  return FALSE; /* no empty path components allowed */
869 
870  last_slash = s;
871  }
872  else
873  {
874  if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
875  return FALSE;
876  }
877 
878  ++s;
879  }
880 
881  if ((end - last_slash) < 2 &&
882  len > 1)
883  return FALSE; /* trailing slash not allowed unless the string is "/" */
884 
885  return TRUE;
886 }
887 
888 const char *
889 _dbus_validity_to_error_message (DBusValidity validity)
890 {
891  switch (validity)
892  {
893  case DBUS_VALIDITY_UNKNOWN_OOM_ERROR: return "Out of memory";
894  case DBUS_INVALID_FOR_UNKNOWN_REASON: return "Unknown reason";
895  case DBUS_VALID_BUT_INCOMPLETE: return "Valid but incomplete";
896  case DBUS_VALIDITY_UNKNOWN: return "Validity unknown";
897  case DBUS_VALID: return "Valid";
898  case DBUS_INVALID_UNKNOWN_TYPECODE: return "Unknown typecode";
899  case DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE: return "Missing array element type";
900  case DBUS_INVALID_SIGNATURE_TOO_LONG: return "Signature is too long";
901  case DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION: return "Exceeded maximum array recursion";
902  case DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION: return "Exceeded maximum struct recursion";
903  case DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED: return "Struct ended but not started";
904  case DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED: return "Struct started but not ended";
905  case DBUS_INVALID_STRUCT_HAS_NO_FIELDS: return "Struct has no fields";
906  case DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL: return "Alignment padding not null";
907  case DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE: return "Boolean is not zero or one";
908  case DBUS_INVALID_NOT_ENOUGH_DATA: return "Not enough data";
909  case DBUS_INVALID_TOO_MUCH_DATA: return "Too much data";
910  case DBUS_INVALID_BAD_BYTE_ORDER: return "Bad byte order";
911  case DBUS_INVALID_BAD_PROTOCOL_VERSION: return "Bad protocol version";
912  case DBUS_INVALID_BAD_MESSAGE_TYPE: return "Bad message type";
913  case DBUS_INVALID_BAD_SERIAL: return "Bad serial";
914  case DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH: return "Insane fields array length";
915  case DBUS_INVALID_INSANE_BODY_LENGTH: return "Insane body length";
916  case DBUS_INVALID_MESSAGE_TOO_LONG: return "Message too long";
917  case DBUS_INVALID_HEADER_FIELD_CODE: return "Header field code";
918  case DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE: return "Header field has wrong type";
919  case DBUS_INVALID_USES_LOCAL_INTERFACE: return "Uses local interface";
920  case DBUS_INVALID_USES_LOCAL_PATH: return "Uses local path";
921  case DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE: return "Header field appears twice";
922  case DBUS_INVALID_BAD_DESTINATION: return "Bad destination";
923  case DBUS_INVALID_BAD_INTERFACE: return "Bad interface";
924  case DBUS_INVALID_BAD_MEMBER: return "Bad member";
925  case DBUS_INVALID_BAD_ERROR_NAME: return "Bad error name";
926  case DBUS_INVALID_BAD_SENDER: return "Bad sender";
927  case DBUS_INVALID_MISSING_PATH: return "Missing path";
928  case DBUS_INVALID_MISSING_INTERFACE: return "Missing interface";
929  case DBUS_INVALID_MISSING_MEMBER: return "Missing member";
930  case DBUS_INVALID_MISSING_ERROR_NAME: return "Missing error name";
931  case DBUS_INVALID_MISSING_REPLY_SERIAL: return "Missing reply serial";
932  case DBUS_INVALID_LENGTH_OUT_OF_BOUNDS: return "Length out of bounds";
933  case DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM: return "Array length exceeds maximum";
934  case DBUS_INVALID_BAD_PATH: return "Bad path";
935  case DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS: return "Signature length out of bounds";
936  case DBUS_INVALID_BAD_UTF8_IN_STRING: return "Bad utf8 in string";
937  case DBUS_INVALID_ARRAY_LENGTH_INCORRECT: return "Array length incorrect";
938  case DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS: return "Variant signature length out of bounds";
939  case DBUS_INVALID_VARIANT_SIGNATURE_BAD: return "Variant signature bad";
940  case DBUS_INVALID_VARIANT_SIGNATURE_EMPTY: return "Variant signature empty";
941  case DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES: return "Variant signature specifies multiple values";
942  case DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL: return "Variant signature missing nul";
943  case DBUS_INVALID_STRING_MISSING_NUL: return "String missing nul";
944  case DBUS_INVALID_SIGNATURE_MISSING_NUL: return "Signature missing nul";
945  case DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION: return "Exceeded maximum dict entry recursion";
946  case DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED: return "Dict entry ended but not started";
947  case DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED: return "Dict entry started but not ended";
948  case DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS: return "Dict entry has no fields";
949  case DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD: return "Dict entry has only one field";
950  case DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS: return "Dict entry has too many fields";
951  case DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY: return "Dict entry not inside array";
952  case DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE: return "Dict key must be basic type";
953  case DBUS_INVALID_MISSING_UNIX_FDS: return "Unix file descriptor missing";
954  case DBUS_INVALID_NESTED_TOO_DEEPLY: return "Variants cannot be used to create a hugely recursive tree of values";
955  case DBUS_VALIDITY_LAST:
956  default:
957  return "Invalid";
958  }
959 }
960 
976  int start,
977  int len)
978 {
979  const unsigned char *s;
980  const unsigned char *end;
981  const unsigned char *iface;
982  const unsigned char *last_dot;
983 
984  _dbus_assert (start >= 0);
985  _dbus_assert (len >= 0);
986  _dbus_assert (start <= _dbus_string_get_length (str));
987 
988  if (len > _dbus_string_get_length (str) - start)
989  return FALSE;
990 
991  if (len > DBUS_MAXIMUM_NAME_LENGTH)
992  return FALSE;
993 
994  if (len == 0)
995  return FALSE;
996 
997  last_dot = NULL;
998  iface = _dbus_string_get_const_udata (str) + start;
999  end = iface + len;
1000  s = iface;
1001 
1002  /* check special cases of first char so it doesn't have to be done
1003  * in the loop. Note we know len > 0
1004  */
1005  if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
1006  return FALSE;
1007  else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
1008  return FALSE;
1009  else
1010  ++s;
1011 
1012  while (s != end)
1013  {
1014  if (*s == '.')
1015  {
1016  if (_DBUS_UNLIKELY ((s + 1) == end))
1017  return FALSE;
1018  else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1))))
1019  return FALSE;
1020  last_dot = s;
1021  ++s; /* we just validated the next char, so skip two */
1022  }
1023  else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
1024  {
1025  return FALSE;
1026  }
1027 
1028  ++s;
1029  }
1030 
1031  if (_DBUS_UNLIKELY (last_dot == NULL))
1032  return FALSE;
1033 
1034  return TRUE;
1035 }
1036 
1052  int start,
1053  int len)
1054 {
1055  const unsigned char *s;
1056  const unsigned char *end;
1057  const unsigned char *member;
1058 
1059  _dbus_assert (start >= 0);
1060  _dbus_assert (len >= 0);
1061  _dbus_assert (start <= _dbus_string_get_length (str));
1062 
1063  if (len > _dbus_string_get_length (str) - start)
1064  return FALSE;
1065 
1066  if (len > DBUS_MAXIMUM_NAME_LENGTH)
1067  return FALSE;
1068 
1069  if (len == 0)
1070  return FALSE;
1071 
1072  member = _dbus_string_get_const_udata (str) + start;
1073  end = member + len;
1074  s = member;
1075 
1076  /* check special cases of first char so it doesn't have to be done
1077  * in the loop. Note we know len > 0
1078  */
1079 
1080  if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
1081  return FALSE;
1082  else
1083  ++s;
1084 
1085  while (s != end)
1086  {
1087  if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
1088  {
1089  return FALSE;
1090  }
1091 
1092  ++s;
1093  }
1094 
1095  return TRUE;
1096 }
1097 
1113  int start,
1114  int len)
1115 {
1116  /* Same restrictions as interface name at the moment */
1117  return _dbus_validate_interface (str, start, len);
1118 }
1119 
1124 #define VALID_INITIAL_BUS_NAME_CHARACTER(c) \
1125  ( ((c) >= 'A' && (c) <= 'Z') || \
1126  ((c) >= 'a' && (c) <= 'z') || \
1127  ((c) == '_') || ((c) == '-'))
1128 
1133 #define VALID_BUS_NAME_CHARACTER(c) \
1134  ( ((c) >= '0' && (c) <= '9') || \
1135  ((c) >= 'A' && (c) <= 'Z') || \
1136  ((c) >= 'a' && (c) <= 'z') || \
1137  ((c) == '_') || ((c) == '-'))
1138 
1139 static dbus_bool_t
1140 _dbus_validate_bus_name_full (const DBusString *str,
1141  int start,
1142  int len,
1143  dbus_bool_t is_namespace)
1144 {
1145  const unsigned char *s;
1146  const unsigned char *end;
1147  const unsigned char *iface;
1148  const unsigned char *last_dot;
1149 
1150  _dbus_assert (start >= 0);
1151  _dbus_assert (len >= 0);
1152  _dbus_assert (start <= _dbus_string_get_length (str));
1153 
1154  if (len > _dbus_string_get_length (str) - start)
1155  return FALSE;
1156 
1157  if (len > DBUS_MAXIMUM_NAME_LENGTH)
1158  return FALSE;
1159 
1160  if (len == 0)
1161  return FALSE;
1162 
1163  last_dot = NULL;
1164  iface = _dbus_string_get_const_udata (str) + start;
1165  end = iface + len;
1166  s = iface;
1167 
1168  /* check special cases of first char so it doesn't have to be done
1169  * in the loop. Note we know len > 0
1170  */
1171  if (*s == ':')
1172  {
1173  /* unique name */
1174  ++s;
1175  while (s != end)
1176  {
1177  if (*s == '.')
1178  {
1179  if (_DBUS_UNLIKELY ((s + 1) == end))
1180  return FALSE;
1181  if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*(s + 1))))
1182  return FALSE;
1183  ++s; /* we just validated the next char, so skip two */
1184  }
1185  else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s)))
1186  {
1187  return FALSE;
1188  }
1189 
1190  ++s;
1191  }
1192 
1193  return TRUE;
1194  }
1195  else if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
1196  return FALSE;
1197  else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*s)))
1198  return FALSE;
1199  else
1200  ++s;
1201 
1202  while (s != end)
1203  {
1204  if (*s == '.')
1205  {
1206  if (_DBUS_UNLIKELY ((s + 1) == end))
1207  return FALSE;
1208  else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*(s + 1))))
1209  return FALSE;
1210  last_dot = s;
1211  ++s; /* we just validated the next char, so skip two */
1212  }
1213  else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s)))
1214  {
1215  return FALSE;
1216  }
1217 
1218  ++s;
1219  }
1220 
1221  if (!is_namespace && _DBUS_UNLIKELY (last_dot == NULL))
1222  return FALSE;
1223 
1224  return TRUE;
1225 }
1226 
1242  int start,
1243  int len)
1244 {
1245  return _dbus_validate_bus_name_full (str, start, len, FALSE);
1246 }
1247 
1263  int start,
1264  int len)
1265 {
1266  return _dbus_validate_bus_name_full (str, start, len, TRUE);
1267 }
1268 
1272 DEFINE_DBUS_NAME_CHECK(interface)
1274 DEFINE_DBUS_NAME_CHECK(member)
1276 DEFINE_DBUS_NAME_CHECK(error_name)
1278 DEFINE_DBUS_NAME_CHECK(bus_name)
1281 
1282 
1284 /* tests in dbus-marshal-validate-util.c */
#define _DBUS_INT_TO_POINTER(integer)
Safely stuffs an integer into a pointer, to be extracted later with _DBUS_POINTER_TO_INT.
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
#define _DBUS_POINTER_TO_INT(pointer)
Safely casts a void* to an integer; should only be used on void* that actually contain integers,...
#define _DBUS_N_ELEMENTS(array)
Computes the number of elements in a fixed-size array using sizeof().
#define _DBUS_INT32_MAX
Maximum value of type "int32".
void _dbus_list_clear(DBusList **list)
Frees all links in the list and sets the list head to NULL.
Definition: dbus-list.c:543
void * _dbus_list_pop_last(DBusList **list)
Removes the last value in the list and returns it.
Definition: dbus-list.c:700
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition: dbus-list.c:271
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
void _dbus_type_reader_recurse(DBusTypeReader *reader, DBusTypeReader *sub)
Initialize a new reader pointing to the first type and corresponding value that's a child of the curr...
DBusValidity
This is primarily used in unit testing, so we can verify that each invalid message is invalid for the...
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.
#define VALID_NAME_CHARACTER(c)
Determine wether the given character is valid as a second or later character in a name.
#define VALID_INITIAL_BUS_NAME_CHARACTER(c)
Determine wether the given character is valid as the first character in a bus name.
#define VALID_BUS_NAME_CHARACTER(c)
Determine wether the given character is valid as a second or later character in a bus name.
int _dbus_type_get_alignment(int typecode)
Gets the alignment requirement for the given type; will be 1, 4, or 8.
#define DEFINE_DBUS_NAME_CHECK(what)
Define a name check to be used in _dbus_return_if_fail() statements.
void _dbus_type_reader_init_types_only(DBusTypeReader *reader, const DBusString *type_str, int type_pos)
Like _dbus_type_reader_init() but the iteration is over the signature, not over values.
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.
const char * _dbus_type_to_string(int typecode)
Returns a string describing the given type.
dbus_uint32_t _dbus_unpack_uint32(int byte_order, const unsigned char *data)
Unpacks a 32 bit unsigned integer from a data pointer.
int _dbus_first_type_in_signature(const DBusString *str, int pos)
Get the first type in the signature.
int _dbus_type_reader_get_element_type(const DBusTypeReader *reader)
Gets the type of an element of the array the reader is currently pointing to.
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_type_reader_next(DBusTypeReader *reader)
Skip to the next value on this "level".
dbus_bool_t _dbus_validate_bus_namespace(const DBusString *str, int start, int len)
Checks that the given range of the string is a prefix of a valid bus name in the D-Bus protocol.
#define VALID_INITIAL_NAME_CHARACTER(c)
Determine wether the given character is valid as the first character in a name.
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_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.
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...
int _dbus_type_reader_get_current_type(const DBusTypeReader *reader)
Gets the type of the value the reader is currently pointing to; or for a types-only reader gets the t...
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.
@ DBUS_VALIDITY_UNKNOWN_OOM_ERROR
can't determine validity due to OOM
@ DBUS_INVALID_TOO_MUCH_DATA
trailing junk makes it invalid
@ DBUS_VALID
the data is valid
#define DBUS_TYPE_SIGNATURE
Type code marking a D-Bus type signature.
#define DBUS_MAXIMUM_SIGNATURE_LENGTH
This one is 255 so it fits in a byte.
#define DBUS_DICT_ENTRY_END_CHAR
Code marking the end of a dict entry type in a type signature.
#define DBUS_TYPE_OBJECT_PATH
Type code marking a D-Bus object path.
#define DBUS_TYPE_BYTE
Type code marking an 8-bit unsigned integer.
Definition: dbus-protocol.h:66
#define DBUS_TYPE_INT16
Type code marking a 16-bit signed integer.
Definition: dbus-protocol.h:74
#define DBUS_TYPE_VARIANT
Type code marking a D-Bus variant type.
#define DBUS_MAXIMUM_ARRAY_LENGTH
Max length of a marshaled array in bytes (64M, 2^26) We use signed int for lengths so must be INT_MAX...
#define DBUS_TYPE_INT32
Type code marking a 32-bit signed integer.
Definition: dbus-protocol.h:82
#define DBUS_TYPE_UNIX_FD
Type code marking a unix file descriptor.
#define DBUS_TYPE_BOOLEAN
Type code marking a boolean.
Definition: dbus-protocol.h:70
#define DBUS_STRUCT_BEGIN_CHAR
Code marking the start of a struct type in a type signature.
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
#define DBUS_MAXIMUM_NAME_LENGTH
Max length in bytes of a bus name, interface, or member (not object path, paths are unlimited).
#define DBUS_TYPE_ARRAY
Type code marking a D-Bus array type.
#define DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
Definition: dbus-protocol.h:60
#define DBUS_MAXIMUM_TYPE_RECURSION_DEPTH
Depth of recursion in the type tree.
#define DBUS_TYPE_INT64
Type code marking a 64-bit signed integer.
Definition: dbus-protocol.h:90
#define DBUS_TYPE_DOUBLE
Type code marking an 8-byte double in IEEE 754 format.
Definition: dbus-protocol.h:98
#define DBUS_TYPE_UINT64
Type code marking a 64-bit unsigned integer.
Definition: dbus-protocol.h:94
#define DBUS_TYPE_DICT_ENTRY
Type code used to represent a dict entry; however, this type code does not appear in type signatures,...
#define DBUS_DICT_ENTRY_BEGIN_CHAR
Code marking the start of a dict entry type in a type signature.
#define DBUS_TYPE_UINT16
Type code marking a 16-bit unsigned integer.
Definition: dbus-protocol.h:78
#define DBUS_TYPE_STRUCT
STRUCT and DICT_ENTRY are sort of special since their codes can't appear in a type string,...
#define DBUS_STRUCT_END_CHAR
Code marking the end of a struct type in a type signature.
#define DBUS_TYPE_UINT32
Type code marking a 32-bit unsigned integer.
Definition: dbus-protocol.h:86
dbus_bool_t dbus_type_is_basic(int typecode)
A "basic type" is a somewhat arbitrary concept, but the intent is to include those types that are ful...
dbus_bool_t dbus_type_is_fixed(int typecode)
Tells you whether values of this type can change length if you set them to some other value.
dbus_bool_t dbus_type_is_valid(int typecode)
Return TRUE if the argument is a valid typecode.
dbus_bool_t _dbus_string_validate_utf8(const DBusString *str, int start, int len)
Checks that the given range of the string is valid UTF-8.
Definition: dbus-string.c:2641
void _dbus_string_init_const_len(DBusString *str, const char *value, int len)
Initializes a constant string with a length.
Definition: dbus-string.c:217
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
A node in a linked list.
Definition: dbus-list.h:35
The type reader is an iterator for reading values from a block of values.
int type_pos
current position in signature