D-Bus 1.4.0
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-marshal-validate.c Validation routines for marshaled data 00003 * 00004 * Copyright (C) 2005 Red Hat, Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 * 00022 */ 00023 00024 #include <config.h> 00025 #include "dbus-internals.h" 00026 #include "dbus-marshal-validate.h" 00027 #include "dbus-marshal-recursive.h" 00028 #include "dbus-marshal-basic.h" 00029 #include "dbus-signature.h" 00030 #include "dbus-string.h" 00031 00050 DBusValidity 00051 _dbus_validate_signature_with_reason (const DBusString *type_str, 00052 int type_pos, 00053 int len) 00054 { 00055 const unsigned char *p; 00056 const unsigned char *end; 00057 int last; 00058 int struct_depth; 00059 int array_depth; 00060 int dict_entry_depth; 00061 DBusValidity result; 00062 00063 int element_count; 00064 DBusList *element_count_stack; 00065 00066 result = DBUS_VALID; 00067 element_count_stack = NULL; 00068 00069 if (!_dbus_list_append (&element_count_stack, _DBUS_INT_TO_POINTER (0))) 00070 { 00071 result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; 00072 goto out; 00073 } 00074 00075 _dbus_assert (type_str != NULL); 00076 _dbus_assert (type_pos < _DBUS_INT32_MAX - len); 00077 _dbus_assert (len >= 0); 00078 _dbus_assert (type_pos >= 0); 00079 00080 if (len > DBUS_MAXIMUM_SIGNATURE_LENGTH) 00081 { 00082 result = DBUS_INVALID_SIGNATURE_TOO_LONG; 00083 goto out; 00084 } 00085 00086 p = _dbus_string_get_const_data_len (type_str, type_pos, 0); 00087 00088 end = _dbus_string_get_const_data_len (type_str, type_pos + len, 0); 00089 struct_depth = 0; 00090 array_depth = 0; 00091 dict_entry_depth = 0; 00092 last = DBUS_TYPE_INVALID; 00093 00094 while (p != end) 00095 { 00096 switch (*p) 00097 { 00098 case DBUS_TYPE_BYTE: 00099 case DBUS_TYPE_BOOLEAN: 00100 case DBUS_TYPE_INT16: 00101 case DBUS_TYPE_UINT16: 00102 case DBUS_TYPE_INT32: 00103 case DBUS_TYPE_UINT32: 00104 case DBUS_TYPE_UNIX_FD: 00105 case DBUS_TYPE_INT64: 00106 case DBUS_TYPE_UINT64: 00107 case DBUS_TYPE_DOUBLE: 00108 case DBUS_TYPE_STRING: 00109 case DBUS_TYPE_OBJECT_PATH: 00110 case DBUS_TYPE_SIGNATURE: 00111 case DBUS_TYPE_VARIANT: 00112 break; 00113 00114 case DBUS_TYPE_ARRAY: 00115 array_depth += 1; 00116 if (array_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) 00117 { 00118 result = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION; 00119 goto out; 00120 } 00121 break; 00122 00123 case DBUS_STRUCT_BEGIN_CHAR: 00124 struct_depth += 1; 00125 00126 if (struct_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) 00127 { 00128 result = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION; 00129 goto out; 00130 } 00131 00132 if (!_dbus_list_append (&element_count_stack, 00133 _DBUS_INT_TO_POINTER (0))) 00134 { 00135 result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; 00136 goto out; 00137 } 00138 00139 break; 00140 00141 case DBUS_STRUCT_END_CHAR: 00142 if (struct_depth == 0) 00143 { 00144 result = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED; 00145 goto out; 00146 } 00147 00148 if (last == DBUS_STRUCT_BEGIN_CHAR) 00149 { 00150 result = DBUS_INVALID_STRUCT_HAS_NO_FIELDS; 00151 goto out; 00152 } 00153 00154 _dbus_list_pop_last (&element_count_stack); 00155 00156 struct_depth -= 1; 00157 break; 00158 00159 case DBUS_DICT_ENTRY_BEGIN_CHAR: 00160 if (last != DBUS_TYPE_ARRAY) 00161 { 00162 result = DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY; 00163 goto out; 00164 } 00165 00166 dict_entry_depth += 1; 00167 00168 if (dict_entry_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) 00169 { 00170 result = DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION; 00171 goto out; 00172 } 00173 00174 if (!_dbus_list_append (&element_count_stack, 00175 _DBUS_INT_TO_POINTER (0))) 00176 { 00177 result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; 00178 goto out; 00179 } 00180 00181 break; 00182 00183 case DBUS_DICT_ENTRY_END_CHAR: 00184 if (dict_entry_depth == 0) 00185 { 00186 result = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED; 00187 goto out; 00188 } 00189 00190 dict_entry_depth -= 1; 00191 00192 element_count = 00193 _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack)); 00194 00195 if (element_count != 2) 00196 { 00197 if (element_count == 0) 00198 result = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS; 00199 else if (element_count == 1) 00200 result = DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD; 00201 else 00202 result = DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS; 00203 00204 goto out; 00205 } 00206 break; 00207 00208 case DBUS_TYPE_STRUCT: /* doesn't appear in signatures */ 00209 case DBUS_TYPE_DICT_ENTRY: /* ditto */ 00210 default: 00211 result = DBUS_INVALID_UNKNOWN_TYPECODE; 00212 goto out; 00213 } 00214 00215 if (*p != DBUS_TYPE_ARRAY && 00216 *p != DBUS_DICT_ENTRY_BEGIN_CHAR && 00217 *p != DBUS_STRUCT_BEGIN_CHAR) 00218 { 00219 element_count = 00220 _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack)); 00221 00222 ++element_count; 00223 00224 if (!_dbus_list_append (&element_count_stack, 00225 _DBUS_INT_TO_POINTER (element_count))) 00226 { 00227 result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; 00228 goto out; 00229 } 00230 } 00231 00232 if (array_depth > 0) 00233 { 00234 if (*p == DBUS_TYPE_ARRAY && p != end) 00235 { 00236 const char *p1; 00237 p1 = p + 1; 00238 if (*p1 == DBUS_STRUCT_END_CHAR || 00239 *p1 == DBUS_DICT_ENTRY_END_CHAR) 00240 { 00241 result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE; 00242 goto out; 00243 } 00244 } 00245 else 00246 { 00247 array_depth = 0; 00248 } 00249 } 00250 00251 if (last == DBUS_DICT_ENTRY_BEGIN_CHAR) 00252 { 00253 if (!(_dbus_type_is_valid (*p) && dbus_type_is_basic (*p))) 00254 { 00255 result = DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE; 00256 goto out; 00257 } 00258 } 00259 00260 last = *p; 00261 ++p; 00262 } 00263 00264 00265 if (array_depth > 0) 00266 { 00267 result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE; 00268 goto out; 00269 } 00270 00271 if (struct_depth > 0) 00272 { 00273 result = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED; 00274 goto out; 00275 } 00276 00277 if (dict_entry_depth > 0) 00278 { 00279 result = DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED; 00280 goto out; 00281 } 00282 00283 _dbus_assert (last != DBUS_TYPE_ARRAY); 00284 _dbus_assert (last != DBUS_STRUCT_BEGIN_CHAR); 00285 _dbus_assert (last != DBUS_DICT_ENTRY_BEGIN_CHAR); 00286 00287 result = DBUS_VALID; 00288 00289 out: 00290 _dbus_list_clear (&element_count_stack); 00291 return result; 00292 } 00293 00294 static DBusValidity 00295 validate_body_helper (DBusTypeReader *reader, 00296 int byte_order, 00297 dbus_bool_t walk_reader_to_end, 00298 const unsigned char *p, 00299 const unsigned char *end, 00300 const unsigned char **new_p) 00301 { 00302 int current_type; 00303 00304 while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID) 00305 { 00306 const unsigned char *a; 00307 int alignment; 00308 00309 #if 0 00310 _dbus_verbose (" validating value of type %s type reader %p type_pos %d p %p end %p %d remain\n", 00311 _dbus_type_to_string (current_type), reader, reader->type_pos, p, end, 00312 (int) (end - p)); 00313 #endif 00314 00315 /* Guarantee that p has one byte to look at */ 00316 if (p == end) 00317 return DBUS_INVALID_NOT_ENOUGH_DATA; 00318 00319 switch (current_type) 00320 { 00321 case DBUS_TYPE_BYTE: 00322 ++p; 00323 break; 00324 00325 case DBUS_TYPE_BOOLEAN: 00326 case DBUS_TYPE_INT16: 00327 case DBUS_TYPE_UINT16: 00328 case DBUS_TYPE_INT32: 00329 case DBUS_TYPE_UINT32: 00330 case DBUS_TYPE_UNIX_FD: 00331 case DBUS_TYPE_INT64: 00332 case DBUS_TYPE_UINT64: 00333 case DBUS_TYPE_DOUBLE: 00334 alignment = _dbus_type_get_alignment (current_type); 00335 a = _DBUS_ALIGN_ADDRESS (p, alignment); 00336 if (a >= end) 00337 return DBUS_INVALID_NOT_ENOUGH_DATA; 00338 while (p != a) 00339 { 00340 if (*p != '\0') 00341 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 00342 ++p; 00343 } 00344 00345 if (current_type == DBUS_TYPE_BOOLEAN) 00346 { 00347 dbus_uint32_t v = _dbus_unpack_uint32 (byte_order, 00348 p); 00349 if (!(v == 0 || v == 1)) 00350 return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE; 00351 } 00352 00353 p += alignment; 00354 break; 00355 00356 case DBUS_TYPE_ARRAY: 00357 case DBUS_TYPE_STRING: 00358 case DBUS_TYPE_OBJECT_PATH: 00359 { 00360 dbus_uint32_t claimed_len; 00361 00362 a = _DBUS_ALIGN_ADDRESS (p, 4); 00363 if (a + 4 > end) 00364 return DBUS_INVALID_NOT_ENOUGH_DATA; 00365 while (p != a) 00366 { 00367 if (*p != '\0') 00368 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 00369 ++p; 00370 } 00371 00372 claimed_len = _dbus_unpack_uint32 (byte_order, p); 00373 p += 4; 00374 00375 /* p may now be == end */ 00376 _dbus_assert (p <= end); 00377 00378 if (current_type == DBUS_TYPE_ARRAY) 00379 { 00380 int array_elem_type = _dbus_type_reader_get_element_type (reader); 00381 00382 if (!_dbus_type_is_valid (array_elem_type)) 00383 { 00384 return DBUS_INVALID_UNKNOWN_TYPECODE; 00385 } 00386 00387 alignment = _dbus_type_get_alignment (array_elem_type); 00388 00389 a = _DBUS_ALIGN_ADDRESS (p, alignment); 00390 00391 /* a may now be == end */ 00392 if (a > end) 00393 return DBUS_INVALID_NOT_ENOUGH_DATA; 00394 00395 while (p != a) 00396 { 00397 if (*p != '\0') 00398 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 00399 ++p; 00400 } 00401 } 00402 00403 if (claimed_len > (unsigned long) (end - p)) 00404 return DBUS_INVALID_LENGTH_OUT_OF_BOUNDS; 00405 00406 if (current_type == DBUS_TYPE_OBJECT_PATH) 00407 { 00408 DBusString str; 00409 _dbus_string_init_const_len (&str, p, claimed_len); 00410 if (!_dbus_validate_path (&str, 0, 00411 _dbus_string_get_length (&str))) 00412 return DBUS_INVALID_BAD_PATH; 00413 00414 p += claimed_len; 00415 } 00416 else if (current_type == DBUS_TYPE_STRING) 00417 { 00418 DBusString str; 00419 _dbus_string_init_const_len (&str, p, claimed_len); 00420 if (!_dbus_string_validate_utf8 (&str, 0, 00421 _dbus_string_get_length (&str))) 00422 return DBUS_INVALID_BAD_UTF8_IN_STRING; 00423 00424 p += claimed_len; 00425 } 00426 else if (current_type == DBUS_TYPE_ARRAY && claimed_len > 0) 00427 { 00428 DBusTypeReader sub; 00429 DBusValidity validity; 00430 const unsigned char *array_end; 00431 int array_elem_type; 00432 00433 if (claimed_len > DBUS_MAXIMUM_ARRAY_LENGTH) 00434 return DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM; 00435 00436 /* Remember that the reader is types only, so we can't 00437 * use it to iterate over elements. It stays the same 00438 * for all elements. 00439 */ 00440 _dbus_type_reader_recurse (reader, &sub); 00441 00442 array_end = p + claimed_len; 00443 00444 array_elem_type = _dbus_type_reader_get_element_type (reader); 00445 00446 /* avoid recursive call to validate_body_helper if this is an array 00447 * of fixed-size elements 00448 */ 00449 if (dbus_type_is_fixed (array_elem_type)) 00450 { 00451 /* bools need to be handled differently, because they can 00452 * have an invalid value 00453 */ 00454 if (array_elem_type == DBUS_TYPE_BOOLEAN) 00455 { 00456 dbus_uint32_t v; 00457 alignment = _dbus_type_get_alignment (array_elem_type); 00458 00459 while (p < array_end) 00460 { 00461 v = _dbus_unpack_uint32 (byte_order, p); 00462 00463 if (!(v == 0 || v == 1)) 00464 return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE; 00465 00466 p += alignment; 00467 } 00468 } 00469 00470 else 00471 { 00472 p = array_end; 00473 } 00474 } 00475 00476 else 00477 { 00478 while (p < array_end) 00479 { 00480 validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p); 00481 if (validity != DBUS_VALID) 00482 return validity; 00483 } 00484 } 00485 00486 if (p != array_end) 00487 return DBUS_INVALID_ARRAY_LENGTH_INCORRECT; 00488 } 00489 00490 /* check nul termination */ 00491 if (current_type != DBUS_TYPE_ARRAY) 00492 { 00493 if (p == end) 00494 return DBUS_INVALID_NOT_ENOUGH_DATA; 00495 00496 if (*p != '\0') 00497 return DBUS_INVALID_STRING_MISSING_NUL; 00498 ++p; 00499 } 00500 } 00501 break; 00502 00503 case DBUS_TYPE_SIGNATURE: 00504 { 00505 dbus_uint32_t claimed_len; 00506 DBusString str; 00507 DBusValidity validity; 00508 00509 claimed_len = *p; 00510 ++p; 00511 00512 /* 1 is for nul termination */ 00513 if (claimed_len + 1 > (unsigned long) (end - p)) 00514 return DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS; 00515 00516 _dbus_string_init_const_len (&str, p, claimed_len); 00517 validity = 00518 _dbus_validate_signature_with_reason (&str, 0, 00519 _dbus_string_get_length (&str)); 00520 00521 if (validity != DBUS_VALID) 00522 return validity; 00523 00524 p += claimed_len; 00525 00526 _dbus_assert (p < end); 00527 if (*p != DBUS_TYPE_INVALID) 00528 return DBUS_INVALID_SIGNATURE_MISSING_NUL; 00529 00530 ++p; 00531 00532 _dbus_verbose ("p = %p end = %p claimed_len %u\n", p, end, claimed_len); 00533 } 00534 break; 00535 00536 case DBUS_TYPE_VARIANT: 00537 { 00538 /* 1 byte sig len, sig typecodes, align to 00539 * contained-type-boundary, values. 00540 */ 00541 00542 /* In addition to normal signature validation, we need to be sure 00543 * the signature contains only a single (possibly container) type. 00544 */ 00545 dbus_uint32_t claimed_len; 00546 DBusString sig; 00547 DBusTypeReader sub; 00548 DBusValidity validity; 00549 int contained_alignment; 00550 int contained_type; 00551 DBusValidity reason; 00552 00553 claimed_len = *p; 00554 ++p; 00555 00556 /* + 1 for nul */ 00557 if (claimed_len + 1 > (unsigned long) (end - p)) 00558 return DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS; 00559 00560 _dbus_string_init_const_len (&sig, p, claimed_len); 00561 reason = _dbus_validate_signature_with_reason (&sig, 0, 00562 _dbus_string_get_length (&sig)); 00563 if (!(reason == DBUS_VALID)) 00564 { 00565 if (reason == DBUS_VALIDITY_UNKNOWN_OOM_ERROR) 00566 return reason; 00567 else 00568 return DBUS_INVALID_VARIANT_SIGNATURE_BAD; 00569 } 00570 00571 p += claimed_len; 00572 00573 if (*p != DBUS_TYPE_INVALID) 00574 return DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL; 00575 ++p; 00576 00577 contained_type = _dbus_first_type_in_signature (&sig, 0); 00578 if (contained_type == DBUS_TYPE_INVALID) 00579 return DBUS_INVALID_VARIANT_SIGNATURE_EMPTY; 00580 00581 contained_alignment = _dbus_type_get_alignment (contained_type); 00582 00583 a = _DBUS_ALIGN_ADDRESS (p, contained_alignment); 00584 if (a > end) 00585 return DBUS_INVALID_NOT_ENOUGH_DATA; 00586 while (p != a) 00587 { 00588 if (*p != '\0') 00589 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 00590 ++p; 00591 } 00592 00593 _dbus_type_reader_init_types_only (&sub, &sig, 0); 00594 00595 _dbus_assert (_dbus_type_reader_get_current_type (&sub) != DBUS_TYPE_INVALID); 00596 00597 validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p); 00598 if (validity != DBUS_VALID) 00599 return validity; 00600 00601 if (_dbus_type_reader_next (&sub)) 00602 return DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES; 00603 00604 _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_INVALID); 00605 } 00606 break; 00607 00608 case DBUS_TYPE_DICT_ENTRY: 00609 case DBUS_TYPE_STRUCT: 00610 { 00611 DBusTypeReader sub; 00612 DBusValidity validity; 00613 00614 a = _DBUS_ALIGN_ADDRESS (p, 8); 00615 if (a > end) 00616 return DBUS_INVALID_NOT_ENOUGH_DATA; 00617 while (p != a) 00618 { 00619 if (*p != '\0') 00620 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 00621 ++p; 00622 } 00623 00624 _dbus_type_reader_recurse (reader, &sub); 00625 00626 validity = validate_body_helper (&sub, byte_order, TRUE, p, end, &p); 00627 if (validity != DBUS_VALID) 00628 return validity; 00629 } 00630 break; 00631 00632 default: 00633 _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature"); 00634 break; 00635 } 00636 00637 #if 0 00638 _dbus_verbose (" validated value of type %s type reader %p type_pos %d p %p end %p %d remain\n", 00639 _dbus_type_to_string (current_type), reader, reader->type_pos, p, end, 00640 (int) (end - p)); 00641 #endif 00642 00643 if (p > end) 00644 { 00645 _dbus_verbose ("not enough data!!! p = %p end = %p end-p = %d\n", 00646 p, end, (int) (end - p)); 00647 return DBUS_INVALID_NOT_ENOUGH_DATA; 00648 } 00649 00650 if (walk_reader_to_end) 00651 _dbus_type_reader_next (reader); 00652 else 00653 break; 00654 } 00655 00656 if (new_p) 00657 *new_p = p; 00658 00659 return DBUS_VALID; 00660 } 00661 00682 DBusValidity 00683 _dbus_validate_body_with_reason (const DBusString *expected_signature, 00684 int expected_signature_start, 00685 int byte_order, 00686 int *bytes_remaining, 00687 const DBusString *value_str, 00688 int value_pos, 00689 int len) 00690 { 00691 DBusTypeReader reader; 00692 const unsigned char *p; 00693 const unsigned char *end; 00694 DBusValidity validity; 00695 00696 _dbus_assert (len >= 0); 00697 _dbus_assert (value_pos >= 0); 00698 _dbus_assert (value_pos <= _dbus_string_get_length (value_str) - len); 00699 00700 _dbus_verbose ("validating body from pos %d len %d sig '%s'\n", 00701 value_pos, len, _dbus_string_get_const_data_len (expected_signature, 00702 expected_signature_start, 00703 0)); 00704 00705 _dbus_type_reader_init_types_only (&reader, 00706 expected_signature, expected_signature_start); 00707 00708 p = _dbus_string_get_const_data_len (value_str, value_pos, len); 00709 end = p + len; 00710 00711 validity = validate_body_helper (&reader, byte_order, TRUE, p, end, &p); 00712 if (validity != DBUS_VALID) 00713 return validity; 00714 00715 if (bytes_remaining) 00716 { 00717 *bytes_remaining = end - p; 00718 return DBUS_VALID; 00719 } 00720 else if (p < end) 00721 return DBUS_INVALID_TOO_MUCH_DATA; 00722 else 00723 { 00724 _dbus_assert (p == end); 00725 return DBUS_VALID; 00726 } 00727 } 00728 00733 #define VALID_INITIAL_NAME_CHARACTER(c) \ 00734 ( ((c) >= 'A' && (c) <= 'Z') || \ 00735 ((c) >= 'a' && (c) <= 'z') || \ 00736 ((c) == '_') ) 00737 00742 #define VALID_NAME_CHARACTER(c) \ 00743 ( ((c) >= '0' && (c) <= '9') || \ 00744 ((c) >= 'A' && (c) <= 'Z') || \ 00745 ((c) >= 'a' && (c) <= 'z') || \ 00746 ((c) == '_') ) 00747 00764 dbus_bool_t 00765 _dbus_validate_path (const DBusString *str, 00766 int start, 00767 int len) 00768 { 00769 const unsigned char *s; 00770 const unsigned char *end; 00771 const unsigned char *last_slash; 00772 00773 _dbus_assert (start >= 0); 00774 _dbus_assert (len >= 0); 00775 _dbus_assert (start <= _dbus_string_get_length (str)); 00776 00777 if (len > _dbus_string_get_length (str) - start) 00778 return FALSE; 00779 00780 if (len == 0) 00781 return FALSE; 00782 00783 s = _dbus_string_get_const_data (str) + start; 00784 end = s + len; 00785 00786 if (*s != '/') 00787 return FALSE; 00788 last_slash = s; 00789 ++s; 00790 00791 while (s != end) 00792 { 00793 if (*s == '/') 00794 { 00795 if ((s - last_slash) < 2) 00796 return FALSE; /* no empty path components allowed */ 00797 00798 last_slash = s; 00799 } 00800 else 00801 { 00802 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 00803 return FALSE; 00804 } 00805 00806 ++s; 00807 } 00808 00809 if ((end - last_slash) < 2 && 00810 len > 1) 00811 return FALSE; /* trailing slash not allowed unless the string is "/" */ 00812 00813 return TRUE; 00814 } 00815 00816 const char * 00817 _dbus_validity_to_error_message (DBusValidity validity) 00818 { 00819 switch (validity) 00820 { 00821 case DBUS_VALIDITY_UNKNOWN_OOM_ERROR: return "Out of memory"; 00822 case DBUS_INVALID_FOR_UNKNOWN_REASON: return "Unknown reason"; 00823 case DBUS_VALID_BUT_INCOMPLETE: return "Valid but incomplete"; 00824 case DBUS_VALIDITY_UNKNOWN: return "Validity unknown"; 00825 case DBUS_VALID: return "Valid"; 00826 case DBUS_INVALID_UNKNOWN_TYPECODE: return "Unknown typecode"; 00827 case DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE: return "Missing array element type"; 00828 case DBUS_INVALID_SIGNATURE_TOO_LONG: return "Signature is too long"; 00829 case DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION: return "Exceeded maximum array recursion"; 00830 case DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION: return "Exceeded maximum struct recursion"; 00831 case DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED: return "Struct ended but not started"; 00832 case DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED: return "Struct started but not ended"; 00833 case DBUS_INVALID_STRUCT_HAS_NO_FIELDS: return "Struct has no fields"; 00834 case DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL: return "Alignment padding not null"; 00835 case DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE: return "Boolean is not zero or one"; 00836 case DBUS_INVALID_NOT_ENOUGH_DATA: return "Not enough data"; 00837 case DBUS_INVALID_TOO_MUCH_DATA: return "Too much data"; 00838 case DBUS_INVALID_BAD_BYTE_ORDER: return "Bad byte order"; 00839 case DBUS_INVALID_BAD_PROTOCOL_VERSION: return "Bad protocol version"; 00840 case DBUS_INVALID_BAD_MESSAGE_TYPE: return "Bad message type"; 00841 case DBUS_INVALID_BAD_SERIAL: return "Bad serial"; 00842 case DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH: return "Insane fields array length"; 00843 case DBUS_INVALID_INSANE_BODY_LENGTH: return "Insane body length"; 00844 case DBUS_INVALID_MESSAGE_TOO_LONG: return "Message too long"; 00845 case DBUS_INVALID_HEADER_FIELD_CODE: return "Header field code"; 00846 case DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE: return "Header field has wrong type"; 00847 case DBUS_INVALID_USES_LOCAL_INTERFACE: return "Uses local interface"; 00848 case DBUS_INVALID_USES_LOCAL_PATH: return "Uses local path"; 00849 case DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE: return "Header field appears twice"; 00850 case DBUS_INVALID_BAD_DESTINATION: return "Bad destination"; 00851 case DBUS_INVALID_BAD_INTERFACE: return "Bad interface"; 00852 case DBUS_INVALID_BAD_MEMBER: return "Bad member"; 00853 case DBUS_INVALID_BAD_ERROR_NAME: return "Bad error name"; 00854 case DBUS_INVALID_BAD_SENDER: return "Bad sender"; 00855 case DBUS_INVALID_MISSING_PATH: return "Missing path"; 00856 case DBUS_INVALID_MISSING_INTERFACE: return "Missing interface"; 00857 case DBUS_INVALID_MISSING_MEMBER: return "Missing member"; 00858 case DBUS_INVALID_MISSING_ERROR_NAME: return "Missing error name"; 00859 case DBUS_INVALID_MISSING_REPLY_SERIAL: return "Missing reply serial"; 00860 case DBUS_INVALID_LENGTH_OUT_OF_BOUNDS: return "Length out of bounds"; 00861 case DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM: return "Array length exceeds maximum"; 00862 case DBUS_INVALID_BAD_PATH: return "Bad path"; 00863 case DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS: return "Signature length out of bounds"; 00864 case DBUS_INVALID_BAD_UTF8_IN_STRING: return "Bad utf8 in string"; 00865 case DBUS_INVALID_ARRAY_LENGTH_INCORRECT: return "Array length incorrect"; 00866 case DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS: return "Variant signature length out of bounds"; 00867 case DBUS_INVALID_VARIANT_SIGNATURE_BAD: return "Variant signature bad"; 00868 case DBUS_INVALID_VARIANT_SIGNATURE_EMPTY: return "Variant signature empty"; 00869 case DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES: return "Variant signature specifies multiple values"; 00870 case DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL: return "Variant signature missing nul"; 00871 case DBUS_INVALID_STRING_MISSING_NUL: return "String missing nul"; 00872 case DBUS_INVALID_SIGNATURE_MISSING_NUL: return "Signature missing nul"; 00873 case DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION: return "Exceeded maximum dict entry recursion"; 00874 case DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED: return "Dict entry ended but not started"; 00875 case DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED: return "Dict entry started but not ended"; 00876 case DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS: return "Dict entry has no fields"; 00877 case DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD: return "Dict entry has only one field"; 00878 case DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS: return "Dict entry has too many fields"; 00879 case DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY: return "Dict entry not inside array"; 00880 case DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE: return "Dict key must be basic type"; 00881 00882 default: 00883 return "Invalid"; 00884 } 00885 } 00886 00900 dbus_bool_t 00901 _dbus_validate_interface (const DBusString *str, 00902 int start, 00903 int len) 00904 { 00905 const unsigned char *s; 00906 const unsigned char *end; 00907 const unsigned char *iface; 00908 const unsigned char *last_dot; 00909 00910 _dbus_assert (start >= 0); 00911 _dbus_assert (len >= 0); 00912 _dbus_assert (start <= _dbus_string_get_length (str)); 00913 00914 if (len > _dbus_string_get_length (str) - start) 00915 return FALSE; 00916 00917 if (len > DBUS_MAXIMUM_NAME_LENGTH) 00918 return FALSE; 00919 00920 if (len == 0) 00921 return FALSE; 00922 00923 last_dot = NULL; 00924 iface = _dbus_string_get_const_data (str) + start; 00925 end = iface + len; 00926 s = iface; 00927 00928 /* check special cases of first char so it doesn't have to be done 00929 * in the loop. Note we know len > 0 00930 */ 00931 if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */ 00932 return FALSE; 00933 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) 00934 return FALSE; 00935 else 00936 ++s; 00937 00938 while (s != end) 00939 { 00940 if (*s == '.') 00941 { 00942 if (_DBUS_UNLIKELY ((s + 1) == end)) 00943 return FALSE; 00944 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1)))) 00945 return FALSE; 00946 last_dot = s; 00947 ++s; /* we just validated the next char, so skip two */ 00948 } 00949 else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 00950 { 00951 return FALSE; 00952 } 00953 00954 ++s; 00955 } 00956 00957 if (_DBUS_UNLIKELY (last_dot == NULL)) 00958 return FALSE; 00959 00960 return TRUE; 00961 } 00962 00976 dbus_bool_t 00977 _dbus_validate_member (const DBusString *str, 00978 int start, 00979 int len) 00980 { 00981 const unsigned char *s; 00982 const unsigned char *end; 00983 const unsigned char *member; 00984 00985 _dbus_assert (start >= 0); 00986 _dbus_assert (len >= 0); 00987 _dbus_assert (start <= _dbus_string_get_length (str)); 00988 00989 if (len > _dbus_string_get_length (str) - start) 00990 return FALSE; 00991 00992 if (len > DBUS_MAXIMUM_NAME_LENGTH) 00993 return FALSE; 00994 00995 if (len == 0) 00996 return FALSE; 00997 00998 member = _dbus_string_get_const_data (str) + start; 00999 end = member + len; 01000 s = member; 01001 01002 /* check special cases of first char so it doesn't have to be done 01003 * in the loop. Note we know len > 0 01004 */ 01005 01006 if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) 01007 return FALSE; 01008 else 01009 ++s; 01010 01011 while (s != end) 01012 { 01013 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 01014 { 01015 return FALSE; 01016 } 01017 01018 ++s; 01019 } 01020 01021 return TRUE; 01022 } 01023 01037 dbus_bool_t 01038 _dbus_validate_error_name (const DBusString *str, 01039 int start, 01040 int len) 01041 { 01042 /* Same restrictions as interface name at the moment */ 01043 return _dbus_validate_interface (str, start, len); 01044 } 01045 01050 #define VALID_INITIAL_BUS_NAME_CHARACTER(c) \ 01051 ( ((c) >= 'A' && (c) <= 'Z') || \ 01052 ((c) >= 'a' && (c) <= 'z') || \ 01053 ((c) == '_') || ((c) == '-')) 01054 01059 #define VALID_BUS_NAME_CHARACTER(c) \ 01060 ( ((c) >= '0' && (c) <= '9') || \ 01061 ((c) >= 'A' && (c) <= 'Z') || \ 01062 ((c) >= 'a' && (c) <= 'z') || \ 01063 ((c) == '_') || ((c) == '-')) 01064 01078 dbus_bool_t 01079 _dbus_validate_bus_name (const DBusString *str, 01080 int start, 01081 int len) 01082 { 01083 const unsigned char *s; 01084 const unsigned char *end; 01085 const unsigned char *iface; 01086 const unsigned char *last_dot; 01087 01088 _dbus_assert (start >= 0); 01089 _dbus_assert (len >= 0); 01090 _dbus_assert (start <= _dbus_string_get_length (str)); 01091 01092 if (len > _dbus_string_get_length (str) - start) 01093 return FALSE; 01094 01095 if (len > DBUS_MAXIMUM_NAME_LENGTH) 01096 return FALSE; 01097 01098 if (len == 0) 01099 return FALSE; 01100 01101 last_dot = NULL; 01102 iface = _dbus_string_get_const_data (str) + start; 01103 end = iface + len; 01104 s = iface; 01105 01106 /* check special cases of first char so it doesn't have to be done 01107 * in the loop. Note we know len > 0 01108 */ 01109 if (*s == ':') 01110 { 01111 /* unique name */ 01112 ++s; 01113 while (s != end) 01114 { 01115 if (*s == '.') 01116 { 01117 if (_DBUS_UNLIKELY ((s + 1) == end)) 01118 return FALSE; 01119 if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*(s + 1)))) 01120 return FALSE; 01121 ++s; /* we just validated the next char, so skip two */ 01122 } 01123 else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s))) 01124 { 01125 return FALSE; 01126 } 01127 01128 ++s; 01129 } 01130 01131 return TRUE; 01132 } 01133 else if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */ 01134 return FALSE; 01135 else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*s))) 01136 return FALSE; 01137 else 01138 ++s; 01139 01140 while (s != end) 01141 { 01142 if (*s == '.') 01143 { 01144 if (_DBUS_UNLIKELY ((s + 1) == end)) 01145 return FALSE; 01146 else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*(s + 1)))) 01147 return FALSE; 01148 last_dot = s; 01149 ++s; /* we just validated the next char, so skip two */ 01150 } 01151 else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s))) 01152 { 01153 return FALSE; 01154 } 01155 01156 ++s; 01157 } 01158 01159 if (_DBUS_UNLIKELY (last_dot == NULL)) 01160 return FALSE; 01161 01162 return TRUE; 01163 } 01164 01177 dbus_bool_t 01178 _dbus_validate_signature (const DBusString *str, 01179 int start, 01180 int len) 01181 { 01182 _dbus_assert (start >= 0); 01183 _dbus_assert (start <= _dbus_string_get_length (str)); 01184 _dbus_assert (len >= 0); 01185 01186 if (len > _dbus_string_get_length (str) - start) 01187 return FALSE; 01188 01189 return _dbus_validate_signature_with_reason (str, start, len) == DBUS_VALID; 01190 } 01191 01193 DEFINE_DBUS_NAME_CHECK(path) 01195 DEFINE_DBUS_NAME_CHECK(interface) 01197 DEFINE_DBUS_NAME_CHECK(member) 01199 DEFINE_DBUS_NAME_CHECK(error_name) 01201 DEFINE_DBUS_NAME_CHECK(bus_name) 01203 DEFINE_DBUS_NAME_CHECK(signature) 01204 01207 /* tests in dbus-marshal-validate-util.c */