D-Bus 1.2.24
|
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 "dbus-internals.h" 00025 #include "dbus-marshal-validate.h" 00026 #include "dbus-marshal-recursive.h" 00027 #include "dbus-marshal-basic.h" 00028 #include "dbus-signature.h" 00029 #include "dbus-string.h" 00030 00049 DBusValidity 00050 _dbus_validate_signature_with_reason (const DBusString *type_str, 00051 int type_pos, 00052 int len) 00053 { 00054 const unsigned char *p; 00055 const unsigned char *end; 00056 int last; 00057 int struct_depth; 00058 int array_depth; 00059 int dict_entry_depth; 00060 DBusValidity result; 00061 00062 int element_count; 00063 DBusList *element_count_stack; 00064 00065 result = DBUS_VALID; 00066 element_count_stack = NULL; 00067 00068 if (!_dbus_list_append (&element_count_stack, _DBUS_INT_TO_POINTER (0))) 00069 { 00070 result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; 00071 goto out; 00072 } 00073 00074 _dbus_assert (type_str != NULL); 00075 _dbus_assert (type_pos < _DBUS_INT32_MAX - len); 00076 _dbus_assert (len >= 0); 00077 _dbus_assert (type_pos >= 0); 00078 00079 if (len > DBUS_MAXIMUM_SIGNATURE_LENGTH) 00080 { 00081 result = DBUS_INVALID_SIGNATURE_TOO_LONG; 00082 goto out; 00083 } 00084 00085 p = _dbus_string_get_const_data_len (type_str, type_pos, 0); 00086 00087 end = _dbus_string_get_const_data_len (type_str, type_pos + len, 0); 00088 struct_depth = 0; 00089 array_depth = 0; 00090 dict_entry_depth = 0; 00091 last = DBUS_TYPE_INVALID; 00092 00093 while (p != end) 00094 { 00095 switch (*p) 00096 { 00097 case DBUS_TYPE_BYTE: 00098 case DBUS_TYPE_BOOLEAN: 00099 case DBUS_TYPE_INT16: 00100 case DBUS_TYPE_UINT16: 00101 case DBUS_TYPE_INT32: 00102 case DBUS_TYPE_UINT32: 00103 case DBUS_TYPE_INT64: 00104 case DBUS_TYPE_UINT64: 00105 case DBUS_TYPE_DOUBLE: 00106 case DBUS_TYPE_STRING: 00107 case DBUS_TYPE_OBJECT_PATH: 00108 case DBUS_TYPE_SIGNATURE: 00109 case DBUS_TYPE_VARIANT: 00110 break; 00111 00112 case DBUS_TYPE_ARRAY: 00113 array_depth += 1; 00114 if (array_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) 00115 { 00116 result = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION; 00117 goto out; 00118 } 00119 break; 00120 00121 case DBUS_STRUCT_BEGIN_CHAR: 00122 struct_depth += 1; 00123 00124 if (struct_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) 00125 { 00126 result = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION; 00127 goto out; 00128 } 00129 00130 if (!_dbus_list_append (&element_count_stack, 00131 _DBUS_INT_TO_POINTER (0))) 00132 { 00133 result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; 00134 goto out; 00135 } 00136 00137 break; 00138 00139 case DBUS_STRUCT_END_CHAR: 00140 if (struct_depth == 0) 00141 { 00142 result = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED; 00143 goto out; 00144 } 00145 00146 if (last == DBUS_STRUCT_BEGIN_CHAR) 00147 { 00148 result = DBUS_INVALID_STRUCT_HAS_NO_FIELDS; 00149 goto out; 00150 } 00151 00152 _dbus_list_pop_last (&element_count_stack); 00153 00154 struct_depth -= 1; 00155 break; 00156 00157 case DBUS_DICT_ENTRY_BEGIN_CHAR: 00158 if (last != DBUS_TYPE_ARRAY) 00159 { 00160 result = DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY; 00161 goto out; 00162 } 00163 00164 dict_entry_depth += 1; 00165 00166 if (dict_entry_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) 00167 { 00168 result = DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION; 00169 goto out; 00170 } 00171 00172 if (!_dbus_list_append (&element_count_stack, 00173 _DBUS_INT_TO_POINTER (0))) 00174 { 00175 result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; 00176 goto out; 00177 } 00178 00179 break; 00180 00181 case DBUS_DICT_ENTRY_END_CHAR: 00182 if (dict_entry_depth == 0) 00183 { 00184 result = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED; 00185 goto out; 00186 } 00187 00188 dict_entry_depth -= 1; 00189 00190 element_count = 00191 _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack)); 00192 00193 if (element_count != 2) 00194 { 00195 if (element_count == 0) 00196 result = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS; 00197 else if (element_count == 1) 00198 result = DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD; 00199 else 00200 result = DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS; 00201 00202 goto out; 00203 } 00204 break; 00205 00206 case DBUS_TYPE_STRUCT: /* doesn't appear in signatures */ 00207 case DBUS_TYPE_DICT_ENTRY: /* ditto */ 00208 default: 00209 result = DBUS_INVALID_UNKNOWN_TYPECODE; 00210 goto out; 00211 } 00212 00213 if (*p != DBUS_TYPE_ARRAY && 00214 *p != DBUS_DICT_ENTRY_BEGIN_CHAR && 00215 *p != DBUS_STRUCT_BEGIN_CHAR) 00216 { 00217 element_count = 00218 _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack)); 00219 00220 ++element_count; 00221 00222 if (!_dbus_list_append (&element_count_stack, 00223 _DBUS_INT_TO_POINTER (element_count))) 00224 { 00225 result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; 00226 goto out; 00227 } 00228 } 00229 00230 if (array_depth > 0) 00231 { 00232 if (*p == DBUS_TYPE_ARRAY && p != end) 00233 { 00234 const char *p1; 00235 p1 = p + 1; 00236 if (*p1 == DBUS_STRUCT_END_CHAR || 00237 *p1 == DBUS_DICT_ENTRY_END_CHAR) 00238 { 00239 result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE; 00240 goto out; 00241 } 00242 } 00243 else 00244 { 00245 array_depth = 0; 00246 } 00247 } 00248 00249 if (last == DBUS_DICT_ENTRY_BEGIN_CHAR) 00250 { 00251 if (!(_dbus_type_is_valid (*p) && dbus_type_is_basic (*p))) 00252 { 00253 result = DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE; 00254 goto out; 00255 } 00256 } 00257 00258 last = *p; 00259 ++p; 00260 } 00261 00262 00263 if (array_depth > 0) 00264 { 00265 result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE; 00266 goto out; 00267 } 00268 00269 if (struct_depth > 0) 00270 { 00271 result = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED; 00272 goto out; 00273 } 00274 00275 if (dict_entry_depth > 0) 00276 { 00277 result = DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED; 00278 goto out; 00279 } 00280 00281 _dbus_assert (last != DBUS_TYPE_ARRAY); 00282 _dbus_assert (last != DBUS_STRUCT_BEGIN_CHAR); 00283 _dbus_assert (last != DBUS_DICT_ENTRY_BEGIN_CHAR); 00284 00285 result = DBUS_VALID; 00286 00287 out: 00288 _dbus_list_clear (&element_count_stack); 00289 return result; 00290 } 00291 00292 /* note: this function is also used to validate the header's values, 00293 * since the header is a valid body with a particular signature. 00294 */ 00295 static DBusValidity 00296 validate_body_helper (DBusTypeReader *reader, 00297 int byte_order, 00298 dbus_bool_t walk_reader_to_end, 00299 int total_depth, 00300 const unsigned char *p, 00301 const unsigned char *end, 00302 const unsigned char **new_p) 00303 { 00304 int current_type; 00305 00306 /* The spec allows arrays and structs to each nest 32, for total 00307 * nesting of 2*32. We want to impose the same limit on "dynamic" 00308 * value nesting (not visible in the signature) which is introduced 00309 * by DBUS_TYPE_VARIANT. 00310 */ 00311 if (total_depth > (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH * 2)) 00312 { 00313 return DBUS_INVALID_NESTED_TOO_DEEPLY; 00314 } 00315 00316 while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID) 00317 { 00318 const unsigned char *a; 00319 int alignment; 00320 00321 #if 0 00322 _dbus_verbose (" validating value of type %s type reader %p type_pos %d p %p end %p %d remain\n", 00323 _dbus_type_to_string (current_type), reader, reader->type_pos, p, end, 00324 (int) (end - p)); 00325 #endif 00326 00327 /* Guarantee that p has one byte to look at */ 00328 if (p == end) 00329 return DBUS_INVALID_NOT_ENOUGH_DATA; 00330 00331 switch (current_type) 00332 { 00333 case DBUS_TYPE_BYTE: 00334 ++p; 00335 break; 00336 00337 case DBUS_TYPE_BOOLEAN: 00338 case DBUS_TYPE_INT16: 00339 case DBUS_TYPE_UINT16: 00340 case DBUS_TYPE_INT32: 00341 case DBUS_TYPE_UINT32: 00342 case DBUS_TYPE_INT64: 00343 case DBUS_TYPE_UINT64: 00344 case DBUS_TYPE_DOUBLE: 00345 alignment = _dbus_type_get_alignment (current_type); 00346 a = _DBUS_ALIGN_ADDRESS (p, alignment); 00347 if (a >= end) 00348 return DBUS_INVALID_NOT_ENOUGH_DATA; 00349 while (p != a) 00350 { 00351 if (*p != '\0') 00352 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 00353 ++p; 00354 } 00355 00356 if (current_type == DBUS_TYPE_BOOLEAN) 00357 { 00358 dbus_uint32_t v = _dbus_unpack_uint32 (byte_order, 00359 p); 00360 if (!(v == 0 || v == 1)) 00361 return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE; 00362 } 00363 00364 p += alignment; 00365 break; 00366 00367 case DBUS_TYPE_ARRAY: 00368 case DBUS_TYPE_STRING: 00369 case DBUS_TYPE_OBJECT_PATH: 00370 { 00371 dbus_uint32_t claimed_len; 00372 00373 a = _DBUS_ALIGN_ADDRESS (p, 4); 00374 if (a + 4 > end) 00375 return DBUS_INVALID_NOT_ENOUGH_DATA; 00376 while (p != a) 00377 { 00378 if (*p != '\0') 00379 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 00380 ++p; 00381 } 00382 00383 claimed_len = _dbus_unpack_uint32 (byte_order, p); 00384 p += 4; 00385 00386 /* p may now be == end */ 00387 _dbus_assert (p <= end); 00388 00389 if (current_type == DBUS_TYPE_ARRAY) 00390 { 00391 int array_elem_type = _dbus_type_reader_get_element_type (reader); 00392 00393 if (!_dbus_type_is_valid (array_elem_type)) 00394 { 00395 return DBUS_INVALID_UNKNOWN_TYPECODE; 00396 } 00397 00398 alignment = _dbus_type_get_alignment (array_elem_type); 00399 00400 a = _DBUS_ALIGN_ADDRESS (p, alignment); 00401 00402 /* a may now be == end */ 00403 if (a > end) 00404 return DBUS_INVALID_NOT_ENOUGH_DATA; 00405 00406 while (p != a) 00407 { 00408 if (*p != '\0') 00409 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 00410 ++p; 00411 } 00412 } 00413 00414 if (claimed_len > (unsigned long) (end - p)) 00415 return DBUS_INVALID_LENGTH_OUT_OF_BOUNDS; 00416 00417 if (current_type == DBUS_TYPE_OBJECT_PATH) 00418 { 00419 DBusString str; 00420 _dbus_string_init_const_len (&str, p, claimed_len); 00421 if (!_dbus_validate_path (&str, 0, 00422 _dbus_string_get_length (&str))) 00423 return DBUS_INVALID_BAD_PATH; 00424 00425 p += claimed_len; 00426 } 00427 else if (current_type == DBUS_TYPE_STRING) 00428 { 00429 DBusString str; 00430 _dbus_string_init_const_len (&str, p, claimed_len); 00431 if (!_dbus_string_validate_utf8 (&str, 0, 00432 _dbus_string_get_length (&str))) 00433 return DBUS_INVALID_BAD_UTF8_IN_STRING; 00434 00435 p += claimed_len; 00436 } 00437 else if (current_type == DBUS_TYPE_ARRAY && claimed_len > 0) 00438 { 00439 DBusTypeReader sub; 00440 DBusValidity validity; 00441 const unsigned char *array_end; 00442 int array_elem_type; 00443 00444 if (claimed_len > DBUS_MAXIMUM_ARRAY_LENGTH) 00445 return DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM; 00446 00447 /* Remember that the reader is types only, so we can't 00448 * use it to iterate over elements. It stays the same 00449 * for all elements. 00450 */ 00451 _dbus_type_reader_recurse (reader, &sub); 00452 00453 array_end = p + claimed_len; 00454 00455 array_elem_type = _dbus_type_reader_get_element_type (reader); 00456 00457 /* avoid recursive call to validate_body_helper if this is an array 00458 * of fixed-size elements 00459 */ 00460 if (dbus_type_is_fixed (array_elem_type)) 00461 { 00462 /* bools need to be handled differently, because they can 00463 * have an invalid value 00464 */ 00465 if (array_elem_type == DBUS_TYPE_BOOLEAN) 00466 { 00467 dbus_uint32_t v; 00468 alignment = _dbus_type_get_alignment (array_elem_type); 00469 00470 while (p < array_end) 00471 { 00472 v = _dbus_unpack_uint32 (byte_order, p); 00473 00474 if (!(v == 0 || v == 1)) 00475 return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE; 00476 00477 p += alignment; 00478 } 00479 } 00480 00481 else 00482 { 00483 p = array_end; 00484 } 00485 } 00486 00487 else 00488 { 00489 while (p < array_end) 00490 { 00491 validity = validate_body_helper (&sub, byte_order, FALSE, 00492 total_depth + 1, 00493 p, end, &p); 00494 if (validity != DBUS_VALID) 00495 return validity; 00496 } 00497 } 00498 00499 if (p != array_end) 00500 return DBUS_INVALID_ARRAY_LENGTH_INCORRECT; 00501 } 00502 00503 /* check nul termination */ 00504 if (current_type != DBUS_TYPE_ARRAY) 00505 { 00506 if (p == end) 00507 return DBUS_INVALID_NOT_ENOUGH_DATA; 00508 00509 if (*p != '\0') 00510 return DBUS_INVALID_STRING_MISSING_NUL; 00511 ++p; 00512 } 00513 } 00514 break; 00515 00516 case DBUS_TYPE_SIGNATURE: 00517 { 00518 dbus_uint32_t claimed_len; 00519 DBusString str; 00520 DBusValidity validity; 00521 00522 claimed_len = *p; 00523 ++p; 00524 00525 /* 1 is for nul termination */ 00526 if (claimed_len + 1 > (unsigned long) (end - p)) 00527 return DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS; 00528 00529 _dbus_string_init_const_len (&str, p, claimed_len); 00530 validity = 00531 _dbus_validate_signature_with_reason (&str, 0, 00532 _dbus_string_get_length (&str)); 00533 00534 if (validity != DBUS_VALID) 00535 return validity; 00536 00537 p += claimed_len; 00538 00539 _dbus_assert (p < end); 00540 if (*p != DBUS_TYPE_INVALID) 00541 return DBUS_INVALID_SIGNATURE_MISSING_NUL; 00542 00543 ++p; 00544 00545 _dbus_verbose ("p = %p end = %p claimed_len %u\n", p, end, claimed_len); 00546 } 00547 break; 00548 00549 case DBUS_TYPE_VARIANT: 00550 { 00551 /* 1 byte sig len, sig typecodes, align to 00552 * contained-type-boundary, values. 00553 */ 00554 00555 /* In addition to normal signature validation, we need to be sure 00556 * the signature contains only a single (possibly container) type. 00557 */ 00558 dbus_uint32_t claimed_len; 00559 DBusString sig; 00560 DBusTypeReader sub; 00561 DBusValidity validity; 00562 int contained_alignment; 00563 int contained_type; 00564 DBusValidity reason; 00565 00566 claimed_len = *p; 00567 ++p; 00568 00569 /* + 1 for nul */ 00570 if (claimed_len + 1 > (unsigned long) (end - p)) 00571 return DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS; 00572 00573 _dbus_string_init_const_len (&sig, p, claimed_len); 00574 reason = _dbus_validate_signature_with_reason (&sig, 0, 00575 _dbus_string_get_length (&sig)); 00576 if (!(reason == DBUS_VALID)) 00577 { 00578 if (reason == DBUS_VALIDITY_UNKNOWN_OOM_ERROR) 00579 return reason; 00580 else 00581 return DBUS_INVALID_VARIANT_SIGNATURE_BAD; 00582 } 00583 00584 p += claimed_len; 00585 00586 if (*p != DBUS_TYPE_INVALID) 00587 return DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL; 00588 ++p; 00589 00590 contained_type = _dbus_first_type_in_signature (&sig, 0); 00591 if (contained_type == DBUS_TYPE_INVALID) 00592 return DBUS_INVALID_VARIANT_SIGNATURE_EMPTY; 00593 00594 contained_alignment = _dbus_type_get_alignment (contained_type); 00595 00596 a = _DBUS_ALIGN_ADDRESS (p, contained_alignment); 00597 if (a > end) 00598 return DBUS_INVALID_NOT_ENOUGH_DATA; 00599 while (p != a) 00600 { 00601 if (*p != '\0') 00602 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 00603 ++p; 00604 } 00605 00606 _dbus_type_reader_init_types_only (&sub, &sig, 0); 00607 00608 _dbus_assert (_dbus_type_reader_get_current_type (&sub) != DBUS_TYPE_INVALID); 00609 00610 validity = validate_body_helper (&sub, byte_order, FALSE, 00611 total_depth + 1, 00612 p, end, &p); 00613 if (validity != DBUS_VALID) 00614 return validity; 00615 00616 if (_dbus_type_reader_next (&sub)) 00617 return DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES; 00618 00619 _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_INVALID); 00620 } 00621 break; 00622 00623 case DBUS_TYPE_DICT_ENTRY: 00624 case DBUS_TYPE_STRUCT: 00625 { 00626 DBusTypeReader sub; 00627 DBusValidity validity; 00628 00629 a = _DBUS_ALIGN_ADDRESS (p, 8); 00630 if (a > end) 00631 return DBUS_INVALID_NOT_ENOUGH_DATA; 00632 while (p != a) 00633 { 00634 if (*p != '\0') 00635 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 00636 ++p; 00637 } 00638 00639 _dbus_type_reader_recurse (reader, &sub); 00640 00641 validity = validate_body_helper (&sub, byte_order, TRUE, 00642 total_depth + 1, 00643 p, end, &p); 00644 if (validity != DBUS_VALID) 00645 return validity; 00646 } 00647 break; 00648 00649 default: 00650 _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature"); 00651 break; 00652 } 00653 00654 #if 0 00655 _dbus_verbose (" validated value of type %s type reader %p type_pos %d p %p end %p %d remain\n", 00656 _dbus_type_to_string (current_type), reader, reader->type_pos, p, end, 00657 (int) (end - p)); 00658 #endif 00659 00660 if (p > end) 00661 { 00662 _dbus_verbose ("not enough data!!! p = %p end = %p end-p = %d\n", 00663 p, end, (int) (end - p)); 00664 return DBUS_INVALID_NOT_ENOUGH_DATA; 00665 } 00666 00667 if (walk_reader_to_end) 00668 _dbus_type_reader_next (reader); 00669 else 00670 break; 00671 } 00672 00673 if (new_p) 00674 *new_p = p; 00675 00676 return DBUS_VALID; 00677 } 00678 00699 DBusValidity 00700 _dbus_validate_body_with_reason (const DBusString *expected_signature, 00701 int expected_signature_start, 00702 int byte_order, 00703 int *bytes_remaining, 00704 const DBusString *value_str, 00705 int value_pos, 00706 int len) 00707 { 00708 DBusTypeReader reader; 00709 const unsigned char *p; 00710 const unsigned char *end; 00711 DBusValidity validity; 00712 00713 _dbus_assert (len >= 0); 00714 _dbus_assert (value_pos >= 0); 00715 _dbus_assert (value_pos <= _dbus_string_get_length (value_str) - len); 00716 00717 _dbus_verbose ("validating body from pos %d len %d sig '%s'\n", 00718 value_pos, len, _dbus_string_get_const_data_len (expected_signature, 00719 expected_signature_start, 00720 0)); 00721 00722 _dbus_type_reader_init_types_only (&reader, 00723 expected_signature, expected_signature_start); 00724 00725 p = _dbus_string_get_const_data_len (value_str, value_pos, len); 00726 end = p + len; 00727 00728 validity = validate_body_helper (&reader, byte_order, TRUE, 0, p, end, &p); 00729 if (validity != DBUS_VALID) 00730 return validity; 00731 00732 if (bytes_remaining) 00733 { 00734 *bytes_remaining = end - p; 00735 return DBUS_VALID; 00736 } 00737 else if (p < end) 00738 return DBUS_INVALID_TOO_MUCH_DATA; 00739 else 00740 { 00741 _dbus_assert (p == end); 00742 return DBUS_VALID; 00743 } 00744 } 00745 00750 #define VALID_INITIAL_NAME_CHARACTER(c) \ 00751 ( ((c) >= 'A' && (c) <= 'Z') || \ 00752 ((c) >= 'a' && (c) <= 'z') || \ 00753 ((c) == '_') ) 00754 00759 #define VALID_NAME_CHARACTER(c) \ 00760 ( ((c) >= '0' && (c) <= '9') || \ 00761 ((c) >= 'A' && (c) <= 'Z') || \ 00762 ((c) >= 'a' && (c) <= 'z') || \ 00763 ((c) == '_') ) 00764 00781 dbus_bool_t 00782 _dbus_validate_path (const DBusString *str, 00783 int start, 00784 int len) 00785 { 00786 const unsigned char *s; 00787 const unsigned char *end; 00788 const unsigned char *last_slash; 00789 00790 _dbus_assert (start >= 0); 00791 _dbus_assert (len >= 0); 00792 _dbus_assert (start <= _dbus_string_get_length (str)); 00793 00794 if (len > _dbus_string_get_length (str) - start) 00795 return FALSE; 00796 00797 if (len == 0) 00798 return FALSE; 00799 00800 s = _dbus_string_get_const_data (str) + start; 00801 end = s + len; 00802 00803 if (*s != '/') 00804 return FALSE; 00805 last_slash = s; 00806 ++s; 00807 00808 while (s != end) 00809 { 00810 if (*s == '/') 00811 { 00812 if ((s - last_slash) < 2) 00813 return FALSE; /* no empty path components allowed */ 00814 00815 last_slash = s; 00816 } 00817 else 00818 { 00819 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 00820 return FALSE; 00821 } 00822 00823 ++s; 00824 } 00825 00826 if ((end - last_slash) < 2 && 00827 len > 1) 00828 return FALSE; /* trailing slash not allowed unless the string is "/" */ 00829 00830 return TRUE; 00831 } 00832 00833 const char * 00834 _dbus_validity_to_error_message (DBusValidity validity) 00835 { 00836 switch (validity) 00837 { 00838 case DBUS_VALIDITY_UNKNOWN_OOM_ERROR: return "Out of memory"; 00839 case DBUS_INVALID_FOR_UNKNOWN_REASON: return "Unknown reason"; 00840 case DBUS_VALID_BUT_INCOMPLETE: return "Valid but incomplete"; 00841 case DBUS_VALIDITY_UNKNOWN: return "Validity unknown"; 00842 case DBUS_VALID: return "Valid"; 00843 case DBUS_INVALID_UNKNOWN_TYPECODE: return "Unknown typecode"; 00844 case DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE: return "Missing array element type"; 00845 case DBUS_INVALID_SIGNATURE_TOO_LONG: return "Signature is too long"; 00846 case DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION: return "Exceeded maximum array recursion"; 00847 case DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION: return "Exceeded maximum struct recursion"; 00848 case DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED: return "Struct ended but not started"; 00849 case DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED: return "Struct started but not ended"; 00850 case DBUS_INVALID_STRUCT_HAS_NO_FIELDS: return "Struct has no fields"; 00851 case DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL: return "Alignment padding not null"; 00852 case DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE: return "Boolean is not zero or one"; 00853 case DBUS_INVALID_NOT_ENOUGH_DATA: return "Not enough data"; 00854 case DBUS_INVALID_TOO_MUCH_DATA: return "Too much data"; 00855 case DBUS_INVALID_BAD_BYTE_ORDER: return "Bad byte order"; 00856 case DBUS_INVALID_BAD_PROTOCOL_VERSION: return "Bad protocol version"; 00857 case DBUS_INVALID_BAD_MESSAGE_TYPE: return "Bad message type"; 00858 case DBUS_INVALID_BAD_SERIAL: return "Bad serial"; 00859 case DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH: return "Insane fields array length"; 00860 case DBUS_INVALID_INSANE_BODY_LENGTH: return "Insane body length"; 00861 case DBUS_INVALID_MESSAGE_TOO_LONG: return "Message too long"; 00862 case DBUS_INVALID_HEADER_FIELD_CODE: return "Header field code"; 00863 case DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE: return "Header field has wrong type"; 00864 case DBUS_INVALID_USES_LOCAL_INTERFACE: return "Uses local interface"; 00865 case DBUS_INVALID_USES_LOCAL_PATH: return "Uses local path"; 00866 case DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE: return "Header field appears twice"; 00867 case DBUS_INVALID_BAD_DESTINATION: return "Bad destination"; 00868 case DBUS_INVALID_BAD_INTERFACE: return "Bad interface"; 00869 case DBUS_INVALID_BAD_MEMBER: return "Bad member"; 00870 case DBUS_INVALID_BAD_ERROR_NAME: return "Bad error name"; 00871 case DBUS_INVALID_BAD_SENDER: return "Bad sender"; 00872 case DBUS_INVALID_MISSING_PATH: return "Missing path"; 00873 case DBUS_INVALID_MISSING_INTERFACE: return "Missing interface"; 00874 case DBUS_INVALID_MISSING_MEMBER: return "Missing member"; 00875 case DBUS_INVALID_MISSING_ERROR_NAME: return "Missing error name"; 00876 case DBUS_INVALID_MISSING_REPLY_SERIAL: return "Missing reply serial"; 00877 case DBUS_INVALID_LENGTH_OUT_OF_BOUNDS: return "Length out of bounds"; 00878 case DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM: return "Array length exceeds maximum"; 00879 case DBUS_INVALID_BAD_PATH: return "Bad path"; 00880 case DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS: return "Signature length out of bounds"; 00881 case DBUS_INVALID_BAD_UTF8_IN_STRING: return "Bad utf8 in string"; 00882 case DBUS_INVALID_ARRAY_LENGTH_INCORRECT: return "Array length incorrect"; 00883 case DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS: return "Variant signature length out of bounds"; 00884 case DBUS_INVALID_VARIANT_SIGNATURE_BAD: return "Variant signature bad"; 00885 case DBUS_INVALID_VARIANT_SIGNATURE_EMPTY: return "Variant signature empty"; 00886 case DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES: return "Variant signature specifies multiple values"; 00887 case DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL: return "Variant signature missing nul"; 00888 case DBUS_INVALID_STRING_MISSING_NUL: return "String missing nul"; 00889 case DBUS_INVALID_SIGNATURE_MISSING_NUL: return "Signature missing nul"; 00890 case DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION: return "Exceeded maximum dict entry recursion"; 00891 case DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED: return "Dict entry ended but not started"; 00892 case DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED: return "Dict entry started but not ended"; 00893 case DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS: return "Dict entry has no fields"; 00894 case DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD: return "Dict entry has only one field"; 00895 case DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS: return "Dict entry has too many fields"; 00896 case DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY: return "Dict entry not inside array"; 00897 case DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE: return "Dict key must be basic type"; 00898 case DBUS_INVALID_NESTED_TOO_DEEPLY: return "Variants cannot be used to create a hugely recursive tree of values"; 00899 default: 00900 return "Invalid"; 00901 } 00902 } 00903 00917 dbus_bool_t 00918 _dbus_validate_interface (const DBusString *str, 00919 int start, 00920 int len) 00921 { 00922 const unsigned char *s; 00923 const unsigned char *end; 00924 const unsigned char *iface; 00925 const unsigned char *last_dot; 00926 00927 _dbus_assert (start >= 0); 00928 _dbus_assert (len >= 0); 00929 _dbus_assert (start <= _dbus_string_get_length (str)); 00930 00931 if (len > _dbus_string_get_length (str) - start) 00932 return FALSE; 00933 00934 if (len > DBUS_MAXIMUM_NAME_LENGTH) 00935 return FALSE; 00936 00937 if (len == 0) 00938 return FALSE; 00939 00940 last_dot = NULL; 00941 iface = _dbus_string_get_const_data (str) + start; 00942 end = iface + len; 00943 s = iface; 00944 00945 /* check special cases of first char so it doesn't have to be done 00946 * in the loop. Note we know len > 0 00947 */ 00948 if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */ 00949 return FALSE; 00950 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) 00951 return FALSE; 00952 else 00953 ++s; 00954 00955 while (s != end) 00956 { 00957 if (*s == '.') 00958 { 00959 if (_DBUS_UNLIKELY ((s + 1) == end)) 00960 return FALSE; 00961 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1)))) 00962 return FALSE; 00963 last_dot = s; 00964 ++s; /* we just validated the next char, so skip two */ 00965 } 00966 else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 00967 { 00968 return FALSE; 00969 } 00970 00971 ++s; 00972 } 00973 00974 if (_DBUS_UNLIKELY (last_dot == NULL)) 00975 return FALSE; 00976 00977 return TRUE; 00978 } 00979 00993 dbus_bool_t 00994 _dbus_validate_member (const DBusString *str, 00995 int start, 00996 int len) 00997 { 00998 const unsigned char *s; 00999 const unsigned char *end; 01000 const unsigned char *member; 01001 01002 _dbus_assert (start >= 0); 01003 _dbus_assert (len >= 0); 01004 _dbus_assert (start <= _dbus_string_get_length (str)); 01005 01006 if (len > _dbus_string_get_length (str) - start) 01007 return FALSE; 01008 01009 if (len > DBUS_MAXIMUM_NAME_LENGTH) 01010 return FALSE; 01011 01012 if (len == 0) 01013 return FALSE; 01014 01015 member = _dbus_string_get_const_data (str) + start; 01016 end = member + len; 01017 s = member; 01018 01019 /* check special cases of first char so it doesn't have to be done 01020 * in the loop. Note we know len > 0 01021 */ 01022 01023 if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) 01024 return FALSE; 01025 else 01026 ++s; 01027 01028 while (s != end) 01029 { 01030 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 01031 { 01032 return FALSE; 01033 } 01034 01035 ++s; 01036 } 01037 01038 return TRUE; 01039 } 01040 01054 dbus_bool_t 01055 _dbus_validate_error_name (const DBusString *str, 01056 int start, 01057 int len) 01058 { 01059 /* Same restrictions as interface name at the moment */ 01060 return _dbus_validate_interface (str, start, len); 01061 } 01062 01067 #define VALID_INITIAL_BUS_NAME_CHARACTER(c) \ 01068 ( ((c) >= 'A' && (c) <= 'Z') || \ 01069 ((c) >= 'a' && (c) <= 'z') || \ 01070 ((c) == '_') || ((c) == '-')) 01071 01076 #define VALID_BUS_NAME_CHARACTER(c) \ 01077 ( ((c) >= '0' && (c) <= '9') || \ 01078 ((c) >= 'A' && (c) <= 'Z') || \ 01079 ((c) >= 'a' && (c) <= 'z') || \ 01080 ((c) == '_') || ((c) == '-')) 01081 01095 dbus_bool_t 01096 _dbus_validate_bus_name (const DBusString *str, 01097 int start, 01098 int len) 01099 { 01100 const unsigned char *s; 01101 const unsigned char *end; 01102 const unsigned char *iface; 01103 const unsigned char *last_dot; 01104 01105 _dbus_assert (start >= 0); 01106 _dbus_assert (len >= 0); 01107 _dbus_assert (start <= _dbus_string_get_length (str)); 01108 01109 if (len > _dbus_string_get_length (str) - start) 01110 return FALSE; 01111 01112 if (len > DBUS_MAXIMUM_NAME_LENGTH) 01113 return FALSE; 01114 01115 if (len == 0) 01116 return FALSE; 01117 01118 last_dot = NULL; 01119 iface = _dbus_string_get_const_data (str) + start; 01120 end = iface + len; 01121 s = iface; 01122 01123 /* check special cases of first char so it doesn't have to be done 01124 * in the loop. Note we know len > 0 01125 */ 01126 if (*s == ':') 01127 { 01128 /* unique name */ 01129 ++s; 01130 while (s != end) 01131 { 01132 if (*s == '.') 01133 { 01134 if (_DBUS_UNLIKELY ((s + 1) == end)) 01135 return FALSE; 01136 if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*(s + 1)))) 01137 return FALSE; 01138 ++s; /* we just validated the next char, so skip two */ 01139 } 01140 else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s))) 01141 { 01142 return FALSE; 01143 } 01144 01145 ++s; 01146 } 01147 01148 return TRUE; 01149 } 01150 else if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */ 01151 return FALSE; 01152 else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*s))) 01153 return FALSE; 01154 else 01155 ++s; 01156 01157 while (s != end) 01158 { 01159 if (*s == '.') 01160 { 01161 if (_DBUS_UNLIKELY ((s + 1) == end)) 01162 return FALSE; 01163 else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*(s + 1)))) 01164 return FALSE; 01165 last_dot = s; 01166 ++s; /* we just validated the next char, so skip two */ 01167 } 01168 else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s))) 01169 { 01170 return FALSE; 01171 } 01172 01173 ++s; 01174 } 01175 01176 if (_DBUS_UNLIKELY (last_dot == NULL)) 01177 return FALSE; 01178 01179 return TRUE; 01180 } 01181 01194 dbus_bool_t 01195 _dbus_validate_signature (const DBusString *str, 01196 int start, 01197 int len) 01198 { 01199 _dbus_assert (start >= 0); 01200 _dbus_assert (start <= _dbus_string_get_length (str)); 01201 _dbus_assert (len >= 0); 01202 01203 if (len > _dbus_string_get_length (str) - start) 01204 return FALSE; 01205 01206 return _dbus_validate_signature_with_reason (str, start, len) == DBUS_VALID; 01207 } 01208 01210 DEFINE_DBUS_NAME_CHECK(path) 01212 DEFINE_DBUS_NAME_CHECK(interface) 01214 DEFINE_DBUS_NAME_CHECK(member) 01216 DEFINE_DBUS_NAME_CHECK(error_name) 01218 DEFINE_DBUS_NAME_CHECK(bus_name) 01220 DEFINE_DBUS_NAME_CHECK(signature) 01221 01224 /* tests in dbus-marshal-validate-util.c */