1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-marshal-validate.c Validation routines for marshaled data
4 * Copyright (C) 2005 Red Hat, Inc.
6 * Licensed under the Academic Free License version 2.1
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.
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.
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
24 #include "dbus-internals.h"
25 #include "dbus-marshal-validate.h"
26 #include "dbus-marshal-recursive.h"
29 * @addtogroup DBusMarshal
35 * Verifies that the range of type_str from type_pos to type_end is a
36 * valid signature. If this function returns #TRUE, it will be safe
37 * to iterate over the signature with a types-only #DBusTypeReader.
38 * The range passed in should NOT include the terminating
39 * nul/DBUS_TYPE_INVALID.
41 * @param type_str the string
42 * @param type_pos where the typecodes start
43 * @param len length of typecodes
44 * @returns #DBUS_VALID if valid, reason why invalid otherwise
47 _dbus_validate_signature_with_reason (const DBusString *type_str,
51 const unsigned char *p;
52 const unsigned char *end;
57 _dbus_assert (type_str != NULL);
58 _dbus_assert (type_pos < _DBUS_INT_MAX - len);
59 _dbus_assert (len >= 0);
60 _dbus_assert (type_pos >= 0);
62 if (len > DBUS_MAXIMUM_SIGNATURE_LENGTH)
63 return DBUS_INVALID_SIGNATURE_TOO_LONG;
65 p = _dbus_string_get_const_data_len (type_str, type_pos, 0);
66 end = _dbus_string_get_const_data_len (type_str, type_pos + len, 0);
69 last = DBUS_TYPE_INVALID;
76 case DBUS_TYPE_BOOLEAN:
78 case DBUS_TYPE_UINT32:
80 case DBUS_TYPE_UINT64:
81 case DBUS_TYPE_DOUBLE:
82 case DBUS_TYPE_STRING:
83 case DBUS_TYPE_OBJECT_PATH:
84 case DBUS_TYPE_SIGNATURE:
85 case DBUS_TYPE_VARIANT:
90 if (array_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH)
91 return DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION;
94 case DBUS_STRUCT_BEGIN_CHAR:
97 if (struct_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH)
98 return DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION;
101 case DBUS_STRUCT_END_CHAR:
102 if (struct_depth == 0)
103 return DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED;
105 if (last == DBUS_STRUCT_BEGIN_CHAR)
106 return DBUS_INVALID_STRUCT_HAS_NO_FIELDS;
111 case DBUS_TYPE_STRUCT: /* doesn't appear in signatures */
113 return DBUS_INVALID_UNKNOWN_TYPECODE;
116 if (*p != DBUS_TYPE_ARRAY)
124 return DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE;
126 if (struct_depth > 0)
127 return DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED;
133 validate_body_helper (DBusTypeReader *reader,
135 dbus_bool_t walk_reader_to_end,
136 const unsigned char *p,
137 const unsigned char *end,
138 const unsigned char **new_p)
142 while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID)
144 const unsigned char *a;
147 _dbus_verbose (" validating value of type %s type reader %p type_pos %d p %p end %p %d remain\n",
148 _dbus_type_to_string (current_type), reader, reader->type_pos, p, end,
151 /* Guarantee that p has one byte to look at */
153 return DBUS_INVALID_NOT_ENOUGH_DATA;
155 switch (current_type)
161 case DBUS_TYPE_BOOLEAN:
162 case DBUS_TYPE_INT32:
163 case DBUS_TYPE_UINT32:
164 case DBUS_TYPE_INT64:
165 case DBUS_TYPE_UINT64:
166 case DBUS_TYPE_DOUBLE:
167 alignment = _dbus_type_get_alignment (current_type);
168 a = _DBUS_ALIGN_ADDRESS (p, alignment);
170 return DBUS_INVALID_NOT_ENOUGH_DATA;
174 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
178 if (current_type == DBUS_TYPE_BOOLEAN)
180 dbus_uint32_t v = _dbus_unpack_uint32 (byte_order,
182 if (!(v == 0 || v == 1))
183 return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE;
189 case DBUS_TYPE_ARRAY:
190 case DBUS_TYPE_STRING:
191 case DBUS_TYPE_OBJECT_PATH:
193 dbus_uint32_t claimed_len;
195 a = _DBUS_ALIGN_ADDRESS (p, 4);
197 return DBUS_INVALID_NOT_ENOUGH_DATA;
201 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
205 claimed_len = _dbus_unpack_uint32 (byte_order, p);
208 /* p may now be == end */
209 _dbus_assert (p <= end);
211 if (current_type == DBUS_TYPE_ARRAY)
213 int array_elem_type = _dbus_type_reader_get_element_type (reader);
214 alignment = _dbus_type_get_alignment (array_elem_type);
215 p = _DBUS_ALIGN_ADDRESS (p, alignment);
218 if (claimed_len > (unsigned long) (end - p))
219 return DBUS_INVALID_STRING_LENGTH_OUT_OF_BOUNDS;
221 if (current_type == DBUS_TYPE_OBJECT_PATH)
224 _dbus_string_init_const_len (&str, p, claimed_len);
225 if (!_dbus_validate_path (&str, 0,
226 _dbus_string_get_length (&str)))
227 return DBUS_INVALID_BAD_PATH;
231 else if (current_type == DBUS_TYPE_STRING)
234 _dbus_string_init_const_len (&str, p, claimed_len);
235 if (!_dbus_string_validate_utf8 (&str, 0,
236 _dbus_string_get_length (&str)))
237 return DBUS_INVALID_BAD_UTF8_IN_STRING;
241 else if (current_type == DBUS_TYPE_ARRAY && claimed_len > 0)
244 DBusValidity validity;
245 const unsigned char *array_end;
247 /* Remember that the reader is types only, so we can't
248 * use it to iterate over elements. It stays the same
251 _dbus_type_reader_recurse (reader, &sub);
253 array_end = p + claimed_len;
255 while (p < array_end)
257 validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p);
258 if (validity != DBUS_VALID)
263 return DBUS_INVALID_ARRAY_LENGTH_INCORRECT;
266 /* check nul termination */
267 if (current_type != DBUS_TYPE_ARRAY)
270 return DBUS_INVALID_NOT_ENOUGH_DATA;
273 return DBUS_INVALID_STRING_MISSING_NUL;
279 case DBUS_TYPE_SIGNATURE:
281 dbus_uint32_t claimed_len;
287 /* 1 is for nul termination */
288 if (claimed_len + 1 > (unsigned long) (end - p))
289 return DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS;
291 _dbus_string_init_const_len (&str, p, claimed_len);
292 if (!_dbus_validate_signature (&str, 0,
293 _dbus_string_get_length (&str)))
294 return DBUS_INVALID_BAD_SIGNATURE;
298 _dbus_assert (p < end);
299 if (*p != DBUS_TYPE_INVALID)
300 return DBUS_INVALID_SIGNATURE_MISSING_NUL;
304 _dbus_verbose ("p = %p end = %p claimed_len %u\n", p, end, claimed_len);
308 case DBUS_TYPE_VARIANT:
310 /* 1 byte sig len, sig typecodes, align to
311 * contained-type-boundary, values.
314 /* In addition to normal signature validation, we need to be sure
315 * the signature contains only a single (possibly container) type.
317 dbus_uint32_t claimed_len;
320 DBusValidity validity;
321 int contained_alignment;
327 if (claimed_len + 1 > (unsigned long) (end - p))
328 return DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS;
330 _dbus_string_init_const_len (&sig, p, claimed_len);
331 if (!_dbus_validate_signature (&sig, 0,
332 _dbus_string_get_length (&sig)))
333 return DBUS_INVALID_VARIANT_SIGNATURE_BAD;
337 if (*p != DBUS_TYPE_INVALID)
338 return DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL;
341 contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (&sig, 0));
343 a = _DBUS_ALIGN_ADDRESS (p, contained_alignment);
345 return DBUS_INVALID_NOT_ENOUGH_DATA;
349 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
353 _dbus_type_reader_init_types_only (&sub, &sig, 0);
355 if (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_INVALID)
356 return DBUS_INVALID_VARIANT_SIGNATURE_EMPTY;
358 validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p);
359 if (validity != DBUS_VALID)
362 if (_dbus_type_reader_next (&sub))
363 return DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES;
365 _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_INVALID);
369 case DBUS_TYPE_STRUCT:
372 DBusValidity validity;
374 a = _DBUS_ALIGN_ADDRESS (p, 8);
376 return DBUS_INVALID_NOT_ENOUGH_DATA;
380 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
384 _dbus_type_reader_recurse (reader, &sub);
386 validity = validate_body_helper (&sub, byte_order, TRUE, p, end, &p);
387 if (validity != DBUS_VALID)
393 _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature");
397 _dbus_verbose (" validated value of type %s type reader %p type_pos %d p %p end %p %d remain\n",
398 _dbus_type_to_string (current_type), reader, reader->type_pos, p, end,
403 _dbus_verbose ("not enough data!!! p = %p end = %p end-p = %d\n",
404 p, end, (int) (end - p));
405 return DBUS_INVALID_NOT_ENOUGH_DATA;
408 if (walk_reader_to_end)
409 _dbus_type_reader_next (reader);
421 * Verifies that the range of value_str from value_pos to value_end is
422 * a legitimate value of type expected_signature. If this function
423 * returns #TRUE, it will be safe to iterate over the values with
424 * #DBusTypeReader. The signature is assumed to be already valid.
426 * If bytes_remaining is not #NULL, then leftover bytes will be stored
427 * there and #DBUS_VALID returned. If it is #NULL, then
428 * #DBUS_INVALID_TOO_MUCH_DATA will be returned if bytes are left
431 * @param expected_signature the expected types in the value_str
432 * @param expected_signature_start where in expected_signature is the signature
433 * @param byte_order the byte order
434 * @param bytes_remaining place to store leftover bytes
435 * @param value_str the string containing the body
436 * @param value_pos where the values start
437 * @param len length of values after value_pos
438 * @returns #DBUS_VALID if valid, reason why invalid otherwise
441 _dbus_validate_body_with_reason (const DBusString *expected_signature,
442 int expected_signature_start,
444 int *bytes_remaining,
445 const DBusString *value_str,
449 DBusTypeReader reader;
450 const unsigned char *p;
451 const unsigned char *end;
452 DBusValidity validity;
454 _dbus_assert (len >= 0);
455 _dbus_assert (value_pos >= 0);
456 _dbus_assert (value_pos <= _dbus_string_get_length (value_str) - len);
458 _dbus_verbose ("validating body from pos %d len %d sig '%s'\n",
459 value_pos, len, _dbus_string_get_const_data_len (expected_signature,
460 expected_signature_start,
463 _dbus_type_reader_init_types_only (&reader,
464 expected_signature, expected_signature_start);
466 p = _dbus_string_get_const_data_len (value_str, value_pos, len);
469 validity = validate_body_helper (&reader, byte_order, TRUE, p, end, &p);
470 if (validity != DBUS_VALID)
475 *bytes_remaining = end - p;
479 return DBUS_INVALID_TOO_MUCH_DATA;
482 _dbus_assert (p == end);
488 * Determine wether the given charater is valid as the first charater
491 #define VALID_INITIAL_NAME_CHARACTER(c) \
492 ( ((c) >= 'A' && (c) <= 'Z') || \
493 ((c) >= 'a' && (c) <= 'z') || \
497 * Determine wether the given charater is valid as a second or later
498 * character in a name
500 #define VALID_NAME_CHARACTER(c) \
501 ( ((c) >= '0' && (c) <= '9') || \
502 ((c) >= 'A' && (c) <= 'Z') || \
503 ((c) >= 'a' && (c) <= 'z') || \
507 * Checks that the given range of the string is a valid object path
508 * name in the D-BUS protocol. Part of the validation ensures that
509 * the object path contains only ASCII.
511 * @todo this is inconsistent with most of DBusString in that
512 * it allows a start,len range that extends past the string end.
514 * @todo change spec to disallow more things, such as spaces in the
517 * @param str the string
518 * @param start first byte index to check
519 * @param len number of bytes to check
520 * @returns #TRUE if the byte range exists and is a valid name
523 _dbus_validate_path (const DBusString *str,
527 const unsigned char *s;
528 const unsigned char *end;
529 const unsigned char *last_slash;
531 _dbus_assert (start >= 0);
532 _dbus_assert (len >= 0);
533 _dbus_assert (start <= _dbus_string_get_length (str));
535 if (len > _dbus_string_get_length (str) - start)
541 s = _dbus_string_get_const_data (str) + start;
553 if ((s - last_slash) < 2)
554 return FALSE; /* no empty path components allowed */
560 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
567 if ((end - last_slash) < 2 &&
569 return FALSE; /* trailing slash not allowed unless the string is "/" */
575 * Checks that the given range of the string is a valid interface name
576 * in the D-BUS protocol. This includes a length restriction and an
577 * ASCII subset, see the specification.
579 * @todo this is inconsistent with most of DBusString in that
580 * it allows a start,len range that extends past the string end.
582 * @param str the string
583 * @param start first byte index to check
584 * @param len number of bytes to check
585 * @returns #TRUE if the byte range exists and is a valid name
588 _dbus_validate_interface (const DBusString *str,
592 const unsigned char *s;
593 const unsigned char *end;
594 const unsigned char *iface;
595 const unsigned char *last_dot;
597 _dbus_assert (start >= 0);
598 _dbus_assert (len >= 0);
599 _dbus_assert (start <= _dbus_string_get_length (str));
601 if (len > _dbus_string_get_length (str) - start)
604 if (len > DBUS_MAXIMUM_NAME_LENGTH)
611 iface = _dbus_string_get_const_data (str) + start;
615 /* check special cases of first char so it doesn't have to be done
616 * in the loop. Note we know len > 0
618 if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
620 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
629 if (_DBUS_UNLIKELY ((s + 1) == end))
631 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1))))
634 ++s; /* we just validated the next char, so skip two */
636 else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
644 if (_DBUS_UNLIKELY (last_dot == NULL))
651 * Checks that the given range of the string is a valid member name
652 * in the D-BUS protocol. This includes a length restriction, etc.,
653 * see the specification.
655 * @todo this is inconsistent with most of DBusString in that
656 * it allows a start,len range that extends past the string end.
658 * @param str the string
659 * @param start first byte index to check
660 * @param len number of bytes to check
661 * @returns #TRUE if the byte range exists and is a valid name
664 _dbus_validate_member (const DBusString *str,
668 const unsigned char *s;
669 const unsigned char *end;
670 const unsigned char *member;
672 _dbus_assert (start >= 0);
673 _dbus_assert (len >= 0);
674 _dbus_assert (start <= _dbus_string_get_length (str));
676 if (len > _dbus_string_get_length (str) - start)
679 if (len > DBUS_MAXIMUM_NAME_LENGTH)
685 member = _dbus_string_get_const_data (str) + start;
689 /* check special cases of first char so it doesn't have to be done
690 * in the loop. Note we know len > 0
693 if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
700 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
712 * Checks that the given range of the string is a valid error name
713 * in the D-BUS protocol. This includes a length restriction, etc.,
714 * see the specification.
716 * @todo this is inconsistent with most of DBusString in that
717 * it allows a start,len range that extends past the string end.
719 * @param str the string
720 * @param start first byte index to check
721 * @param len number of bytes to check
722 * @returns #TRUE if the byte range exists and is a valid name
725 _dbus_validate_error_name (const DBusString *str,
729 /* Same restrictions as interface name at the moment */
730 return _dbus_validate_interface (str, start, len);
733 /* This assumes the first char exists and is ':' */
735 _dbus_validate_unique_name (const DBusString *str,
739 const unsigned char *s;
740 const unsigned char *end;
741 const unsigned char *name;
743 _dbus_assert (start >= 0);
744 _dbus_assert (len >= 0);
745 _dbus_assert (start <= _dbus_string_get_length (str));
747 if (len > _dbus_string_get_length (str) - start)
750 if (len > DBUS_MAXIMUM_NAME_LENGTH)
753 _dbus_assert (len > 0);
755 name = _dbus_string_get_const_data (str) + start;
757 _dbus_assert (*name == ':');
764 if (_DBUS_UNLIKELY ((s + 1) == end))
766 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*(s + 1))))
768 ++s; /* we just validated the next char, so skip two */
770 else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
782 * Checks that the given range of the string is a valid bus name in
783 * the D-BUS protocol. This includes a length restriction, etc., see
786 * @todo this is inconsistent with most of DBusString in that
787 * it allows a start,len range that extends past the string end.
789 * @param str the string
790 * @param start first byte index to check
791 * @param len number of bytes to check
792 * @returns #TRUE if the byte range exists and is a valid name
795 _dbus_validate_bus_name (const DBusString *str,
799 if (_DBUS_UNLIKELY (len == 0))
801 if (_dbus_string_get_byte (str, start) == ':')
802 return _dbus_validate_unique_name (str, start, len);
804 return _dbus_validate_interface (str, start, len);
808 * Checks that the given range of the string is a valid message type
809 * signature in the D-BUS protocol.
811 * @todo this is inconsistent with most of DBusString in that
812 * it allows a start,len range that extends past the string end.
814 * @param str the string
815 * @param start first byte index to check
816 * @param len number of bytes to check
817 * @returns #TRUE if the byte range exists and is a valid signature
820 _dbus_validate_signature (const DBusString *str,
824 _dbus_assert (start >= 0);
825 _dbus_assert (start <= _dbus_string_get_length (str));
826 _dbus_assert (len >= 0);
828 if (len > _dbus_string_get_length (str) - start)
831 return _dbus_validate_signature_with_reason (str, start, len) == DBUS_VALID;
834 /** define _dbus_check_is_valid_path() */
835 DEFINE_DBUS_NAME_CHECK(path);
836 /** define _dbus_check_is_valid_interface() */
837 DEFINE_DBUS_NAME_CHECK(interface);
838 /** define _dbus_check_is_valid_member() */
839 DEFINE_DBUS_NAME_CHECK(member);
840 /** define _dbus_check_is_valid_error_name() */
841 DEFINE_DBUS_NAME_CHECK(error_name);
842 /** define _dbus_check_is_valid_bus_name() */
843 DEFINE_DBUS_NAME_CHECK(bus_name);
844 /** define _dbus_check_is_valid_signature() */
845 DEFINE_DBUS_NAME_CHECK(signature);
849 /* tests in dbus-marshal-validate-util.c */