dbus-marshal-validate.c revision 62e465339a306fa564b69935da494dad6e1b474a
1/* -*- mode: C; c-file-style: "gnu" -*- */ 2/* dbus-marshal-validate.c Validation routines for marshaled data 3 * 4 * Copyright (C) 2005 Red Hat, Inc. 5 * 6 * Licensed under the Academic Free License version 2.1 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 */ 23 24#include "dbus-internals.h" 25#include "dbus-marshal-validate.h" 26#include "dbus-marshal-recursive.h" 27 28/** 29 * @addtogroup DBusMarshal 30 * 31 * @{ 32 */ 33 34/** 35 * Verifies that the range of type_str from type_pos to type_end is a 36 * valid signature. If this function returns #TRUE, it will be safe 37 * to iterate over the signature with a types-only #DBusTypeReader. 38 * The range passed in should NOT include the terminating 39 * nul/DBUS_TYPE_INVALID. 40 * 41 * @param type_str the string 42 * @param type_pos where the typecodes start 43 * @param len length of typecodes 44 * @returns #DBUS_VALID if valid, reason why invalid otherwise 45 */ 46DBusValidity 47_dbus_validate_signature_with_reason (const DBusString *type_str, 48 int type_pos, 49 int len) 50{ 51 const unsigned char *p; 52 const unsigned char *end; 53 int last; 54 int struct_depth; 55 int array_depth; 56 57 _dbus_assert (type_str != NULL); 58 _dbus_assert (type_pos < _DBUS_INT_MAX - len); 59 _dbus_assert (len >= 0); 60 _dbus_assert (type_pos >= 0); 61 62 if (len > DBUS_MAXIMUM_SIGNATURE_LENGTH) 63 return DBUS_INVALID_SIGNATURE_TOO_LONG; 64 65 p = _dbus_string_get_const_data_len (type_str, type_pos, 0); 66 end = _dbus_string_get_const_data_len (type_str, type_pos + len, 0); 67 struct_depth = 0; 68 array_depth = 0; 69 last = DBUS_TYPE_INVALID; 70 71 while (p != end) 72 { 73 switch (*p) 74 { 75 case DBUS_TYPE_BYTE: 76 case DBUS_TYPE_BOOLEAN: 77 case DBUS_TYPE_INT32: 78 case DBUS_TYPE_UINT32: 79 case DBUS_TYPE_INT64: 80 case DBUS_TYPE_UINT64: 81 case DBUS_TYPE_DOUBLE: 82 case DBUS_TYPE_STRING: 83 case DBUS_TYPE_OBJECT_PATH: 84 case DBUS_TYPE_SIGNATURE: 85 case DBUS_TYPE_VARIANT: 86 break; 87 88 case DBUS_TYPE_ARRAY: 89 array_depth += 1; 90 if (array_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) 91 return DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION; 92 break; 93 94 case DBUS_STRUCT_BEGIN_CHAR: 95 struct_depth += 1; 96 97 if (struct_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) 98 return DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION; 99 break; 100 101 case DBUS_STRUCT_END_CHAR: 102 if (struct_depth == 0) 103 return DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED; 104 105 if (last == DBUS_STRUCT_BEGIN_CHAR) 106 return DBUS_INVALID_STRUCT_HAS_NO_FIELDS; 107 108 struct_depth -= 1; 109 break; 110 111 case DBUS_TYPE_STRUCT: /* doesn't appear in signatures */ 112 default: 113 return DBUS_INVALID_UNKNOWN_TYPECODE; 114 } 115 116 if (*p != DBUS_TYPE_ARRAY) 117 array_depth = 0; 118 119 last = *p; 120 ++p; 121 } 122 123 if (array_depth > 0) 124 return DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE; 125 126 if (struct_depth > 0) 127 return DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED; 128 129 return DBUS_VALID; 130} 131 132static DBusValidity 133validate_body_helper (DBusTypeReader *reader, 134 int byte_order, 135 dbus_bool_t walk_reader_to_end, 136 const unsigned char *p, 137 const unsigned char *end, 138 const unsigned char **new_p) 139{ 140 int current_type; 141 142 while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID) 143 { 144 const unsigned char *a; 145 int alignment; 146 147 _dbus_verbose (" validating value of type %s type reader %p type_pos %d p %p end %p %d remain\n", 148 _dbus_type_to_string (current_type), reader, reader->type_pos, p, end, 149 (int) (end - p)); 150 151 /* Guarantee that p has one byte to look at */ 152 if (p == end) 153 return DBUS_INVALID_NOT_ENOUGH_DATA; 154 155 switch (current_type) 156 { 157 case DBUS_TYPE_BYTE: 158 ++p; 159 break; 160 161 case DBUS_TYPE_BOOLEAN: 162 case DBUS_TYPE_INT32: 163 case DBUS_TYPE_UINT32: 164 case DBUS_TYPE_INT64: 165 case DBUS_TYPE_UINT64: 166 case DBUS_TYPE_DOUBLE: 167 alignment = _dbus_type_get_alignment (current_type); 168 a = _DBUS_ALIGN_ADDRESS (p, alignment); 169 if (a >= end) 170 return DBUS_INVALID_NOT_ENOUGH_DATA; 171 while (p != a) 172 { 173 if (*p != '\0') 174 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 175 ++p; 176 } 177 178 if (current_type == DBUS_TYPE_BOOLEAN) 179 { 180 dbus_uint32_t v = _dbus_unpack_uint32 (byte_order, 181 p); 182 if (!(v == 0 || v == 1)) 183 return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE; 184 } 185 186 p += alignment; 187 break; 188 189 case DBUS_TYPE_ARRAY: 190 case DBUS_TYPE_STRING: 191 case DBUS_TYPE_OBJECT_PATH: 192 { 193 dbus_uint32_t claimed_len; 194 195 a = _DBUS_ALIGN_ADDRESS (p, 4); 196 if (a + 4 >= end) 197 return DBUS_INVALID_NOT_ENOUGH_DATA; 198 while (p != a) 199 { 200 if (*p != '\0') 201 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 202 ++p; 203 } 204 205 claimed_len = _dbus_unpack_uint32 (byte_order, p); 206 p += 4; 207 208 if (current_type == DBUS_TYPE_ARRAY) 209 { 210 int array_elem_type = _dbus_type_reader_get_element_type (reader); 211 alignment = _dbus_type_get_alignment (array_elem_type); 212 p = _DBUS_ALIGN_ADDRESS (p, alignment); 213 } 214 215 if (claimed_len > (unsigned long) (end - p)) 216 return DBUS_INVALID_STRING_LENGTH_OUT_OF_BOUNDS; 217 218 if (current_type == DBUS_TYPE_OBJECT_PATH) 219 { 220 DBusString str; 221 _dbus_string_init_const_len (&str, p, claimed_len); 222 if (!_dbus_validate_path (&str, 0, 223 _dbus_string_get_length (&str))) 224 return DBUS_INVALID_BAD_PATH; 225 226 p += claimed_len; 227 } 228 else if (current_type == DBUS_TYPE_STRING) 229 { 230 DBusString str; 231 _dbus_string_init_const_len (&str, p, claimed_len); 232 if (!_dbus_string_validate_utf8 (&str, 0, 233 _dbus_string_get_length (&str))) 234 return DBUS_INVALID_BAD_UTF8_IN_STRING; 235 236 p += claimed_len; 237 } 238 else if (current_type == DBUS_TYPE_ARRAY && claimed_len > 0) 239 { 240 DBusTypeReader sub; 241 DBusValidity validity; 242 const unsigned char *array_end; 243 244 /* Remember that the reader is types only, so we can't 245 * use it to iterate over elements. It stays the same 246 * for all elements. 247 */ 248 _dbus_type_reader_recurse (reader, &sub); 249 250 array_end = p + claimed_len; 251 252 while (p < array_end) 253 { 254 validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p); 255 if (validity != DBUS_VALID) 256 return validity; 257 } 258 259 if (p != array_end) 260 return DBUS_INVALID_ARRAY_LENGTH_INCORRECT; 261 } 262 263 /* check nul termination */ 264 if (current_type != DBUS_TYPE_ARRAY) 265 { 266 if (p == end) 267 return DBUS_INVALID_NOT_ENOUGH_DATA; 268 269 if (*p != '\0') 270 return DBUS_INVALID_STRING_MISSING_NUL; 271 ++p; 272 } 273 } 274 break; 275 276 case DBUS_TYPE_SIGNATURE: 277 { 278 dbus_uint32_t claimed_len; 279 DBusString str; 280 281 claimed_len = *p; 282 ++p; 283 284 /* 1 is for nul termination */ 285 if (claimed_len + 1 > (unsigned long) (end - p)) 286 return DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS; 287 288 _dbus_string_init_const_len (&str, p, claimed_len); 289 if (!_dbus_validate_signature (&str, 0, 290 _dbus_string_get_length (&str))) 291 return DBUS_INVALID_BAD_SIGNATURE; 292 293 p += claimed_len; 294 295 _dbus_assert (p < end); 296 if (*p != DBUS_TYPE_INVALID) 297 return DBUS_INVALID_SIGNATURE_MISSING_NUL; 298 299 ++p; 300 301 _dbus_verbose ("p = %p end = %p claimed_len %u\n", p, end, claimed_len); 302 } 303 break; 304 305 case DBUS_TYPE_VARIANT: 306 { 307 /* 1 byte sig len, sig typecodes, align to 8-boundary, values. */ 308 /* In addition to normal signature validation, we need to be sure 309 * the signature contains only a single (possibly container) type. 310 */ 311 dbus_uint32_t claimed_len; 312 DBusString sig; 313 DBusTypeReader sub; 314 DBusValidity validity; 315 316 claimed_len = *p; 317 ++p; 318 319 /* + 1 for nul */ 320 if (claimed_len + 1 > (unsigned long) (end - p)) 321 return DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS; 322 323 _dbus_string_init_const_len (&sig, p, claimed_len); 324 if (!_dbus_validate_signature (&sig, 0, 325 _dbus_string_get_length (&sig))) 326 return DBUS_INVALID_VARIANT_SIGNATURE_BAD; 327 328 p += claimed_len; 329 330 if (*p != DBUS_TYPE_INVALID) 331 return DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL; 332 ++p; 333 334 a = _DBUS_ALIGN_ADDRESS (p, 8); 335 if (a > end) 336 return DBUS_INVALID_NOT_ENOUGH_DATA; 337 while (p != a) 338 { 339 if (*p != '\0') 340 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 341 ++p; 342 } 343 344 _dbus_type_reader_init_types_only (&sub, &sig, 0); 345 346 if (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_INVALID) 347 return DBUS_INVALID_VARIANT_SIGNATURE_EMPTY; 348 349 validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p); 350 if (validity != DBUS_VALID) 351 return validity; 352 353 if (_dbus_type_reader_next (&sub)) 354 return DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES; 355 356 _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_INVALID); 357 } 358 break; 359 360 case DBUS_TYPE_STRUCT: 361 { 362 DBusTypeReader sub; 363 DBusValidity validity; 364 365 a = _DBUS_ALIGN_ADDRESS (p, 8); 366 if (a > end) 367 return DBUS_INVALID_NOT_ENOUGH_DATA; 368 while (p != a) 369 { 370 if (*p != '\0') 371 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 372 ++p; 373 } 374 375 _dbus_type_reader_recurse (reader, &sub); 376 377 validity = validate_body_helper (&sub, byte_order, TRUE, p, end, &p); 378 if (validity != DBUS_VALID) 379 return validity; 380 } 381 break; 382 383 default: 384 _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature"); 385 break; 386 } 387 388 _dbus_verbose (" validated value of type %s type reader %p type_pos %d p %p end %p %d remain\n", 389 _dbus_type_to_string (current_type), reader, reader->type_pos, p, end, 390 (int) (end - p)); 391 392 if (p > end) 393 { 394 _dbus_verbose ("not enough data!!! p = %p end = %p end-p = %d\n", 395 p, end, (int) (end - p)); 396 return DBUS_INVALID_NOT_ENOUGH_DATA; 397 } 398 399 if (walk_reader_to_end) 400 _dbus_type_reader_next (reader); 401 else 402 break; 403 } 404 405 if (new_p) 406 *new_p = p; 407 408 return DBUS_VALID; 409} 410 411/** 412 * Verifies that the range of value_str from value_pos to value_end is 413 * a legitimate value of type expected_signature. If this function 414 * returns #TRUE, it will be safe to iterate over the values with 415 * #DBusTypeReader. The signature is assumed to be already valid. 416 * 417 * If bytes_remaining is not #NULL, then leftover bytes will be stored 418 * there and #DBUS_VALID returned. If it is #NULL, then 419 * #DBUS_INVALID_TOO_MUCH_DATA will be returned if bytes are left 420 * over. 421 * 422 * @param expected_signature the expected types in the value_str 423 * @param expected_signature_start where in expected_signature is the signature 424 * @param byte_order the byte order 425 * @param bytes_remaining place to store leftover bytes 426 * @param value_str the string containing the body 427 * @param value_pos where the values start 428 * @param len length of values after value_pos 429 * @returns #DBUS_VALID if valid, reason why invalid otherwise 430 */ 431DBusValidity 432_dbus_validate_body_with_reason (const DBusString *expected_signature, 433 int expected_signature_start, 434 int byte_order, 435 int *bytes_remaining, 436 const DBusString *value_str, 437 int value_pos, 438 int len) 439{ 440 DBusTypeReader reader; 441 const unsigned char *p; 442 const unsigned char *end; 443 DBusValidity validity; 444 445 _dbus_assert (len >= 0); 446 _dbus_assert (value_pos >= 0); 447 _dbus_assert (value_pos <= _dbus_string_get_length (value_str) - len); 448 449 _dbus_verbose ("validating body from pos %d len %d sig '%s'\n", 450 value_pos, len, _dbus_string_get_const_data_len (expected_signature, 451 expected_signature_start, 452 0)); 453 454 _dbus_type_reader_init_types_only (&reader, 455 expected_signature, expected_signature_start); 456 457 p = _dbus_string_get_const_data_len (value_str, value_pos, len); 458 end = p + len; 459 460 validity = validate_body_helper (&reader, byte_order, TRUE, p, end, &p); 461 if (validity != DBUS_VALID) 462 return validity; 463 464 if (p < end) 465 { 466 if (bytes_remaining) 467 *bytes_remaining = end - p; 468 else 469 return DBUS_INVALID_TOO_MUCH_DATA; 470 } 471 472 return DBUS_VALID; 473} 474 475/** 476 * Checks that the given range of the string is a valid object path 477 * name in the D-BUS protocol. Part of the validation ensures that 478 * the object path contains only ASCII. 479 * 480 * @todo this is inconsistent with most of DBusString in that 481 * it allows a start,len range that extends past the string end. 482 * 483 * @todo change spec to disallow more things, such as spaces in the 484 * path name 485 * 486 * @param str the string 487 * @param start first byte index to check 488 * @param len number of bytes to check 489 * @returns #TRUE if the byte range exists and is a valid name 490 */ 491dbus_bool_t 492_dbus_validate_path (const DBusString *str, 493 int start, 494 int len) 495{ 496 const unsigned char *s; 497 const unsigned char *end; 498 const unsigned char *last_slash; 499 500 _dbus_assert (start >= 0); 501 _dbus_assert (len >= 0); 502 _dbus_assert (start <= _dbus_string_get_length (str)); 503 504 if (len > _dbus_string_get_length (str) - start) 505 return FALSE; 506 507 if (len == 0) 508 return FALSE; 509 510 s = _dbus_string_get_const_data (str) + start; 511 end = s + len; 512 513 if (*s != '/') 514 return FALSE; 515 last_slash = s; 516 ++s; 517 518 while (s != end) 519 { 520 if (*s == '/') 521 { 522 if ((s - last_slash) < 2) 523 return FALSE; /* no empty path components allowed */ 524 525 last_slash = s; 526 } 527 else 528 { 529 if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s))) 530 return FALSE; 531 } 532 533 ++s; 534 } 535 536 if ((end - last_slash) < 2 && 537 len > 1) 538 return FALSE; /* trailing slash not allowed unless the string is "/" */ 539 540 return TRUE; 541} 542 543/** 544 * Determine wether the given charater is valid as the first charater 545 * in a name. 546 */ 547#define VALID_INITIAL_NAME_CHARACTER(c) \ 548 ( ((c) >= 'A' && (c) <= 'Z') || \ 549 ((c) >= 'a' && (c) <= 'z') || \ 550 ((c) == '_') ) 551 552/** 553 * Determine wether the given charater is valid as a second or later 554 * character in a name 555 */ 556#define VALID_NAME_CHARACTER(c) \ 557 ( ((c) >= '0' && (c) <= '9') || \ 558 ((c) >= 'A' && (c) <= 'Z') || \ 559 ((c) >= 'a' && (c) <= 'z') || \ 560 ((c) == '_') ) 561 562/** 563 * Checks that the given range of the string is a valid interface name 564 * in the D-BUS protocol. This includes a length restriction and an 565 * ASCII subset, see the specification. 566 * 567 * @todo this is inconsistent with most of DBusString in that 568 * it allows a start,len range that extends past the string end. 569 * 570 * @param str the string 571 * @param start first byte index to check 572 * @param len number of bytes to check 573 * @returns #TRUE if the byte range exists and is a valid name 574 */ 575dbus_bool_t 576_dbus_validate_interface (const DBusString *str, 577 int start, 578 int len) 579{ 580 const unsigned char *s; 581 const unsigned char *end; 582 const unsigned char *iface; 583 const unsigned char *last_dot; 584 585 _dbus_assert (start >= 0); 586 _dbus_assert (len >= 0); 587 _dbus_assert (start <= _dbus_string_get_length (str)); 588 589 if (len > _dbus_string_get_length (str) - start) 590 return FALSE; 591 592 if (len > DBUS_MAXIMUM_NAME_LENGTH) 593 return FALSE; 594 595 if (len == 0) 596 return FALSE; 597 598 last_dot = NULL; 599 iface = _dbus_string_get_const_data (str) + start; 600 end = iface + len; 601 s = iface; 602 603 /* check special cases of first char so it doesn't have to be done 604 * in the loop. Note we know len > 0 605 */ 606 if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */ 607 return FALSE; 608 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) 609 return FALSE; 610 else 611 ++s; 612 613 while (s != end) 614 { 615 if (*s == '.') 616 { 617 if (_DBUS_UNLIKELY ((s + 1) == end)) 618 return FALSE; 619 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1)))) 620 return FALSE; 621 last_dot = s; 622 ++s; /* we just validated the next char, so skip two */ 623 } 624 else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 625 { 626 return FALSE; 627 } 628 629 ++s; 630 } 631 632 if (_DBUS_UNLIKELY (last_dot == NULL)) 633 return FALSE; 634 635 return TRUE; 636} 637 638/** 639 * Checks that the given range of the string is a valid member name 640 * in the D-BUS protocol. This includes a length restriction, etc., 641 * see the specification. 642 * 643 * @todo this is inconsistent with most of DBusString in that 644 * it allows a start,len range that extends past the string end. 645 * 646 * @param str the string 647 * @param start first byte index to check 648 * @param len number of bytes to check 649 * @returns #TRUE if the byte range exists and is a valid name 650 */ 651dbus_bool_t 652_dbus_validate_member (const DBusString *str, 653 int start, 654 int len) 655{ 656 const unsigned char *s; 657 const unsigned char *end; 658 const unsigned char *member; 659 660 _dbus_assert (start >= 0); 661 _dbus_assert (len >= 0); 662 _dbus_assert (start <= _dbus_string_get_length (str)); 663 664 if (len > _dbus_string_get_length (str) - start) 665 return FALSE; 666 667 if (len > DBUS_MAXIMUM_NAME_LENGTH) 668 return FALSE; 669 670 if (len == 0) 671 return FALSE; 672 673 member = _dbus_string_get_const_data (str) + start; 674 end = member + len; 675 s = member; 676 677 /* check special cases of first char so it doesn't have to be done 678 * in the loop. Note we know len > 0 679 */ 680 681 if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) 682 return FALSE; 683 else 684 ++s; 685 686 while (s != end) 687 { 688 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 689 { 690 return FALSE; 691 } 692 693 ++s; 694 } 695 696 return TRUE; 697} 698 699/** 700 * Checks that the given range of the string is a valid error name 701 * in the D-BUS protocol. This includes a length restriction, etc., 702 * see the specification. 703 * 704 * @todo this is inconsistent with most of DBusString in that 705 * it allows a start,len range that extends past the string end. 706 * 707 * @param str the string 708 * @param start first byte index to check 709 * @param len number of bytes to check 710 * @returns #TRUE if the byte range exists and is a valid name 711 */ 712dbus_bool_t 713_dbus_validate_error_name (const DBusString *str, 714 int start, 715 int len) 716{ 717 /* Same restrictions as interface name at the moment */ 718 return _dbus_validate_interface (str, start, len); 719} 720 721/* This assumes the first char exists and is ':' */ 722static dbus_bool_t 723_dbus_validate_base_service (const DBusString *str, 724 int start, 725 int len) 726{ 727 const unsigned char *s; 728 const unsigned char *end; 729 const unsigned char *service; 730 731 _dbus_assert (start >= 0); 732 _dbus_assert (len >= 0); 733 _dbus_assert (start <= _dbus_string_get_length (str)); 734 735 if (len > _dbus_string_get_length (str) - start) 736 return FALSE; 737 738 if (len > DBUS_MAXIMUM_NAME_LENGTH) 739 return FALSE; 740 741 _dbus_assert (len > 0); 742 743 service = _dbus_string_get_const_data (str) + start; 744 end = service + len; 745 _dbus_assert (*service == ':'); 746 s = service + 1; 747 748 while (s != end) 749 { 750 if (*s == '.') 751 { 752 if (_DBUS_UNLIKELY ((s + 1) == end)) 753 return FALSE; 754 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*(s + 1)))) 755 return FALSE; 756 ++s; /* we just validated the next char, so skip two */ 757 } 758 else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 759 { 760 return FALSE; 761 } 762 763 ++s; 764 } 765 766 return TRUE; 767} 768 769/** 770 * Checks that the given range of the string is a valid service name 771 * in the D-BUS protocol. This includes a length restriction, etc., 772 * see the specification. 773 * 774 * @todo this is inconsistent with most of DBusString in that 775 * it allows a start,len range that extends past the string end. 776 * 777 * @param str the string 778 * @param start first byte index to check 779 * @param len number of bytes to check 780 * @returns #TRUE if the byte range exists and is a valid name 781 */ 782dbus_bool_t 783_dbus_validate_service (const DBusString *str, 784 int start, 785 int len) 786{ 787 if (_DBUS_UNLIKELY (len == 0)) 788 return FALSE; 789 if (_dbus_string_get_byte (str, start) == ':') 790 return _dbus_validate_base_service (str, start, len); 791 else 792 return _dbus_validate_interface (str, start, len); 793} 794 795/** 796 * Checks that the given range of the string is a valid message type 797 * signature in the D-BUS protocol. 798 * 799 * @todo this is inconsistent with most of DBusString in that 800 * it allows a start,len range that extends past the string end. 801 * 802 * @param str the string 803 * @param start first byte index to check 804 * @param len number of bytes to check 805 * @returns #TRUE if the byte range exists and is a valid signature 806 */ 807dbus_bool_t 808_dbus_validate_signature (const DBusString *str, 809 int start, 810 int len) 811{ 812 _dbus_assert (start >= 0); 813 _dbus_assert (start <= _dbus_string_get_length (str)); 814 _dbus_assert (len >= 0); 815 816 if (len > _dbus_string_get_length (str) - start) 817 return FALSE; 818 819 return _dbus_validate_signature_with_reason (str, start, len) == DBUS_VALID; 820} 821 822/** define _dbus_check_is_valid_path() */ 823DEFINE_DBUS_NAME_CHECK(path); 824/** define _dbus_check_is_valid_interface() */ 825DEFINE_DBUS_NAME_CHECK(interface); 826/** define _dbus_check_is_valid_member() */ 827DEFINE_DBUS_NAME_CHECK(member); 828/** define _dbus_check_is_valid_error_name() */ 829DEFINE_DBUS_NAME_CHECK(error_name); 830/** define _dbus_check_is_valid_service() */ 831DEFINE_DBUS_NAME_CHECK(service); 832/** define _dbus_check_is_valid_signature() */ 833DEFINE_DBUS_NAME_CHECK(signature); 834 835/** @} */ 836 837#ifdef DBUS_BUILD_TESTS 838#include "dbus-test.h" 839#include <stdio.h> 840 841typedef struct 842{ 843 const char *data; 844 DBusValidity expected; 845} ValidityTest; 846 847static void 848run_validity_tests (const ValidityTest *tests, 849 int n_tests, 850 DBusValidity (* func) (const DBusString*,int,int)) 851{ 852 int i; 853 854 for (i = 0; i < n_tests; i++) 855 { 856 DBusString str; 857 DBusValidity v; 858 859 _dbus_string_init_const (&str, tests[i].data); 860 861 v = (*func) (&str, 0, _dbus_string_get_length (&str)); 862 863 if (v != tests[i].expected) 864 { 865 _dbus_warn ("Improper validation result %d for '%s'\n", 866 v, tests[i].data); 867 _dbus_assert_not_reached ("test failed"); 868 } 869 870 ++i; 871 } 872} 873 874static const ValidityTest signature_tests[] = { 875 { "", DBUS_VALID }, 876 { "i", DBUS_VALID }, 877 { "ai", DBUS_VALID }, 878 { "(i)", DBUS_VALID }, 879 { "q", DBUS_INVALID_UNKNOWN_TYPECODE }, 880 { "a", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE }, 881 { "aaaaaa", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE }, 882 { "ii(ii)a", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE }, 883 { "ia", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE }, 884 /* DBUS_INVALID_SIGNATURE_TOO_LONG, */ /* too hard to test this way */ 885 { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 886 DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION }, 887 { "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((ii))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))", 888 DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION }, 889 { ")", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED }, 890 { "i)", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED }, 891 { "a)", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED }, 892 { "(", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED }, 893 { "(i", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED }, 894 { "(iiiii", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED }, 895 { "(ai", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED }, 896 { "()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS }, 897 { "(())", DBUS_INVALID_STRUCT_HAS_NO_FIELDS }, 898 { "a()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS }, 899 { "i()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS }, 900 { "()i", DBUS_INVALID_STRUCT_HAS_NO_FIELDS } 901}; 902 903dbus_bool_t 904_dbus_marshal_validate_test (void) 905{ 906 DBusString str; 907 int i; 908 909 const char *valid_paths[] = { 910 "/", 911 "/foo/bar", 912 "/foo", 913 "/foo/bar/baz" 914 }; 915 const char *invalid_paths[] = { 916 "bar", 917 "bar/baz", 918 "/foo/bar/", 919 "/foo/" 920 "foo/", 921 "boo//blah", 922 "//", 923 "///", 924 "foo///blah/", 925 "Hello World", 926 "", 927 " ", 928 "foo bar" 929 }; 930 931 const char *valid_interfaces[] = { 932 "org.freedesktop.Foo", 933 "Bar.Baz", 934 "Blah.Blah.Blah.Blah.Blah", 935 "a.b", 936 "a.b.c.d.e.f.g", 937 "a0.b1.c2.d3.e4.f5.g6", 938 "abc123.foo27" 939 }; 940 const char *invalid_interfaces[] = { 941 ".", 942 "", 943 "..", 944 ".Foo.Bar", 945 "..Foo.Bar", 946 "Foo.Bar.", 947 "Foo.Bar..", 948 "Foo", 949 "9foo.bar.baz", 950 "foo.bar..baz", 951 "foo.bar...baz", 952 "foo.bar.b..blah", 953 ":", 954 ":0-1", 955 "10", 956 ":11.34324", 957 "0.0.0", 958 "0..0", 959 "foo.Bar.%", 960 "foo.Bar!!", 961 "!Foo.bar.bz", 962 "foo.$.blah", 963 "", 964 " ", 965 "foo bar" 966 }; 967 968 const char *valid_base_services[] = { 969 ":0", 970 ":a", 971 ":", 972 ":.a", 973 ":.1", 974 ":0.1", 975 ":000.2222", 976 ":.blah", 977 ":abce.freedesktop.blah" 978 }; 979 const char *invalid_base_services[] = { 980 ":-", 981 ":!", 982 ":0-10", 983 ":blah.", 984 ":blah.", 985 ":blah..org", 986 ":blah.org..", 987 ":..blah.org", 988 "", 989 " ", 990 "foo bar" 991 }; 992 993 const char *valid_members[] = { 994 "Hello", 995 "Bar", 996 "foobar", 997 "_foobar", 998 "foo89" 999 }; 1000 1001 const char *invalid_members[] = { 1002 "9Hello", 1003 "10", 1004 "1", 1005 "foo-bar", 1006 "blah.org", 1007 ".blah", 1008 "blah.", 1009 "Hello.", 1010 "!foo", 1011 "", 1012 " ", 1013 "foo bar" 1014 }; 1015 1016 const char *valid_signatures[] = { 1017 "", 1018 "sss", 1019 "i", 1020 "b" 1021 }; 1022 1023 const char *invalid_signatures[] = { 1024 " ", 1025 "not a valid signature", 1026 "123", 1027 ".", 1028 "(" 1029 }; 1030 1031 /* Signature with reason */ 1032 1033 run_validity_tests (signature_tests, _DBUS_N_ELEMENTS (signature_tests), 1034 _dbus_validate_signature_with_reason); 1035 1036 /* Path validation */ 1037 i = 0; 1038 while (i < (int) _DBUS_N_ELEMENTS (valid_paths)) 1039 { 1040 _dbus_string_init_const (&str, valid_paths[i]); 1041 1042 if (!_dbus_validate_path (&str, 0, 1043 _dbus_string_get_length (&str))) 1044 { 1045 _dbus_warn ("Path \"%s\" should have been valid\n", valid_paths[i]); 1046 _dbus_assert_not_reached ("invalid path"); 1047 } 1048 1049 ++i; 1050 } 1051 1052 i = 0; 1053 while (i < (int) _DBUS_N_ELEMENTS (invalid_paths)) 1054 { 1055 _dbus_string_init_const (&str, invalid_paths[i]); 1056 1057 if (_dbus_validate_path (&str, 0, 1058 _dbus_string_get_length (&str))) 1059 { 1060 _dbus_warn ("Path \"%s\" should have been invalid\n", invalid_paths[i]); 1061 _dbus_assert_not_reached ("valid path"); 1062 } 1063 1064 ++i; 1065 } 1066 1067 /* Interface validation */ 1068 i = 0; 1069 while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces)) 1070 { 1071 _dbus_string_init_const (&str, valid_interfaces[i]); 1072 1073 if (!_dbus_validate_interface (&str, 0, 1074 _dbus_string_get_length (&str))) 1075 { 1076 _dbus_warn ("Interface \"%s\" should have been valid\n", valid_interfaces[i]); 1077 _dbus_assert_not_reached ("invalid interface"); 1078 } 1079 1080 ++i; 1081 } 1082 1083 i = 0; 1084 while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces)) 1085 { 1086 _dbus_string_init_const (&str, invalid_interfaces[i]); 1087 1088 if (_dbus_validate_interface (&str, 0, 1089 _dbus_string_get_length (&str))) 1090 { 1091 _dbus_warn ("Interface \"%s\" should have been invalid\n", invalid_interfaces[i]); 1092 _dbus_assert_not_reached ("valid interface"); 1093 } 1094 1095 ++i; 1096 } 1097 1098 /* Service validation (check that valid interfaces are valid services, 1099 * and invalid interfaces are invalid services except if they start with ':') 1100 */ 1101 i = 0; 1102 while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces)) 1103 { 1104 _dbus_string_init_const (&str, valid_interfaces[i]); 1105 1106 if (!_dbus_validate_service (&str, 0, 1107 _dbus_string_get_length (&str))) 1108 { 1109 _dbus_warn ("Service \"%s\" should have been valid\n", valid_interfaces[i]); 1110 _dbus_assert_not_reached ("invalid service"); 1111 } 1112 1113 ++i; 1114 } 1115 1116 i = 0; 1117 while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces)) 1118 { 1119 if (invalid_interfaces[i][0] != ':') 1120 { 1121 _dbus_string_init_const (&str, invalid_interfaces[i]); 1122 1123 if (_dbus_validate_service (&str, 0, 1124 _dbus_string_get_length (&str))) 1125 { 1126 _dbus_warn ("Service \"%s\" should have been invalid\n", invalid_interfaces[i]); 1127 _dbus_assert_not_reached ("valid service"); 1128 } 1129 } 1130 1131 ++i; 1132 } 1133 1134 /* Base service validation */ 1135 i = 0; 1136 while (i < (int) _DBUS_N_ELEMENTS (valid_base_services)) 1137 { 1138 _dbus_string_init_const (&str, valid_base_services[i]); 1139 1140 if (!_dbus_validate_service (&str, 0, 1141 _dbus_string_get_length (&str))) 1142 { 1143 _dbus_warn ("Service \"%s\" should have been valid\n", valid_base_services[i]); 1144 _dbus_assert_not_reached ("invalid base service"); 1145 } 1146 1147 ++i; 1148 } 1149 1150 i = 0; 1151 while (i < (int) _DBUS_N_ELEMENTS (invalid_base_services)) 1152 { 1153 _dbus_string_init_const (&str, invalid_base_services[i]); 1154 1155 if (_dbus_validate_service (&str, 0, 1156 _dbus_string_get_length (&str))) 1157 { 1158 _dbus_warn ("Service \"%s\" should have been invalid\n", invalid_base_services[i]); 1159 _dbus_assert_not_reached ("valid base service"); 1160 } 1161 1162 ++i; 1163 } 1164 1165 1166 /* Error name validation (currently identical to interfaces) 1167 */ 1168 i = 0; 1169 while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces)) 1170 { 1171 _dbus_string_init_const (&str, valid_interfaces[i]); 1172 1173 if (!_dbus_validate_error_name (&str, 0, 1174 _dbus_string_get_length (&str))) 1175 { 1176 _dbus_warn ("Error name \"%s\" should have been valid\n", valid_interfaces[i]); 1177 _dbus_assert_not_reached ("invalid error name"); 1178 } 1179 1180 ++i; 1181 } 1182 1183 i = 0; 1184 while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces)) 1185 { 1186 if (invalid_interfaces[i][0] != ':') 1187 { 1188 _dbus_string_init_const (&str, invalid_interfaces[i]); 1189 1190 if (_dbus_validate_error_name (&str, 0, 1191 _dbus_string_get_length (&str))) 1192 { 1193 _dbus_warn ("Error name \"%s\" should have been invalid\n", invalid_interfaces[i]); 1194 _dbus_assert_not_reached ("valid error name"); 1195 } 1196 } 1197 1198 ++i; 1199 } 1200 1201 /* Member validation */ 1202 i = 0; 1203 while (i < (int) _DBUS_N_ELEMENTS (valid_members)) 1204 { 1205 _dbus_string_init_const (&str, valid_members[i]); 1206 1207 if (!_dbus_validate_member (&str, 0, 1208 _dbus_string_get_length (&str))) 1209 { 1210 _dbus_warn ("Member \"%s\" should have been valid\n", valid_members[i]); 1211 _dbus_assert_not_reached ("invalid member"); 1212 } 1213 1214 ++i; 1215 } 1216 1217 i = 0; 1218 while (i < (int) _DBUS_N_ELEMENTS (invalid_members)) 1219 { 1220 _dbus_string_init_const (&str, invalid_members[i]); 1221 1222 if (_dbus_validate_member (&str, 0, 1223 _dbus_string_get_length (&str))) 1224 { 1225 _dbus_warn ("Member \"%s\" should have been invalid\n", invalid_members[i]); 1226 _dbus_assert_not_reached ("valid member"); 1227 } 1228 1229 ++i; 1230 } 1231 1232 /* Signature validation */ 1233 i = 0; 1234 while (i < (int) _DBUS_N_ELEMENTS (valid_signatures)) 1235 { 1236 _dbus_string_init_const (&str, valid_signatures[i]); 1237 1238 if (!_dbus_validate_signature (&str, 0, 1239 _dbus_string_get_length (&str))) 1240 { 1241 _dbus_warn ("Signature \"%s\" should have been valid\n", valid_signatures[i]); 1242 _dbus_assert_not_reached ("invalid signature"); 1243 } 1244 1245 ++i; 1246 } 1247 1248 i = 0; 1249 while (i < (int) _DBUS_N_ELEMENTS (invalid_signatures)) 1250 { 1251 _dbus_string_init_const (&str, invalid_signatures[i]); 1252 1253 if (_dbus_validate_signature (&str, 0, 1254 _dbus_string_get_length (&str))) 1255 { 1256 _dbus_warn ("Signature \"%s\" should have been invalid\n", invalid_signatures[i]); 1257 _dbus_assert_not_reached ("valid signature"); 1258 } 1259 1260 ++i; 1261 } 1262 1263 /* Validate claimed length longer than real length */ 1264 _dbus_string_init_const (&str, "abc.efg"); 1265 if (_dbus_validate_service (&str, 0, 8)) 1266 _dbus_assert_not_reached ("validated too-long string"); 1267 if (_dbus_validate_interface (&str, 0, 8)) 1268 _dbus_assert_not_reached ("validated too-long string"); 1269 if (_dbus_validate_error_name (&str, 0, 8)) 1270 _dbus_assert_not_reached ("validated too-long string"); 1271 1272 _dbus_string_init_const (&str, "abc"); 1273 if (_dbus_validate_member (&str, 0, 4)) 1274 _dbus_assert_not_reached ("validated too-long string"); 1275 1276 _dbus_string_init_const (&str, "sss"); 1277 if (_dbus_validate_signature (&str, 0, 4)) 1278 _dbus_assert_not_reached ("validated too-long signature"); 1279 1280 /* Validate string exceeding max name length */ 1281 if (!_dbus_string_init (&str)) 1282 _dbus_assert_not_reached ("no memory"); 1283 1284 while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH) 1285 if (!_dbus_string_append (&str, "abc.def")) 1286 _dbus_assert_not_reached ("no memory"); 1287 1288 if (_dbus_validate_service (&str, 0, _dbus_string_get_length (&str))) 1289 _dbus_assert_not_reached ("validated overmax string"); 1290 if (_dbus_validate_interface (&str, 0, _dbus_string_get_length (&str))) 1291 _dbus_assert_not_reached ("validated overmax string"); 1292 if (_dbus_validate_error_name (&str, 0, _dbus_string_get_length (&str))) 1293 _dbus_assert_not_reached ("validated overmax string"); 1294 1295 /* overlong member */ 1296 _dbus_string_set_length (&str, 0); 1297 while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH) 1298 if (!_dbus_string_append (&str, "abc")) 1299 _dbus_assert_not_reached ("no memory"); 1300 1301 if (_dbus_validate_member (&str, 0, _dbus_string_get_length (&str))) 1302 _dbus_assert_not_reached ("validated overmax string"); 1303 1304 /* overlong base service */ 1305 _dbus_string_set_length (&str, 0); 1306 _dbus_string_append (&str, ":"); 1307 while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH) 1308 if (!_dbus_string_append (&str, "abc")) 1309 _dbus_assert_not_reached ("no memory"); 1310 1311 if (_dbus_validate_service (&str, 0, _dbus_string_get_length (&str))) 1312 _dbus_assert_not_reached ("validated overmax string"); 1313 1314 _dbus_string_free (&str); 1315 1316 return TRUE; 1317} 1318 1319#endif /* DBUS_BUILD_TESTS */ 1320