D-Bus
1.4.18
|
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 /* note: this function is also used to validate the header's values, 00295 * since the header is a valid body with a particular signature. 00296 */ 00297 static DBusValidity 00298 validate_body_helper (DBusTypeReader *reader, 00299 int byte_order, 00300 dbus_bool_t walk_reader_to_end, 00301 int total_depth, 00302 const unsigned char *p, 00303 const unsigned char *end, 00304 const unsigned char **new_p) 00305 { 00306 int current_type; 00307 00308 /* The spec allows arrays and structs to each nest 32, for total 00309 * nesting of 2*32. We want to impose the same limit on "dynamic" 00310 * value nesting (not visible in the signature) which is introduced 00311 * by DBUS_TYPE_VARIANT. 00312 */ 00313 if (total_depth > (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH * 2)) 00314 { 00315 return DBUS_INVALID_NESTED_TOO_DEEPLY; 00316 } 00317 00318 while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID) 00319 { 00320 const unsigned char *a; 00321 int alignment; 00322 00323 #if 0 00324 _dbus_verbose (" validating value of type %s type reader %p type_pos %d p %p end %p %d remain\n", 00325 _dbus_type_to_string (current_type), reader, reader->type_pos, p, end, 00326 (int) (end - p)); 00327 #endif 00328 00329 /* Guarantee that p has one byte to look at */ 00330 if (p == end) 00331 return DBUS_INVALID_NOT_ENOUGH_DATA; 00332 00333 switch (current_type) 00334 { 00335 case DBUS_TYPE_BYTE: 00336 ++p; 00337 break; 00338 00339 case DBUS_TYPE_BOOLEAN: 00340 case DBUS_TYPE_INT16: 00341 case DBUS_TYPE_UINT16: 00342 case DBUS_TYPE_INT32: 00343 case DBUS_TYPE_UINT32: 00344 case DBUS_TYPE_UNIX_FD: 00345 case DBUS_TYPE_INT64: 00346 case DBUS_TYPE_UINT64: 00347 case DBUS_TYPE_DOUBLE: 00348 alignment = _dbus_type_get_alignment (current_type); 00349 a = _DBUS_ALIGN_ADDRESS (p, alignment); 00350 if (a >= end) 00351 return DBUS_INVALID_NOT_ENOUGH_DATA; 00352 while (p != a) 00353 { 00354 if (*p != '\0') 00355 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 00356 ++p; 00357 } 00358 00359 if (current_type == DBUS_TYPE_BOOLEAN) 00360 { 00361 dbus_uint32_t v = _dbus_unpack_uint32 (byte_order, 00362 p); 00363 if (!(v == 0 || v == 1)) 00364 return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE; 00365 } 00366 00367 p += alignment; 00368 break; 00369 00370 case DBUS_TYPE_ARRAY: 00371 case DBUS_TYPE_STRING: 00372 case DBUS_TYPE_OBJECT_PATH: 00373 { 00374 dbus_uint32_t claimed_len; 00375 00376 a = _DBUS_ALIGN_ADDRESS (p, 4); 00377 if (a + 4 > end) 00378 return DBUS_INVALID_NOT_ENOUGH_DATA; 00379 while (p != a) 00380 { 00381 if (*p != '\0') 00382 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 00383 ++p; 00384 } 00385 00386 claimed_len = _dbus_unpack_uint32 (byte_order, p); 00387 p += 4; 00388 00389 /* p may now be == end */ 00390 _dbus_assert (p <= end); 00391 00392 if (current_type == DBUS_TYPE_ARRAY) 00393 { 00394 int array_elem_type = _dbus_type_reader_get_element_type (reader); 00395 00396 if (!_dbus_type_is_valid (array_elem_type)) 00397 { 00398 return DBUS_INVALID_UNKNOWN_TYPECODE; 00399 } 00400 00401 alignment = _dbus_type_get_alignment (array_elem_type); 00402 00403 a = _DBUS_ALIGN_ADDRESS (p, alignment); 00404 00405 /* a may now be == end */ 00406 if (a > end) 00407 return DBUS_INVALID_NOT_ENOUGH_DATA; 00408 00409 while (p != a) 00410 { 00411 if (*p != '\0') 00412 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 00413 ++p; 00414 } 00415 } 00416 00417 if (claimed_len > (unsigned long) (end - p)) 00418 return DBUS_INVALID_LENGTH_OUT_OF_BOUNDS; 00419 00420 if (current_type == DBUS_TYPE_OBJECT_PATH) 00421 { 00422 DBusString str; 00423 _dbus_string_init_const_len (&str, p, claimed_len); 00424 if (!_dbus_validate_path (&str, 0, 00425 _dbus_string_get_length (&str))) 00426 return DBUS_INVALID_BAD_PATH; 00427 00428 p += claimed_len; 00429 } 00430 else if (current_type == DBUS_TYPE_STRING) 00431 { 00432 DBusString str; 00433 _dbus_string_init_const_len (&str, p, claimed_len); 00434 if (!_dbus_string_validate_utf8 (&str, 0, 00435 _dbus_string_get_length (&str))) 00436 return DBUS_INVALID_BAD_UTF8_IN_STRING; 00437 00438 p += claimed_len; 00439 } 00440 else if (current_type == DBUS_TYPE_ARRAY && claimed_len > 0) 00441 { 00442 DBusTypeReader sub; 00443 DBusValidity validity; 00444 const unsigned char *array_end; 00445 int array_elem_type; 00446 00447 if (claimed_len > DBUS_MAXIMUM_ARRAY_LENGTH) 00448 return DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM; 00449 00450 /* Remember that the reader is types only, so we can't 00451 * use it to iterate over elements. It stays the same 00452 * for all elements. 00453 */ 00454 _dbus_type_reader_recurse (reader, &sub); 00455 00456 array_end = p + claimed_len; 00457 00458 array_elem_type = _dbus_type_reader_get_element_type (reader); 00459 00460 /* avoid recursive call to validate_body_helper if this is an array 00461 * of fixed-size elements 00462 */ 00463 if (dbus_type_is_fixed (array_elem_type)) 00464 { 00465 /* bools need to be handled differently, because they can 00466 * have an invalid value 00467 */ 00468 if (array_elem_type == DBUS_TYPE_BOOLEAN) 00469 { 00470 dbus_uint32_t v; 00471 alignment = _dbus_type_get_alignment (array_elem_type); 00472 00473 while (p < array_end) 00474 { 00475 v = _dbus_unpack_uint32 (byte_order, p); 00476 00477 if (!(v == 0 || v == 1)) 00478 return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE; 00479 00480 p += alignment; 00481 } 00482 } 00483 00484 else 00485 { 00486 p = array_end; 00487 } 00488 } 00489 00490 else 00491 { 00492 while (p < array_end) 00493 { 00494 validity = validate_body_helper (&sub, byte_order, FALSE, 00495 total_depth + 1, 00496 p, end, &p); 00497 if (validity != DBUS_VALID) 00498 return validity; 00499 } 00500 } 00501 00502 if (p != array_end) 00503 return DBUS_INVALID_ARRAY_LENGTH_INCORRECT; 00504 } 00505 00506 /* check nul termination */ 00507 if (current_type != DBUS_TYPE_ARRAY) 00508 { 00509 if (p == end) 00510 return DBUS_INVALID_NOT_ENOUGH_DATA; 00511 00512 if (*p != '\0') 00513 return DBUS_INVALID_STRING_MISSING_NUL; 00514 ++p; 00515 } 00516 } 00517 break; 00518 00519 case DBUS_TYPE_SIGNATURE: 00520 { 00521 dbus_uint32_t claimed_len; 00522 DBusString str; 00523 DBusValidity validity; 00524 00525 claimed_len = *p; 00526 ++p; 00527 00528 /* 1 is for nul termination */ 00529 if (claimed_len + 1 > (unsigned long) (end - p)) 00530 return DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS; 00531 00532 _dbus_string_init_const_len (&str, p, claimed_len); 00533 validity = 00534 _dbus_validate_signature_with_reason (&str, 0, 00535 _dbus_string_get_length (&str)); 00536 00537 if (validity != DBUS_VALID) 00538 return validity; 00539 00540 p += claimed_len; 00541 00542 _dbus_assert (p < end); 00543 if (*p != DBUS_TYPE_INVALID) 00544 return DBUS_INVALID_SIGNATURE_MISSING_NUL; 00545 00546 ++p; 00547 00548 _dbus_verbose ("p = %p end = %p claimed_len %u\n", p, end, claimed_len); 00549 } 00550 break; 00551 00552 case DBUS_TYPE_VARIANT: 00553 { 00554 /* 1 byte sig len, sig typecodes, align to 00555 * contained-type-boundary, values. 00556 */ 00557 00558 /* In addition to normal signature validation, we need to be sure 00559 * the signature contains only a single (possibly container) type. 00560 */ 00561 dbus_uint32_t claimed_len; 00562 DBusString sig; 00563 DBusTypeReader sub; 00564 DBusValidity validity; 00565 int contained_alignment; 00566 int contained_type; 00567 DBusValidity reason; 00568 00569 claimed_len = *p; 00570 ++p; 00571 00572 /* + 1 for nul */ 00573 if (claimed_len + 1 > (unsigned long) (end - p)) 00574 return DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS; 00575 00576 _dbus_string_init_const_len (&sig, p, claimed_len); 00577 reason = _dbus_validate_signature_with_reason (&sig, 0, 00578 _dbus_string_get_length (&sig)); 00579 if (!(reason == DBUS_VALID)) 00580 { 00581 if (reason == DBUS_VALIDITY_UNKNOWN_OOM_ERROR) 00582 return reason; 00583 else 00584 return DBUS_INVALID_VARIANT_SIGNATURE_BAD; 00585 } 00586 00587 p += claimed_len; 00588 00589 if (*p != DBUS_TYPE_INVALID) 00590 return DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL; 00591 ++p; 00592 00593 contained_type = _dbus_first_type_in_signature (&sig, 0); 00594 if (contained_type == DBUS_TYPE_INVALID) 00595 return DBUS_INVALID_VARIANT_SIGNATURE_EMPTY; 00596 00597 contained_alignment = _dbus_type_get_alignment (contained_type); 00598 00599 a = _DBUS_ALIGN_ADDRESS (p, contained_alignment); 00600 if (a > end) 00601 return DBUS_INVALID_NOT_ENOUGH_DATA; 00602 while (p != a) 00603 { 00604 if (*p != '\0') 00605 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 00606 ++p; 00607 } 00608 00609 _dbus_type_reader_init_types_only (&sub, &sig, 0); 00610 00611 _dbus_assert (_dbus_type_reader_get_current_type (&sub) != DBUS_TYPE_INVALID); 00612 00613 validity = validate_body_helper (&sub, byte_order, FALSE, 00614 total_depth + 1, 00615 p, end, &p); 00616 if (validity != DBUS_VALID) 00617 return validity; 00618 00619 if (_dbus_type_reader_next (&sub)) 00620 return DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES; 00621 00622 _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_INVALID); 00623 } 00624 break; 00625 00626 case DBUS_TYPE_DICT_ENTRY: 00627 case DBUS_TYPE_STRUCT: 00628 { 00629 DBusTypeReader sub; 00630 DBusValidity validity; 00631 00632 a = _DBUS_ALIGN_ADDRESS (p, 8); 00633 if (a > end) 00634 return DBUS_INVALID_NOT_ENOUGH_DATA; 00635 while (p != a) 00636 { 00637 if (*p != '\0') 00638 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 00639 ++p; 00640 } 00641 00642 _dbus_type_reader_recurse (reader, &sub); 00643 00644 validity = validate_body_helper (&sub, byte_order, TRUE, 00645 total_depth + 1, 00646 p, end, &p); 00647 if (validity != DBUS_VALID) 00648 return validity; 00649 } 00650 break; 00651 00652 default: 00653 _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature"); 00654 break; 00655 } 00656 00657 #if 0 00658 _dbus_verbose (" validated value of type %s type reader %p type_pos %d p %p end %p %d remain\n", 00659 _dbus_type_to_string (current_type), reader, reader->type_pos, p, end, 00660 (int) (end - p)); 00661 #endif 00662 00663 if (p > end) 00664 { 00665 _dbus_verbose ("not enough data!!! p = %p end = %p end-p = %d\n", 00666 p, end, (int) (end - p)); 00667 return DBUS_INVALID_NOT_ENOUGH_DATA; 00668 } 00669 00670 if (walk_reader_to_end) 00671 _dbus_type_reader_next (reader); 00672 else 00673 break; 00674 } 00675 00676 if (new_p) 00677 *new_p = p; 00678 00679 return DBUS_VALID; 00680 } 00681 00702 DBusValidity 00703 _dbus_validate_body_with_reason (const DBusString *expected_signature, 00704 int expected_signature_start, 00705 int byte_order, 00706 int *bytes_remaining, 00707 const DBusString *value_str, 00708 int value_pos, 00709 int len) 00710 { 00711 DBusTypeReader reader; 00712 const unsigned char *p; 00713 const unsigned char *end; 00714 DBusValidity validity; 00715 00716 _dbus_assert (len >= 0); 00717 _dbus_assert (value_pos >= 0); 00718 _dbus_assert (value_pos <= _dbus_string_get_length (value_str) - len); 00719 00720 _dbus_verbose ("validating body from pos %d len %d sig '%s'\n", 00721 value_pos, len, _dbus_string_get_const_data_len (expected_signature, 00722 expected_signature_start, 00723 0)); 00724 00725 _dbus_type_reader_init_types_only (&reader, 00726 expected_signature, expected_signature_start); 00727 00728 p = _dbus_string_get_const_data_len (value_str, value_pos, len); 00729 end = p + len; 00730 00731 validity = validate_body_helper (&reader, byte_order, TRUE, 0, p, end, &p); 00732 if (validity != DBUS_VALID) 00733 return validity; 00734 00735 if (bytes_remaining) 00736 { 00737 *bytes_remaining = end - p; 00738 return DBUS_VALID; 00739 } 00740 else if (p < end) 00741 return DBUS_INVALID_TOO_MUCH_DATA; 00742 else 00743 { 00744 _dbus_assert (p == end); 00745 return DBUS_VALID; 00746 } 00747 } 00748 00753 #define VALID_INITIAL_NAME_CHARACTER(c) \ 00754 ( ((c) >= 'A' && (c) <= 'Z') || \ 00755 ((c) >= 'a' && (c) <= 'z') || \ 00756 ((c) == '_') ) 00757 00762 #define VALID_NAME_CHARACTER(c) \ 00763 ( ((c) >= '0' && (c) <= '9') || \ 00764 ((c) >= 'A' && (c) <= 'Z') || \ 00765 ((c) >= 'a' && (c) <= 'z') || \ 00766 ((c) == '_') ) 00767 00784 dbus_bool_t 00785 _dbus_validate_path (const DBusString *str, 00786 int start, 00787 int len) 00788 { 00789 const unsigned char *s; 00790 const unsigned char *end; 00791 const unsigned char *last_slash; 00792 00793 _dbus_assert (start >= 0); 00794 _dbus_assert (len >= 0); 00795 _dbus_assert (start <= _dbus_string_get_length (str)); 00796 00797 if (len > _dbus_string_get_length (str) - start) 00798 return FALSE; 00799 00800 if (len == 0) 00801 return FALSE; 00802 00803 s = _dbus_string_get_const_data (str) + start; 00804 end = s + len; 00805 00806 if (*s != '/') 00807 return FALSE; 00808 last_slash = s; 00809 ++s; 00810 00811 while (s != end) 00812 { 00813 if (*s == '/') 00814 { 00815 if ((s - last_slash) < 2) 00816 return FALSE; /* no empty path components allowed */ 00817 00818 last_slash = s; 00819 } 00820 else 00821 { 00822 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 00823 return FALSE; 00824 } 00825 00826 ++s; 00827 } 00828 00829 if ((end - last_slash) < 2 && 00830 len > 1) 00831 return FALSE; /* trailing slash not allowed unless the string is "/" */ 00832 00833 return TRUE; 00834 } 00835 00836 const char * 00837 _dbus_validity_to_error_message (DBusValidity validity) 00838 { 00839 switch (validity) 00840 { 00841 case DBUS_VALIDITY_UNKNOWN_OOM_ERROR: return "Out of memory"; 00842 case DBUS_INVALID_FOR_UNKNOWN_REASON: return "Unknown reason"; 00843 case DBUS_VALID_BUT_INCOMPLETE: return "Valid but incomplete"; 00844 case DBUS_VALIDITY_UNKNOWN: return "Validity unknown"; 00845 case DBUS_VALID: return "Valid"; 00846 case DBUS_INVALID_UNKNOWN_TYPECODE: return "Unknown typecode"; 00847 case DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE: return "Missing array element type"; 00848 case DBUS_INVALID_SIGNATURE_TOO_LONG: return "Signature is too long"; 00849 case DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION: return "Exceeded maximum array recursion"; 00850 case DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION: return "Exceeded maximum struct recursion"; 00851 case DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED: return "Struct ended but not started"; 00852 case DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED: return "Struct started but not ended"; 00853 case DBUS_INVALID_STRUCT_HAS_NO_FIELDS: return "Struct has no fields"; 00854 case DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL: return "Alignment padding not null"; 00855 case DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE: return "Boolean is not zero or one"; 00856 case DBUS_INVALID_NOT_ENOUGH_DATA: return "Not enough data"; 00857 case DBUS_INVALID_TOO_MUCH_DATA: return "Too much data"; 00858 case DBUS_INVALID_BAD_BYTE_ORDER: return "Bad byte order"; 00859 case DBUS_INVALID_BAD_PROTOCOL_VERSION: return "Bad protocol version"; 00860 case DBUS_INVALID_BAD_MESSAGE_TYPE: return "Bad message type"; 00861 case DBUS_INVALID_BAD_SERIAL: return "Bad serial"; 00862 case DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH: return "Insane fields array length"; 00863 case DBUS_INVALID_INSANE_BODY_LENGTH: return "Insane body length"; 00864 case DBUS_INVALID_MESSAGE_TOO_LONG: return "Message too long"; 00865 case DBUS_INVALID_HEADER_FIELD_CODE: return "Header field code"; 00866 case DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE: return "Header field has wrong type"; 00867 case DBUS_INVALID_USES_LOCAL_INTERFACE: return "Uses local interface"; 00868 case DBUS_INVALID_USES_LOCAL_PATH: return "Uses local path"; 00869 case DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE: return "Header field appears twice"; 00870 case DBUS_INVALID_BAD_DESTINATION: return "Bad destination"; 00871 case DBUS_INVALID_BAD_INTERFACE: return "Bad interface"; 00872 case DBUS_INVALID_BAD_MEMBER: return "Bad member"; 00873 case DBUS_INVALID_BAD_ERROR_NAME: return "Bad error name"; 00874 case DBUS_INVALID_BAD_SENDER: return "Bad sender"; 00875 case DBUS_INVALID_MISSING_PATH: return "Missing path"; 00876 case DBUS_INVALID_MISSING_INTERFACE: return "Missing interface"; 00877 case DBUS_INVALID_MISSING_MEMBER: return "Missing member"; 00878 case DBUS_INVALID_MISSING_ERROR_NAME: return "Missing error name"; 00879 case DBUS_INVALID_MISSING_REPLY_SERIAL: return "Missing reply serial"; 00880 case DBUS_INVALID_LENGTH_OUT_OF_BOUNDS: return "Length out of bounds"; 00881 case DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM: return "Array length exceeds maximum"; 00882 case DBUS_INVALID_BAD_PATH: return "Bad path"; 00883 case DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS: return "Signature length out of bounds"; 00884 case DBUS_INVALID_BAD_UTF8_IN_STRING: return "Bad utf8 in string"; 00885 case DBUS_INVALID_ARRAY_LENGTH_INCORRECT: return "Array length incorrect"; 00886 case DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS: return "Variant signature length out of bounds"; 00887 case DBUS_INVALID_VARIANT_SIGNATURE_BAD: return "Variant signature bad"; 00888 case DBUS_INVALID_VARIANT_SIGNATURE_EMPTY: return "Variant signature empty"; 00889 case DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES: return "Variant signature specifies multiple values"; 00890 case DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL: return "Variant signature missing nul"; 00891 case DBUS_INVALID_STRING_MISSING_NUL: return "String missing nul"; 00892 case DBUS_INVALID_SIGNATURE_MISSING_NUL: return "Signature missing nul"; 00893 case DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION: return "Exceeded maximum dict entry recursion"; 00894 case DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED: return "Dict entry ended but not started"; 00895 case DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED: return "Dict entry started but not ended"; 00896 case DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS: return "Dict entry has no fields"; 00897 case DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD: return "Dict entry has only one field"; 00898 case DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS: return "Dict entry has too many fields"; 00899 case DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY: return "Dict entry not inside array"; 00900 case DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE: return "Dict key must be basic type"; 00901 case DBUS_INVALID_NESTED_TOO_DEEPLY: return "Variants cannot be used to create a hugely recursive tree of values"; 00902 default: 00903 return "Invalid"; 00904 } 00905 } 00906 00920 dbus_bool_t 00921 _dbus_validate_interface (const DBusString *str, 00922 int start, 00923 int len) 00924 { 00925 const unsigned char *s; 00926 const unsigned char *end; 00927 const unsigned char *iface; 00928 const unsigned char *last_dot; 00929 00930 _dbus_assert (start >= 0); 00931 _dbus_assert (len >= 0); 00932 _dbus_assert (start <= _dbus_string_get_length (str)); 00933 00934 if (len > _dbus_string_get_length (str) - start) 00935 return FALSE; 00936 00937 if (len > DBUS_MAXIMUM_NAME_LENGTH) 00938 return FALSE; 00939 00940 if (len == 0) 00941 return FALSE; 00942 00943 last_dot = NULL; 00944 iface = _dbus_string_get_const_data (str) + start; 00945 end = iface + len; 00946 s = iface; 00947 00948 /* check special cases of first char so it doesn't have to be done 00949 * in the loop. Note we know len > 0 00950 */ 00951 if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */ 00952 return FALSE; 00953 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) 00954 return FALSE; 00955 else 00956 ++s; 00957 00958 while (s != end) 00959 { 00960 if (*s == '.') 00961 { 00962 if (_DBUS_UNLIKELY ((s + 1) == end)) 00963 return FALSE; 00964 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1)))) 00965 return FALSE; 00966 last_dot = s; 00967 ++s; /* we just validated the next char, so skip two */ 00968 } 00969 else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 00970 { 00971 return FALSE; 00972 } 00973 00974 ++s; 00975 } 00976 00977 if (_DBUS_UNLIKELY (last_dot == NULL)) 00978 return FALSE; 00979 00980 return TRUE; 00981 } 00982 00996 dbus_bool_t 00997 _dbus_validate_member (const DBusString *str, 00998 int start, 00999 int len) 01000 { 01001 const unsigned char *s; 01002 const unsigned char *end; 01003 const unsigned char *member; 01004 01005 _dbus_assert (start >= 0); 01006 _dbus_assert (len >= 0); 01007 _dbus_assert (start <= _dbus_string_get_length (str)); 01008 01009 if (len > _dbus_string_get_length (str) - start) 01010 return FALSE; 01011 01012 if (len > DBUS_MAXIMUM_NAME_LENGTH) 01013 return FALSE; 01014 01015 if (len == 0) 01016 return FALSE; 01017 01018 member = _dbus_string_get_const_data (str) + start; 01019 end = member + len; 01020 s = member; 01021 01022 /* check special cases of first char so it doesn't have to be done 01023 * in the loop. Note we know len > 0 01024 */ 01025 01026 if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) 01027 return FALSE; 01028 else 01029 ++s; 01030 01031 while (s != end) 01032 { 01033 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 01034 { 01035 return FALSE; 01036 } 01037 01038 ++s; 01039 } 01040 01041 return TRUE; 01042 } 01043 01057 dbus_bool_t 01058 _dbus_validate_error_name (const DBusString *str, 01059 int start, 01060 int len) 01061 { 01062 /* Same restrictions as interface name at the moment */ 01063 return _dbus_validate_interface (str, start, len); 01064 } 01065 01070 #define VALID_INITIAL_BUS_NAME_CHARACTER(c) \ 01071 ( ((c) >= 'A' && (c) <= 'Z') || \ 01072 ((c) >= 'a' && (c) <= 'z') || \ 01073 ((c) == '_') || ((c) == '-')) 01074 01079 #define VALID_BUS_NAME_CHARACTER(c) \ 01080 ( ((c) >= '0' && (c) <= '9') || \ 01081 ((c) >= 'A' && (c) <= 'Z') || \ 01082 ((c) >= 'a' && (c) <= 'z') || \ 01083 ((c) == '_') || ((c) == '-')) 01084 01098 dbus_bool_t 01099 _dbus_validate_bus_name (const DBusString *str, 01100 int start, 01101 int len) 01102 { 01103 const unsigned char *s; 01104 const unsigned char *end; 01105 const unsigned char *iface; 01106 const unsigned char *last_dot; 01107 01108 _dbus_assert (start >= 0); 01109 _dbus_assert (len >= 0); 01110 _dbus_assert (start <= _dbus_string_get_length (str)); 01111 01112 if (len > _dbus_string_get_length (str) - start) 01113 return FALSE; 01114 01115 if (len > DBUS_MAXIMUM_NAME_LENGTH) 01116 return FALSE; 01117 01118 if (len == 0) 01119 return FALSE; 01120 01121 last_dot = NULL; 01122 iface = _dbus_string_get_const_data (str) + start; 01123 end = iface + len; 01124 s = iface; 01125 01126 /* check special cases of first char so it doesn't have to be done 01127 * in the loop. Note we know len > 0 01128 */ 01129 if (*s == ':') 01130 { 01131 /* unique name */ 01132 ++s; 01133 while (s != end) 01134 { 01135 if (*s == '.') 01136 { 01137 if (_DBUS_UNLIKELY ((s + 1) == end)) 01138 return FALSE; 01139 if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*(s + 1)))) 01140 return FALSE; 01141 ++s; /* we just validated the next char, so skip two */ 01142 } 01143 else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s))) 01144 { 01145 return FALSE; 01146 } 01147 01148 ++s; 01149 } 01150 01151 return TRUE; 01152 } 01153 else if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */ 01154 return FALSE; 01155 else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*s))) 01156 return FALSE; 01157 else 01158 ++s; 01159 01160 while (s != end) 01161 { 01162 if (*s == '.') 01163 { 01164 if (_DBUS_UNLIKELY ((s + 1) == end)) 01165 return FALSE; 01166 else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*(s + 1)))) 01167 return FALSE; 01168 last_dot = s; 01169 ++s; /* we just validated the next char, so skip two */ 01170 } 01171 else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s))) 01172 { 01173 return FALSE; 01174 } 01175 01176 ++s; 01177 } 01178 01179 if (_DBUS_UNLIKELY (last_dot == NULL)) 01180 return FALSE; 01181 01182 return TRUE; 01183 } 01184 01197 dbus_bool_t 01198 _dbus_validate_signature (const DBusString *str, 01199 int start, 01200 int len) 01201 { 01202 _dbus_assert (start >= 0); 01203 _dbus_assert (start <= _dbus_string_get_length (str)); 01204 _dbus_assert (len >= 0); 01205 01206 if (len > _dbus_string_get_length (str) - start) 01207 return FALSE; 01208 01209 return _dbus_validate_signature_with_reason (str, start, len) == DBUS_VALID; 01210 } 01211 01213 DEFINE_DBUS_NAME_CHECK(path) 01215 DEFINE_DBUS_NAME_CHECK(interface) 01217 DEFINE_DBUS_NAME_CHECK(member) 01219 DEFINE_DBUS_NAME_CHECK(error_name) 01221 DEFINE_DBUS_NAME_CHECK(bus_name) 01223 DEFINE_DBUS_NAME_CHECK(signature) 01225 DEFINE_DBUS_NAME_CHECK(utf8) 01226 01229 /* tests in dbus-marshal-validate-util.c */