1 /* -*- mode: C; c-file-style: "gnu" -*- */ 2 /* dbus-marshal-basic.c Marshalling routines for basic (primitive) types 3 * 4 * Copyright (C) 2002 CodeFactory AB 5 * Copyright (C) 2003, 2004, 2005 Red Hat, Inc. 6 * 7 * Licensed under the Academic Free License version 2.1 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * 23 */ 24 25 #include "dbus-internals.h" 26 #include "dbus-marshal-basic.h" 27 #include "dbus-signature.h" 28 29 #include <string.h> 30 31 /** 32 * @defgroup DBusMarshal marshaling and unmarshaling 33 * @ingroup DBusInternals 34 * @brief functions to marshal/unmarshal data from the wire 35 * 36 * Types and functions related to converting primitive data types from 37 * wire format to native machine format, and vice versa. 38 * 39 * A signature is just a string with multiple types one after the other. 40 * for example a type is "i" or "(ii)", a signature is "i(ii)" 41 * where i is int and (ii) is struct { int; int; } 42 * 43 * @{ 44 */ 45 46 static void 47 pack_2_octets (dbus_uint16_t value, 48 int byte_order, 49 unsigned char *data) 50 { 51 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data); 52 53 if ((byte_order) == DBUS_LITTLE_ENDIAN) 54 *((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_LE (value); 55 else 56 *((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_BE (value); 57 } 58 59 static void 60 pack_4_octets (dbus_uint32_t value, 61 int byte_order, 62 unsigned char *data) 63 { 64 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data); 65 66 if ((byte_order) == DBUS_LITTLE_ENDIAN) 67 *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value); 68 else 69 *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value); 70 } 71 72 static void 73 pack_8_octets (DBusBasicValue value, 74 int byte_order, 75 unsigned char *data) 76 { 77 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data); 78 79 #ifdef DBUS_HAVE_INT64 80 if ((byte_order) == DBUS_LITTLE_ENDIAN) 81 *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u64); 82 else 83 *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u64); 84 #else 85 *(DBus8ByteStruct*)data = value.u64; 86 swap_8_octets ((DBusBasicValue*)data, byte_order); 87 #endif 88 } 89 90 /** 91 * Packs a 32 bit unsigned integer into a data pointer. 92 * 93 * @param value the value 94 * @param byte_order the byte order to use 95 * @param data the data pointer 96 */ 97 void 98 _dbus_pack_uint32 (dbus_uint32_t value, 99 int byte_order, 100 unsigned char *data) 101 { 102 pack_4_octets (value, byte_order, data); 103 } 104 105 #ifndef DBUS_HAVE_INT64 106 /* from ORBit */ 107 static void 108 swap_bytes (unsigned char *data, 109 unsigned int len) 110 { 111 unsigned char *p1 = data; 112 unsigned char *p2 = data + len - 1; 113 114 while (p1 < p2) 115 { 116 unsigned char tmp = *p1; 117 *p1 = *p2; 118 *p2 = tmp; 119 120 --p2; 121 ++p1; 122 } 123 } 124 #endif /* !DBUS_HAVE_INT64 */ 125 126 static void 127 swap_8_octets (DBusBasicValue *value, 128 int byte_order) 129 { 130 if (byte_order != DBUS_COMPILER_BYTE_ORDER) 131 { 132 #ifdef DBUS_HAVE_INT64 133 value->u64 = DBUS_UINT64_SWAP_LE_BE (value->u64); 134 #else 135 swap_bytes ((unsigned char *)value, 8); 136 #endif 137 } 138 } 139 140 #if 0 141 static DBusBasicValue 142 unpack_8_octets (int byte_order, 143 const unsigned char *data) 144 { 145 DBusBasicValue r; 146 147 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data); 148 _dbus_assert (sizeof (r) == 8); 149 150 #ifdef DBUS_HAVE_INT64 151 if (byte_order == DBUS_LITTLE_ENDIAN) 152 r.u64 = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data); 153 else 154 r.u64 = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data); 155 #else 156 r.u64 = *(DBus8ByteStruct*)data; 157 swap_8_octets (&r, byte_order); 158 #endif 159 160 return r; 161 } 162 #endif 163 164 #ifndef _dbus_unpack_uint16 165 /** 166 * Unpacks a 16 bit unsigned integer from a data pointer 167 * 168 * @param byte_order The byte order to use 169 * @param data the data pointer 170 * @returns the integer 171 */ 172 dbus_uint16_t 173 _dbus_unpack_uint16 (int byte_order, 174 const unsigned char *data) 175 { 176 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data); 177 178 if (byte_order == DBUS_LITTLE_ENDIAN) 179 return DBUS_UINT16_FROM_LE (*(dbus_uint16_t*)data); 180 else 181 return DBUS_UINT16_FROM_BE (*(dbus_uint16_t*)data); 182 } 183 #endif /* _dbus_unpack_uint16 */ 184 185 #ifndef _dbus_unpack_uint32 186 /** 187 * Unpacks a 32 bit unsigned integer from a data pointer 188 * 189 * @param byte_order The byte order to use 190 * @param data the data pointer 191 * @returns the integer 192 */ 193 dbus_uint32_t 194 _dbus_unpack_uint32 (int byte_order, 195 const unsigned char *data) 196 { 197 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data); 198 199 if (byte_order == DBUS_LITTLE_ENDIAN) 200 return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data); 201 else 202 return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data); 203 } 204 #endif /* _dbus_unpack_uint32 */ 205 206 static void 207 set_2_octets (DBusString *str, 208 int offset, 209 dbus_uint16_t value, 210 int byte_order) 211 { 212 char *data; 213 214 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || 215 byte_order == DBUS_BIG_ENDIAN); 216 217 data = _dbus_string_get_data_len (str, offset, 2); 218 219 pack_2_octets (value, byte_order, data); 220 } 221 222 static void 223 set_4_octets (DBusString *str, 224 int offset, 225 dbus_uint32_t value, 226 int byte_order) 227 { 228 char *data; 229 230 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || 231 byte_order == DBUS_BIG_ENDIAN); 232 233 data = _dbus_string_get_data_len (str, offset, 4); 234 235 pack_4_octets (value, byte_order, data); 236 } 237 238 static void 239 set_8_octets (DBusString *str, 240 int offset, 241 DBusBasicValue value, 242 int byte_order) 243 { 244 char *data; 245 246 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || 247 byte_order == DBUS_BIG_ENDIAN); 248 249 data = _dbus_string_get_data_len (str, offset, 8); 250 251 pack_8_octets (value, byte_order, data); 252 } 253 254 /** 255 * Sets the 4 bytes at the given offset to a marshaled unsigned 256 * integer, replacing anything found there previously. 257 * 258 * @param str the string to write the marshalled int to 259 * @param pos the byte offset where int should be written 260 * @param value the value 261 * @param byte_order the byte order to use 262 * 263 */ 264 void 265 _dbus_marshal_set_uint32 (DBusString *str, 266 int pos, 267 dbus_uint32_t value, 268 int byte_order) 269 { 270 set_4_octets (str, pos, value, byte_order); 271 } 272 273 /** 274 * Sets the existing marshaled string at the given offset with 275 * a new marshaled string. The given offset must point to 276 * an existing string or the wrong length will be deleted 277 * and replaced with the new string. 278 * 279 * Note: no attempt is made by this function to re-align 280 * any data which has been already marshalled after this 281 * string. Use with caution. 282 * 283 * @param str the string to write the marshalled string to 284 * @param pos the position of the marshaled string length 285 * @param value the value 286 * @param byte_order the byte order to use 287 * @param old_end_pos place to store byte after the nul byte of the old value 288 * @param new_end_pos place to store byte after the nul byte of the new value 289 * @returns #TRUE on success, #FALSE if no memory 290 * 291 */ 292 static dbus_bool_t 293 set_string (DBusString *str, 294 int pos, 295 const char *value, 296 int byte_order, 297 int *old_end_pos, 298 int *new_end_pos) 299 { 300 int old_len, new_len; 301 DBusString dstr; 302 303 _dbus_string_init_const (&dstr, value); 304 305 _dbus_assert (_DBUS_ALIGN_VALUE (pos, 4) == (unsigned) pos); 306 old_len = _dbus_unpack_uint32 (byte_order, 307 _dbus_string_get_const_data_len (str, pos, 4)); 308 309 new_len = _dbus_string_get_length (&dstr); 310 311 if (!_dbus_string_replace_len (&dstr, 0, new_len, 312 str, pos + 4, old_len)) 313 return FALSE; 314 315 _dbus_marshal_set_uint32 (str, pos, new_len, byte_order); 316 317 if (old_end_pos) 318 *old_end_pos = pos + 4 + old_len + 1; 319 if (new_end_pos) 320 *new_end_pos = pos + 4 + new_len + 1; 321 322 return TRUE; 323 } 324 325 /** 326 * Sets the existing marshaled signature at the given offset to a new 327 * marshaled signature. Same basic ideas as set_string(). 328 * 329 * @param str the string to write the marshalled signature to 330 * @param pos the position of the marshaled signature length 331 * @param value the value 332 * @param byte_order the byte order to use 333 * @param old_end_pos place to store byte after the nul byte of the old value 334 * @param new_end_pos place to store byte after the nul byte of the new value 335 * @returns #TRUE on success, #FALSE if no memory 336 * 337 */ 338 static dbus_bool_t 339 set_signature (DBusString *str, 340 int pos, 341 const char *value, 342 int byte_order, 343 int *old_end_pos, 344 int *new_end_pos) 345 { 346 int old_len, new_len; 347 DBusString dstr; 348 349 _dbus_string_init_const (&dstr, value); 350 351 old_len = _dbus_string_get_byte (str, pos); 352 new_len = _dbus_string_get_length (&dstr); 353 354 if (!_dbus_string_replace_len (&dstr, 0, new_len, 355 str, pos + 1, old_len)) 356 return FALSE; 357 358 _dbus_string_set_byte (str, pos, new_len); 359 360 if (old_end_pos) 361 *old_end_pos = pos + 1 + old_len + 1; 362 if (new_end_pos) 363 *new_end_pos = pos + 1 + new_len + 1; 364 365 return TRUE; 366 } 367 368 /** 369 * Sets an existing basic type value to a new value. 370 * Arguments work the same way as _dbus_marshal_basic_type(). 371 * 372 * @param str the string 373 * @param pos location of the current value 374 * @param type the type of the current and new values 375 * @param value the address of the new value 376 * @param byte_order byte order for marshaling 377 * @param old_end_pos location to store end position of the old value, or #NULL 378 * @param new_end_pos location to store end position of the new value, or #NULL 379 * @returns #FALSE if no memory 380 */ 381 dbus_bool_t 382 _dbus_marshal_set_basic (DBusString *str, 383 int pos, 384 int type, 385 const void *value, 386 int byte_order, 387 int *old_end_pos, 388 int *new_end_pos) 389 { 390 const DBusBasicValue *vp; 391 392 vp = value; 393 394 switch (type) 395 { 396 case DBUS_TYPE_BYTE: 397 _dbus_string_set_byte (str, pos, vp->byt); 398 if (old_end_pos) 399 *old_end_pos = pos + 1; 400 if (new_end_pos) 401 *new_end_pos = pos + 1; 402 return TRUE; 403 break; 404 case DBUS_TYPE_INT16: 405 case DBUS_TYPE_UINT16: 406 pos = _DBUS_ALIGN_VALUE (pos, 2); 407 set_2_octets (str, pos, vp->u16, byte_order); 408 if (old_end_pos) 409 *old_end_pos = pos + 2; 410 if (new_end_pos) 411 *new_end_pos = pos + 2; 412 return TRUE; 413 break; 414 case DBUS_TYPE_BOOLEAN: 415 case DBUS_TYPE_INT32: 416 case DBUS_TYPE_UINT32: 417 pos = _DBUS_ALIGN_VALUE (pos, 4); 418 set_4_octets (str, pos, vp->u32, byte_order); 419 if (old_end_pos) 420 *old_end_pos = pos + 4; 421 if (new_end_pos) 422 *new_end_pos = pos + 4; 423 return TRUE; 424 break; 425 case DBUS_TYPE_INT64: 426 case DBUS_TYPE_UINT64: 427 case DBUS_TYPE_DOUBLE: 428 pos = _DBUS_ALIGN_VALUE (pos, 8); 429 set_8_octets (str, pos, *vp, byte_order); 430 if (old_end_pos) 431 *old_end_pos = pos + 8; 432 if (new_end_pos) 433 *new_end_pos = pos + 8; 434 return TRUE; 435 break; 436 case DBUS_TYPE_STRING: 437 case DBUS_TYPE_OBJECT_PATH: 438 pos = _DBUS_ALIGN_VALUE (pos, 4); 439 _dbus_assert (vp->str != NULL); 440 return set_string (str, pos, vp->str, byte_order, 441 old_end_pos, new_end_pos); 442 break; 443 case DBUS_TYPE_SIGNATURE: 444 _dbus_assert (vp->str != NULL); 445 return set_signature (str, pos, vp->str, byte_order, 446 old_end_pos, new_end_pos); 447 break; 448 default: 449 _dbus_assert_not_reached ("not a basic type"); 450 return FALSE; 451 break; 452 } 453 } 454 455 /** 456 * Convenience function to demarshal a 32 bit unsigned integer. 457 * 458 * @param str the string containing the data 459 * @param byte_order the byte order 460 * @param pos the position in the string 461 * @param new_pos the new position of the string 462 * @returns the demarshaled integer. 463 */ 464 dbus_uint32_t 465 _dbus_marshal_read_uint32 (const DBusString *str, 466 int pos, 467 int byte_order, 468 int *new_pos) 469 { 470 pos = _DBUS_ALIGN_VALUE (pos, 4); 471 472 if (new_pos) 473 *new_pos = pos + 4; 474 475 _dbus_assert (pos + 4 <= _dbus_string_get_length (str)); 476 477 return _dbus_unpack_uint32 (byte_order, 478 _dbus_string_get_const_data (str) + pos); 479 } 480 481 /** 482 * Demarshals a basic-typed value. The "value" pointer is always 483 * the address of a variable of the basic type. So e.g. 484 * if the basic type is "double" then the pointer is 485 * a double*, and if it's "char*" then the pointer is 486 * a "char**". 487 * 488 * A value of type #DBusBasicValue is guaranteed to be large enough to 489 * hold any of the types that may be returned, which is handy if you 490 * are trying to do things generically. For example you can pass 491 * a DBusBasicValue* in to this function, and then pass the same 492 * DBusBasicValue* in to _dbus_marshal_basic_type() in order to 493 * move a value from one place to another. 494 * 495 * @param str the string containing the data 496 * @param pos position in the string 497 * @param type type of value to demarshal 498 * @param value pointer to return value data 499 * @param byte_order the byte order 500 * @param new_pos pointer to update with new position, or #NULL 501 **/ 502 void 503 _dbus_marshal_read_basic (const DBusString *str, 504 int pos, 505 int type, 506 void *value, 507 int byte_order, 508 int *new_pos) 509 { 510 const char *str_data; 511 DBusBasicValue *vp; 512 513 _dbus_assert (dbus_type_is_basic (type)); 514 515 str_data = _dbus_string_get_const_data (str); 516 vp = value; 517 518 switch (type) 519 { 520 case DBUS_TYPE_BYTE: 521 vp->byt = _dbus_string_get_byte (str, pos); 522 (pos)++; 523 break; 524 case DBUS_TYPE_INT16: 525 case DBUS_TYPE_UINT16: 526 pos = _DBUS_ALIGN_VALUE (pos, 2); 527 vp->u16 = *(dbus_uint16_t *)(str_data + pos); 528 if (byte_order != DBUS_COMPILER_BYTE_ORDER) 529 vp->u16 = DBUS_UINT16_SWAP_LE_BE (vp->u16); 530 pos += 2; 531 break; 532 case DBUS_TYPE_INT32: 533 case DBUS_TYPE_UINT32: 534 case DBUS_TYPE_BOOLEAN: 535 pos = _DBUS_ALIGN_VALUE (pos, 4); 536 vp->u32 = *(dbus_uint32_t *)(str_data + pos); 537 if (byte_order != DBUS_COMPILER_BYTE_ORDER) 538 vp->u32 = DBUS_UINT32_SWAP_LE_BE (vp->u32); 539 pos += 4; 540 break; 541 case DBUS_TYPE_INT64: 542 case DBUS_TYPE_UINT64: 543 case DBUS_TYPE_DOUBLE: 544 pos = _DBUS_ALIGN_VALUE (pos, 8); 545 #ifdef DBUS_HAVE_INT64 546 if (byte_order != DBUS_COMPILER_BYTE_ORDER) 547 vp->u64 = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t*)(str_data + pos)); 548 else 549 vp->u64 = *(dbus_uint64_t*)(str_data + pos); 550 #else 551 vp->u64 = *(DBus8ByteStruct*) (str_data + pos); 552 swap_8_octets (vp, byte_order); 553 #endif 554 pos += 8; 555 break; 556 case DBUS_TYPE_STRING: 557 case DBUS_TYPE_OBJECT_PATH: 558 { 559 int len; 560 561 len = _dbus_marshal_read_uint32 (str, pos, byte_order, &pos); 562 563 vp->str = (char*) str_data + pos; 564 565 pos += len + 1; /* length plus nul */ 566 } 567 break; 568 case DBUS_TYPE_SIGNATURE: 569 { 570 int len; 571 572 len = _dbus_string_get_byte (str, pos); 573 pos += 1; 574 575 vp->str = (char*) str_data + pos; 576 577 pos += len + 1; /* length plus nul */ 578 } 579 break; 580 default: 581 _dbus_warn_check_failed ("type %s %d not a basic type\n", 582 _dbus_type_to_string (type), type); 583 _dbus_assert_not_reached ("not a basic type"); 584 break; 585 } 586 587 if (new_pos) 588 *new_pos = pos; 589 } 590 591 static dbus_bool_t 592 marshal_2_octets (DBusString *str, 593 int insert_at, 594 dbus_uint16_t value, 595 int byte_order, 596 int *pos_after) 597 { 598 dbus_bool_t retval; 599 int orig_len; 600 601 _dbus_assert (sizeof (value) == 2); 602 603 if (byte_order != DBUS_COMPILER_BYTE_ORDER) 604 value = DBUS_UINT16_SWAP_LE_BE (value); 605 606 orig_len = _dbus_string_get_length (str); 607 608 retval = _dbus_string_insert_2_aligned (str, insert_at, 609 (const unsigned char *)&value); 610 611 if (pos_after) 612 { 613 *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len); 614 _dbus_assert (*pos_after <= _dbus_string_get_length (str)); 615 } 616 617 return retval; 618 } 619 620 static dbus_bool_t 621 marshal_4_octets (DBusString *str, 622 int insert_at, 623 dbus_uint32_t value, 624 int byte_order, 625 int *pos_after) 626 { 627 dbus_bool_t retval; 628 int orig_len; 629 630 _dbus_assert (sizeof (value) == 4); 631 632 if (byte_order != DBUS_COMPILER_BYTE_ORDER) 633 value = DBUS_UINT32_SWAP_LE_BE (value); 634 635 orig_len = _dbus_string_get_length (str); 636 637 retval = _dbus_string_insert_4_aligned (str, insert_at, 638 (const unsigned char *)&value); 639 640 if (pos_after) 641 { 642 *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len); 643 _dbus_assert (*pos_after <= _dbus_string_get_length (str)); 644 } 645 646 return retval; 647 } 648 649 static dbus_bool_t 650 marshal_8_octets (DBusString *str, 651 int insert_at, 652 DBusBasicValue value, 653 int byte_order, 654 int *pos_after) 655 { 656 dbus_bool_t retval; 657 int orig_len; 658 659 _dbus_assert (sizeof (value) == 8); 660 661 swap_8_octets (&value, byte_order); 662 663 orig_len = _dbus_string_get_length (str); 664 665 retval = _dbus_string_insert_8_aligned (str, insert_at, 666 (const unsigned char *)&value); 667 668 if (pos_after) 669 *pos_after = insert_at + _dbus_string_get_length (str) - orig_len; 670 671 return retval; 672 } 673 674 enum 675 { 676 MARSHAL_AS_STRING, 677 MARSHAL_AS_SIGNATURE, 678 MARSHAL_AS_BYTE_ARRAY 679 }; 680 681 static dbus_bool_t 682 marshal_len_followed_by_bytes (int marshal_as, 683 DBusString *str, 684 int insert_at, 685 const unsigned char *value, 686 int data_len, /* doesn't include nul if any */ 687 int byte_order, 688 int *pos_after) 689 { 690 int pos; 691 DBusString value_str; 692 int value_len; 693 694 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || byte_order == DBUS_BIG_ENDIAN); 695 if (insert_at > _dbus_string_get_length (str)) 696 _dbus_warn ("insert_at = %d string len = %d data_len = %d\n", 697 insert_at, _dbus_string_get_length (str), data_len); 698 699 if (marshal_as == MARSHAL_AS_BYTE_ARRAY) 700 value_len = data_len; 701 else 702 value_len = data_len + 1; /* value has a nul */ 703 704 _dbus_string_init_const_len (&value_str, value, value_len); 705 706 pos = insert_at; 707 708 if (marshal_as == MARSHAL_AS_SIGNATURE) 709 { 710 _dbus_assert (data_len <= DBUS_MAXIMUM_SIGNATURE_LENGTH); 711 _dbus_assert (data_len <= 255); /* same as max sig len right now */ 712 713 if (!_dbus_string_insert_byte (str, pos, data_len)) 714 goto oom; 715 716 pos += 1; 717 } 718 else 719 { 720 if (!marshal_4_octets (str, pos, data_len, 721 byte_order, &pos)) 722 goto oom; 723 } 724 725 if (!_dbus_string_copy_len (&value_str, 0, value_len, 726 str, pos)) 727 goto oom; 728 729 #if 0 730 /* too expensive */ 731 _dbus_assert (_dbus_string_equal_substring (&value_str, 0, value_len, 732 str, pos)); 733 _dbus_verbose_bytes_of_string (str, pos, value_len); 734 #endif 735 736 pos += value_len; 737 738 if (pos_after) 739 *pos_after = pos; 740 741 return TRUE; 742 743 oom: 744 /* Delete what we've inserted */ 745 _dbus_string_delete (str, insert_at, pos - insert_at); 746 747 return FALSE; 748 } 749 750 static dbus_bool_t 751 marshal_string (DBusString *str, 752 int insert_at, 753 const char *value, 754 int byte_order, 755 int *pos_after) 756 { 757 return marshal_len_followed_by_bytes (MARSHAL_AS_STRING, 758 str, insert_at, value, 759 strlen (value), 760 byte_order, pos_after); 761 } 762 763 static dbus_bool_t 764 marshal_signature (DBusString *str, 765 int insert_at, 766 const char *value, 767 int *pos_after) 768 { 769 return marshal_len_followed_by_bytes (MARSHAL_AS_SIGNATURE, 770 str, insert_at, value, 771 strlen (value), 772 DBUS_COMPILER_BYTE_ORDER, /* irrelevant */ 773 pos_after); 774 } 775 776 /** 777 * Marshals a basic-typed value. The "value" pointer is always the 778 * address of a variable containing the basic type value. 779 * So for example for int32 it will be dbus_int32_t*, and 780 * for string it will be const char**. This is for symmetry 781 * with _dbus_marshal_read_basic() and to have a simple 782 * consistent rule. 783 * 784 * @param str string to marshal to 785 * @param insert_at where to insert the value 786 * @param type type of value 787 * @param value pointer to a variable containing the value 788 * @param byte_order byte order 789 * @param pos_after #NULL or the position after the type 790 * @returns #TRUE on success 791 **/ 792 dbus_bool_t 793 _dbus_marshal_write_basic (DBusString *str, 794 int insert_at, 795 int type, 796 const void *value, 797 int byte_order, 798 int *pos_after) 799 { 800 const DBusBasicValue *vp; 801 802 _dbus_assert (dbus_type_is_basic (type)); 803 804 vp = value; 805 806 switch (type) 807 { 808 case DBUS_TYPE_BYTE: 809 if (!_dbus_string_insert_byte (str, insert_at, vp->byt)) 810 return FALSE; 811 if (pos_after) 812 *pos_after = insert_at + 1; 813 return TRUE; 814 break; 815 case DBUS_TYPE_INT16: 816 case DBUS_TYPE_UINT16: 817 return marshal_2_octets (str, insert_at, vp->u16, 818 byte_order, pos_after); 819 break; 820 case DBUS_TYPE_BOOLEAN: 821 return marshal_4_octets (str, insert_at, vp->u32 != FALSE, 822 byte_order, pos_after); 823 break; 824 case DBUS_TYPE_INT32: 825 case DBUS_TYPE_UINT32: 826 return marshal_4_octets (str, insert_at, vp->u32, 827 byte_order, pos_after); 828 break; 829 case DBUS_TYPE_INT64: 830 case DBUS_TYPE_UINT64: 831 case DBUS_TYPE_DOUBLE: 832 return marshal_8_octets (str, insert_at, *vp, byte_order, pos_after); 833 break; 834 835 case DBUS_TYPE_STRING: 836 case DBUS_TYPE_OBJECT_PATH: 837 _dbus_assert (vp->str != NULL); 838 return marshal_string (str, insert_at, vp->str, byte_order, pos_after); 839 break; 840 case DBUS_TYPE_SIGNATURE: 841 _dbus_assert (vp->str != NULL); 842 return marshal_signature (str, insert_at, vp->str, pos_after); 843 break; 844 default: 845 _dbus_assert_not_reached ("not a basic type"); 846 return FALSE; 847 break; 848 } 849 } 850 851 static dbus_bool_t 852 marshal_1_octets_array (DBusString *str, 853 int insert_at, 854 const unsigned char *value, 855 int n_elements, 856 int byte_order, 857 int *pos_after) 858 { 859 int pos; 860 DBusString value_str; 861 862 _dbus_string_init_const_len (&value_str, value, n_elements); 863 864 pos = insert_at; 865 866 if (!_dbus_string_copy_len (&value_str, 0, n_elements, 867 str, pos)) 868 return FALSE; 869 870 pos += n_elements; 871 872 if (pos_after) 873 *pos_after = pos; 874 875 return TRUE; 876 } 877 878 /** 879 * Swaps the elements of an array to the opposite byte order 880 * 881 * @param data start of array 882 * @param n_elements number of elements 883 * @param alignment size of each element 884 */ 885 void 886 _dbus_swap_array (unsigned char *data, 887 int n_elements, 888 int alignment) 889 { 890 unsigned char *d; 891 unsigned char *end; 892 893 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, alignment) == data); 894 895 /* we use const_data and cast it off so DBusString can be a const string 896 * for the unit tests. don't ask. 897 */ 898 d = data; 899 end = d + (n_elements * alignment); 900 901 if (alignment == 8) 902 { 903 while (d != end) 904 { 905 #ifdef DBUS_HAVE_INT64 906 *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d)); 907 #else 908 swap_8_bytes ((DBusBasicValue*) d); 909 #endif 910 d += 8; 911 } 912 } 913 else if (alignment == 4) 914 { 915 while (d != end) 916 { 917 *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d)); 918 d += 4; 919 } 920 } 921 else 922 { 923 _dbus_assert (alignment == 2); 924 925 while (d != end) 926 { 927 *((dbus_uint16_t*)d) = DBUS_UINT16_SWAP_LE_BE (*((dbus_uint16_t*)d)); 928 d += 2; 929 } 930 } 931 } 932 933 static void 934 swap_array (DBusString *str, 935 int array_start, 936 int n_elements, 937 int byte_order, 938 int alignment) 939 { 940 _dbus_assert (_DBUS_ALIGN_VALUE (array_start, alignment) == (unsigned) array_start); 941 942 if (byte_order != DBUS_COMPILER_BYTE_ORDER) 943 { 944 /* we use const_data and cast it off so DBusString can be a const string 945 * for the unit tests. don't ask. 946 */ 947 _dbus_swap_array ((unsigned char*) (_dbus_string_get_const_data (str) + array_start), 948 n_elements, alignment); 949 } 950 } 951 952 static dbus_bool_t 953 marshal_fixed_multi (DBusString *str, 954 int insert_at, 955 const DBusBasicValue *value, 956 int n_elements, 957 int byte_order, 958 int alignment, 959 int *pos_after) 960 { 961 int old_string_len; 962 int array_start; 963 DBusString t; 964 int len_in_bytes; 965 966 _dbus_assert (n_elements <= DBUS_MAXIMUM_ARRAY_LENGTH / alignment); 967 968 old_string_len = _dbus_string_get_length (str); 969 970 len_in_bytes = n_elements * alignment; 971 array_start = insert_at; 972 973 /* Note that we do alignment padding unconditionally 974 * even if the array is empty; this means that 975 * padding + len is always equal to the number of bytes 976 * in the array. 977 */ 978 979 if (!_dbus_string_insert_alignment (str, &array_start, alignment)) 980 goto error; 981 982 _dbus_string_init_const_len (&t, 983 (const unsigned char*) value, 984 len_in_bytes); 985 986 if (!_dbus_string_copy (&t, 0, 987 str, array_start)) 988 goto error; 989 990 swap_array (str, array_start, n_elements, byte_order, alignment); 991 992 if (pos_after) 993 *pos_after = array_start + len_in_bytes; 994 995 return TRUE; 996 997 error: 998 _dbus_string_delete (str, insert_at, 999 _dbus_string_get_length (str) - old_string_len); 1000 1001 return FALSE; 1002 } 1003 1004 /** 1005 * Marshals a block of values of fixed-length type all at once, as an 1006 * optimization. dbus_type_is_fixed() returns #TRUE for fixed-length 1007 * types, which are the basic types minus the string-like types. 1008 * 1009 * The value argument should be the adddress of an 1010 * array, so e.g. "const dbus_uint32_t**" 1011 * 1012 * @param str string to marshal to 1013 * @param insert_at where to insert the value 1014 * @param element_type type of array elements 1015 * @param value address of an array to marshal 1016 * @param n_elements number of elements in the array 1017 * @param byte_order byte order 1018 * @param pos_after #NULL or the position after the type 1019 * @returns #TRUE on success 1020 **/ 1021 dbus_bool_t 1022 _dbus_marshal_write_fixed_multi (DBusString *str, 1023 int insert_at, 1024 int element_type, 1025 const void *value, 1026 int n_elements, 1027 int byte_order, 1028 int *pos_after) 1029 { 1030 const void* vp = *(const DBusBasicValue**)value; 1031 1032 _dbus_assert (dbus_type_is_fixed (element_type)); 1033 _dbus_assert (n_elements >= 0); 1034 1035 #if 0 1036 _dbus_verbose ("writing %d elements of %s\n", 1037 n_elements, _dbus_type_to_string (element_type)); 1038 #endif 1039 1040 switch (element_type) 1041 { 1042 case DBUS_TYPE_BYTE: 1043 return marshal_1_octets_array (str, insert_at, vp, n_elements, byte_order, pos_after); 1044 break; 1045 case DBUS_TYPE_INT16: 1046 case DBUS_TYPE_UINT16: 1047 return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 2, pos_after); 1048 /* FIXME: we canonicalize to 0 or 1 for the single boolean case 1049 * should we here too ? */ 1050 case DBUS_TYPE_BOOLEAN: 1051 case DBUS_TYPE_INT32: 1052 case DBUS_TYPE_UINT32: 1053 return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 4, pos_after); 1054 break; 1055 case DBUS_TYPE_INT64: 1056 case DBUS_TYPE_UINT64: 1057 case DBUS_TYPE_DOUBLE: 1058 return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 8, pos_after); 1059 break; 1060 1061 default: 1062 _dbus_assert_not_reached ("non fixed type in array write"); 1063 break; 1064 } 1065 1066 return FALSE; 1067 } 1068 1069 1070 /** 1071 * Skips over a basic-typed value, reporting the following position. 1072 * 1073 * @param str the string containing the data 1074 * @param type type of value to read 1075 * @param byte_order the byte order 1076 * @param pos pointer to position in the string, 1077 * updated on return to new position 1078 **/ 1079 void 1080 _dbus_marshal_skip_basic (const DBusString *str, 1081 int type, 1082 int byte_order, 1083 int *pos) 1084 { 1085 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || 1086 byte_order == DBUS_BIG_ENDIAN); 1087 1088 switch (type) 1089 { 1090 case DBUS_TYPE_BYTE: 1091 (*pos)++; 1092 break; 1093 case DBUS_TYPE_INT16: 1094 case DBUS_TYPE_UINT16: 1095 *pos = _DBUS_ALIGN_VALUE (*pos, 2); 1096 *pos += 2; 1097 break; 1098 case DBUS_TYPE_BOOLEAN: 1099 case DBUS_TYPE_INT32: 1100 case DBUS_TYPE_UINT32: 1101 *pos = _DBUS_ALIGN_VALUE (*pos, 4); 1102 *pos += 4; 1103 break; 1104 case DBUS_TYPE_INT64: 1105 case DBUS_TYPE_UINT64: 1106 case DBUS_TYPE_DOUBLE: 1107 *pos = _DBUS_ALIGN_VALUE (*pos, 8); 1108 *pos += 8; 1109 break; 1110 case DBUS_TYPE_STRING: 1111 case DBUS_TYPE_OBJECT_PATH: 1112 { 1113 int len; 1114 1115 len = _dbus_marshal_read_uint32 (str, *pos, byte_order, pos); 1116 1117 *pos += len + 1; /* length plus nul */ 1118 } 1119 break; 1120 case DBUS_TYPE_SIGNATURE: 1121 { 1122 int len; 1123 1124 len = _dbus_string_get_byte (str, *pos); 1125 1126 *pos += len + 2; /* length byte plus length plus nul */ 1127 } 1128 break; 1129 default: 1130 _dbus_warn ("type %s not a basic type\n", 1131 _dbus_type_to_string (type)); 1132 _dbus_assert_not_reached ("not a basic type"); 1133 break; 1134 } 1135 } 1136 1137 /** 1138 * Skips an array, returning the next position. 1139 * 1140 * @param str the string containing the data 1141 * @param element_type the type of array elements 1142 * @param byte_order the byte order 1143 * @param pos pointer to position in the string, 1144 * updated on return to new position 1145 */ 1146 void 1147 _dbus_marshal_skip_array (const DBusString *str, 1148 int element_type, 1149 int byte_order, 1150 int *pos) 1151 { 1152 dbus_uint32_t array_len; 1153 int i; 1154 int alignment; 1155 1156 i = _DBUS_ALIGN_VALUE (*pos, 4); 1157 1158 array_len = _dbus_marshal_read_uint32 (str, i, byte_order, &i); 1159 1160 alignment = _dbus_type_get_alignment (element_type); 1161 1162 i = _DBUS_ALIGN_VALUE (i, alignment); 1163 1164 *pos = i + array_len; 1165 } 1166 1167 /** 1168 * Gets the alignment requirement for the given type; 1169 * will be 1, 4, or 8. 1170 * 1171 * @param typecode the type 1172 * @returns alignment of 1, 4, or 8 1173 */ 1174 int 1175 _dbus_type_get_alignment (int typecode) 1176 { 1177 switch (typecode) 1178 { 1179 case DBUS_TYPE_BYTE: 1180 case DBUS_TYPE_VARIANT: 1181 case DBUS_TYPE_SIGNATURE: 1182 return 1; 1183 case DBUS_TYPE_INT16: 1184 case DBUS_TYPE_UINT16: 1185 return 2; 1186 case DBUS_TYPE_BOOLEAN: 1187 case DBUS_TYPE_INT32: 1188 case DBUS_TYPE_UINT32: 1189 /* this stuff is 4 since it starts with a length */ 1190 case DBUS_TYPE_STRING: 1191 case DBUS_TYPE_OBJECT_PATH: 1192 case DBUS_TYPE_ARRAY: 1193 return 4; 1194 case DBUS_TYPE_INT64: 1195 case DBUS_TYPE_UINT64: 1196 case DBUS_TYPE_DOUBLE: 1197 /* struct is 8 since it could contain an 8-aligned item 1198 * and it's simpler to just always align structs to 8; 1199 * we want the amount of padding in a struct of a given 1200 * type to be predictable, not location-dependent. 1201 * DICT_ENTRY is always the same as struct. 1202 */ 1203 case DBUS_TYPE_STRUCT: 1204 case DBUS_TYPE_DICT_ENTRY: 1205 return 8; 1206 1207 default: 1208 _dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()"); 1209 return 0; 1210 } 1211 } 1212 1213 1214 /** 1215 * Return #TRUE if the typecode is a valid typecode. 1216 * #DBUS_TYPE_INVALID surprisingly enough is not considered valid, and 1217 * random unknown bytes aren't either. This function is safe with 1218 * untrusted data. 1219 * 1220 * @returns #TRUE if valid 1221 */ 1222 dbus_bool_t 1223 _dbus_type_is_valid (int typecode) 1224 { 1225 switch (typecode) 1226 { 1227 case DBUS_TYPE_BYTE: 1228 case DBUS_TYPE_BOOLEAN: 1229 case DBUS_TYPE_INT16: 1230 case DBUS_TYPE_UINT16: 1231 case DBUS_TYPE_INT32: 1232 case DBUS_TYPE_UINT32: 1233 case DBUS_TYPE_INT64: 1234 case DBUS_TYPE_UINT64: 1235 case DBUS_TYPE_DOUBLE: 1236 case DBUS_TYPE_STRING: 1237 case DBUS_TYPE_OBJECT_PATH: 1238 case DBUS_TYPE_SIGNATURE: 1239 case DBUS_TYPE_ARRAY: 1240 case DBUS_TYPE_STRUCT: 1241 case DBUS_TYPE_DICT_ENTRY: 1242 case DBUS_TYPE_VARIANT: 1243 return TRUE; 1244 1245 default: 1246 return FALSE; 1247 } 1248 } 1249 1250 /** 1251 * Returns a string describing the given type. 1252 * 1253 * @param typecode the type to describe 1254 * @returns a constant string describing the type 1255 */ 1256 const char * 1257 _dbus_type_to_string (int typecode) 1258 { 1259 switch (typecode) 1260 { 1261 case DBUS_TYPE_INVALID: 1262 return "invalid"; 1263 case DBUS_TYPE_BOOLEAN: 1264 return "boolean"; 1265 case DBUS_TYPE_BYTE: 1266 return "byte"; 1267 case DBUS_TYPE_INT16: 1268 return "int16"; 1269 case DBUS_TYPE_UINT16: 1270 return "uint16"; 1271 case DBUS_TYPE_INT32: 1272 return "int32"; 1273 case DBUS_TYPE_UINT32: 1274 return "uint32"; 1275 case DBUS_TYPE_INT64: 1276 return "int64"; 1277 case DBUS_TYPE_UINT64: 1278 return "uint64"; 1279 case DBUS_TYPE_DOUBLE: 1280 return "double"; 1281 case DBUS_TYPE_STRING: 1282 return "string"; 1283 case DBUS_TYPE_OBJECT_PATH: 1284 return "object_path"; 1285 case DBUS_TYPE_SIGNATURE: 1286 return "signature"; 1287 case DBUS_TYPE_STRUCT: 1288 return "struct"; 1289 case DBUS_TYPE_DICT_ENTRY: 1290 return "dict_entry"; 1291 case DBUS_TYPE_ARRAY: 1292 return "array"; 1293 case DBUS_TYPE_VARIANT: 1294 return "variant"; 1295 case DBUS_STRUCT_BEGIN_CHAR: 1296 return "begin_struct"; 1297 case DBUS_STRUCT_END_CHAR: 1298 return "end_struct"; 1299 case DBUS_DICT_ENTRY_BEGIN_CHAR: 1300 return "begin_dict_entry"; 1301 case DBUS_DICT_ENTRY_END_CHAR: 1302 return "end_dict_entry"; 1303 default: 1304 return "unknown"; 1305 } 1306 } 1307 1308 /** 1309 * If in verbose mode, print a block of binary data. 1310 * 1311 * @param data the data 1312 * @param len the length of the data 1313 * @param offset where to start counting for byte indexes 1314 */ 1315 void 1316 _dbus_verbose_bytes (const unsigned char *data, 1317 int len, 1318 int offset) 1319 { 1320 int i; 1321 const unsigned char *aligned; 1322 1323 _dbus_assert (len >= 0); 1324 1325 if (!_dbus_is_verbose()) 1326 return; 1327 1328 /* Print blanks on first row if appropriate */ 1329 aligned = _DBUS_ALIGN_ADDRESS (data, 4); 1330 if (aligned > data) 1331 aligned -= 4; 1332 _dbus_assert (aligned <= data); 1333 1334 if (aligned != data) 1335 { 1336 _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned); 1337 while (aligned != data) 1338 { 1339 _dbus_verbose (" "); 1340 ++aligned; 1341 } 1342 } 1343 1344 /* now print the bytes */ 1345 i = 0; 1346 while (i < len) 1347 { 1348 if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i]) 1349 { 1350 _dbus_verbose ("%4d\t%p: ", 1351 offset + i, &data[i]); 1352 } 1353 1354 if (data[i] >= 32 && 1355 data[i] <= 126) 1356 _dbus_verbose (" '%c' ", data[i]); 1357 else 1358 _dbus_verbose ("0x%s%x ", 1359 data[i] <= 0xf ? "0" : "", data[i]); 1360 1361 ++i; 1362 1363 if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i]) 1364 { 1365 if (i > 3) 1366 _dbus_verbose ("BE: %d LE: %d", 1367 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]), 1368 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4])); 1369 1370 if (i > 7 && 1371 _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i]) 1372 { 1373 #ifdef DBUS_HAVE_INT64 1374 /* I think I probably mean "GNU libc printf" and not "GNUC" 1375 * but we'll wait until someone complains. If you hit this, 1376 * just turn off verbose mode as a workaround. 1377 */ 1378 #if __GNUC__ 1379 _dbus_verbose (" u64: 0x%llx", 1380 *(dbus_uint64_t*)&data[i-8]); 1381 #endif 1382 #endif 1383 _dbus_verbose (" dbl: %g", 1384 *(double*)&data[i-8]); 1385 } 1386 1387 _dbus_verbose ("\n"); 1388 } 1389 } 1390 1391 _dbus_verbose ("\n"); 1392 } 1393 1394 /** 1395 * Dump the given part of the string to verbose log. 1396 * 1397 * @param str the string 1398 * @param start the start of range to dump 1399 * @param len length of range 1400 */ 1401 void 1402 _dbus_verbose_bytes_of_string (const DBusString *str, 1403 int start, 1404 int len) 1405 { 1406 const char *d; 1407 int real_len; 1408 1409 real_len = _dbus_string_get_length (str); 1410 1411 _dbus_assert (start >= 0); 1412 1413 if (start > real_len) 1414 { 1415 _dbus_verbose (" [%d,%d) is not inside string of length %d\n", 1416 start, len, real_len); 1417 return; 1418 } 1419 1420 if ((start + len) > real_len) 1421 { 1422 _dbus_verbose (" [%d,%d) extends outside string of length %d\n", 1423 start, len, real_len); 1424 len = real_len - start; 1425 } 1426 1427 d = _dbus_string_get_const_data_len (str, start, len); 1428 1429 _dbus_verbose_bytes (d, len, start); 1430 } 1431 1432 static int 1433 map_type_char_to_type (int t) 1434 { 1435 if (t == DBUS_STRUCT_BEGIN_CHAR) 1436 return DBUS_TYPE_STRUCT; 1437 else if (t == DBUS_DICT_ENTRY_BEGIN_CHAR) 1438 return DBUS_TYPE_DICT_ENTRY; 1439 else 1440 { 1441 _dbus_assert (t != DBUS_STRUCT_END_CHAR); 1442 _dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR); 1443 return t; 1444 } 1445 } 1446 1447 /** 1448 * Get the first type in the signature. The difference between this 1449 * and just getting the first byte of the signature is that you won't 1450 * get DBUS_STRUCT_BEGIN_CHAR, you'll get DBUS_TYPE_STRUCT 1451 * instead. 1452 * 1453 * @param str string containing signature 1454 * @param pos where the signature starts 1455 * @returns the first type in the signature 1456 */ 1457 int 1458 _dbus_first_type_in_signature (const DBusString *str, 1459 int pos) 1460 { 1461 return map_type_char_to_type (_dbus_string_get_byte (str, pos)); 1462 } 1463 1464 /** 1465 * Similar to #_dbus_first_type_in_signature, but operates 1466 * on a C string buffer. 1467 * 1468 * @param str a C string buffer 1469 * @param pos where the signature starts 1470 * @returns the first type in the signature 1471 */ 1472 int 1473 _dbus_first_type_in_signature_c_str (const char *str, 1474 int pos) 1475 { 1476 return map_type_char_to_type (str[pos]); 1477 } 1478 1479 /** @} */ 1480 1481 #ifdef DBUS_BUILD_TESTS 1482 #include "dbus-test.h" 1483 #include <stdio.h> 1484 1485 /** 1486 * Reads a block of fixed-length basic values, as an optimization 1487 * vs. reading each one individually into a new buffer. 1488 * 1489 * This function returns the data in-place; it does not make a copy, 1490 * and it does not swap the bytes. 1491 * 1492 * If you ask for #DBUS_TYPE_DOUBLE you will get a "const double*" back 1493 * and the "value" argument should be a "const double**" and so on. 1494 * 1495 * @param str the string to read from 1496 * @param pos position to read from 1497 * @param element_type type of array elements 1498 * @param value place to return the array 1499 * @param n_elements number of array elements to read 1500 * @param byte_order the byte order, used to read the array length 1501 * @param new_pos #NULL or location to store a position after the elements 1502 */ 1503 void 1504 _dbus_marshal_read_fixed_multi (const DBusString *str, 1505 int pos, 1506 int element_type, 1507 void *value, 1508 int n_elements, 1509 int byte_order, 1510 int *new_pos) 1511 { 1512 int array_len; 1513 int alignment; 1514 1515 _dbus_assert (dbus_type_is_fixed (element_type)); 1516 _dbus_assert (dbus_type_is_basic (element_type)); 1517 1518 #if 0 1519 _dbus_verbose ("reading %d elements of %s\n", 1520 n_elements, _dbus_type_to_string (element_type)); 1521 #endif 1522 1523 alignment = _dbus_type_get_alignment (element_type); 1524 1525 pos = _DBUS_ALIGN_VALUE (pos, alignment); 1526 1527 array_len = n_elements * alignment; 1528 1529 *(const DBusBasicValue**) value = (void*) _dbus_string_get_const_data_len (str, pos, array_len); 1530 if (new_pos) 1531 *new_pos = pos + array_len; 1532 } 1533 1534 static void 1535 swap_test_array (void *array, 1536 int len_bytes, 1537 int byte_order, 1538 int alignment) 1539 { 1540 DBusString t; 1541 1542 if (alignment == 1) 1543 return; 1544 1545 _dbus_string_init_const_len (&t, array, len_bytes); 1546 swap_array (&t, 0, len_bytes / alignment, byte_order, alignment); 1547 } 1548 1549 #define MARSHAL_BASIC(typename, byte_order, literal) \ 1550 do { \ 1551 v_##typename = literal; \ 1552 if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_##typename, \ 1553 &v_##typename, \ 1554 byte_order, NULL)) \ 1555 _dbus_assert_not_reached ("no memory"); \ 1556 } while (0) 1557 1558 #define DEMARSHAL_BASIC(typename, byte_order) \ 1559 do { \ 1560 _dbus_marshal_read_basic (&str, pos, DBUS_TYPE_##typename, &v_##typename, \ 1561 byte_order, &pos); \ 1562 } while (0) 1563 1564 #define DEMARSHAL_BASIC_AND_CHECK(typename, byte_order, literal) \ 1565 do { \ 1566 DEMARSHAL_BASIC (typename, byte_order); \ 1567 if (literal != v_##typename) \ 1568 { \ 1569 _dbus_verbose_bytes_of_string (&str, dump_pos, \ 1570 _dbus_string_get_length (&str) - dump_pos); \ 1571 _dbus_assert_not_reached ("demarshaled wrong value"); \ 1572 } \ 1573 } while (0) 1574 1575 #define MARSHAL_TEST(typename, byte_order, literal) \ 1576 do { \ 1577 MARSHAL_BASIC (typename, byte_order, literal); \ 1578 dump_pos = pos; \ 1579 DEMARSHAL_BASIC_AND_CHECK (typename, byte_order, literal); \ 1580 } while (0) 1581 1582 #define MARSHAL_TEST_STRCMP(typename, byte_order, literal) \ 1583 do { \ 1584 MARSHAL_BASIC (typename, byte_order, literal); \ 1585 dump_pos = pos; \ 1586 DEMARSHAL_BASIC (typename, byte_order); \ 1587 if (strcmp (literal, v_##typename) != 0) \ 1588 { \ 1589 _dbus_verbose_bytes_of_string (&str, dump_pos, \ 1590 _dbus_string_get_length (&str) - dump_pos); \ 1591 _dbus_warn ("literal '%s'\nvalue '%s'\n", literal, v_##typename); \ 1592 _dbus_assert_not_reached ("demarshaled wrong value"); \ 1593 } \ 1594 } while (0) 1595 1596 #define MARSHAL_FIXED_ARRAY(typename, byte_order, literal) \ 1597 do { \ 1598 int next; \ 1599 v_UINT32 = sizeof(literal); \ 1600 if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_UINT32, &v_UINT32, \ 1601 byte_order, &next)) \ 1602 _dbus_assert_not_reached ("no memory"); \ 1603 v_ARRAY_##typename = literal; \ 1604 if (!_dbus_marshal_write_fixed_multi (&str, next, DBUS_TYPE_##typename, \ 1605 &v_ARRAY_##typename, _DBUS_N_ELEMENTS(literal), \ 1606 byte_order, NULL)) \ 1607 _dbus_assert_not_reached ("no memory"); \ 1608 } while (0) 1609 1610 #define DEMARSHAL_FIXED_ARRAY(typename, byte_order) \ 1611 do { \ 1612 int next; \ 1613 alignment = _dbus_type_get_alignment (DBUS_TYPE_##typename); \ 1614 v_UINT32 = _dbus_marshal_read_uint32 (&str, dump_pos, byte_order, &next); \ 1615 _dbus_marshal_read_fixed_multi (&str, next, DBUS_TYPE_##typename, &v_ARRAY_##typename, \ 1616 v_UINT32/alignment, \ 1617 byte_order, NULL); \ 1618 swap_test_array (v_ARRAY_##typename, v_UINT32, \ 1619 byte_order, alignment); \ 1620 } while (0) 1621 1622 #define DEMARSHAL_FIXED_ARRAY_AND_CHECK(typename, byte_order, literal) \ 1623 do { \ 1624 DEMARSHAL_FIXED_ARRAY (typename, byte_order); \ 1625 if (memcmp (literal, v_ARRAY_##typename, sizeof (literal) != 0)) \ 1626 { \ 1627 _dbus_verbose ("MARSHALED DATA\n"); \ 1628 _dbus_verbose_bytes_of_string (&str, dump_pos, \ 1629 _dbus_string_get_length (&str) - dump_pos); \ 1630 _dbus_verbose ("LITERAL DATA\n"); \ 1631 _dbus_verbose_bytes ((char*)literal, sizeof (literal), 0); \ 1632 _dbus_verbose ("READ DATA\n"); \ 1633 _dbus_verbose_bytes ((char*)v_ARRAY_##typename, sizeof (literal), 0); \ 1634 _dbus_assert_not_reached ("demarshaled wrong fixed array value"); \ 1635 } \ 1636 } while (0) 1637 1638 #define MARSHAL_TEST_FIXED_ARRAY(typename, byte_order, literal) \ 1639 do { \ 1640 MARSHAL_FIXED_ARRAY (typename, byte_order, literal); \ 1641 dump_pos = pos; \ 1642 DEMARSHAL_FIXED_ARRAY_AND_CHECK (typename, byte_order, literal); \ 1643 } while (0) 1644 1645 dbus_bool_t 1646 _dbus_marshal_test (void) 1647 { 1648 int alignment; 1649 DBusString str; 1650 int pos, dump_pos; 1651 unsigned char array1[5] = { 3, 4, 0, 1, 9 }; 1652 dbus_int16_t array2[3] = { 124, 457, 780 }; 1653 dbus_int32_t array4[3] = { 123, 456, 789 }; 1654 #ifdef DBUS_HAVE_INT64 1655 dbus_int64_t array8[3] = { DBUS_INT64_CONSTANT (0x123ffffffff), 1656 DBUS_INT64_CONSTANT (0x456ffffffff), 1657 DBUS_INT64_CONSTANT (0x789ffffffff) }; 1658 dbus_int64_t *v_ARRAY_INT64; 1659 #endif 1660 unsigned char *v_ARRAY_BYTE; 1661 dbus_int16_t *v_ARRAY_INT16; 1662 dbus_uint16_t *v_ARRAY_UINT16; 1663 dbus_int32_t *v_ARRAY_INT32; 1664 dbus_uint32_t *v_ARRAY_UINT32; 1665 DBusString t; 1666 double v_DOUBLE; 1667 double t_DOUBLE; 1668 dbus_int16_t v_INT16; 1669 dbus_uint16_t v_UINT16; 1670 dbus_int32_t v_INT32; 1671 dbus_uint32_t v_UINT32; 1672 dbus_int64_t v_INT64; 1673 dbus_uint64_t v_UINT64; 1674 unsigned char v_BYTE; 1675 dbus_bool_t v_BOOLEAN; 1676 const char *v_STRING; 1677 const char *v_SIGNATURE; 1678 const char *v_OBJECT_PATH; 1679 int byte_order; 1680 1681 if (!_dbus_string_init (&str)) 1682 _dbus_assert_not_reached ("failed to init string"); 1683 1684 pos = 0; 1685 1686 /* Marshal doubles */ 1687 MARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN, 3.14); 1688 DEMARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN); 1689 t_DOUBLE = 3.14; 1690 if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE)) 1691 _dbus_assert_not_reached ("got wrong double value"); 1692 1693 MARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN, 3.14); 1694 DEMARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN); 1695 t_DOUBLE = 3.14; 1696 if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE)) 1697 _dbus_assert_not_reached ("got wrong double value"); 1698 1699 /* Marshal signed 16 integers */ 1700 MARSHAL_TEST (INT16, DBUS_BIG_ENDIAN, -12345); 1701 MARSHAL_TEST (INT16, DBUS_LITTLE_ENDIAN, -12345); 1702 1703 /* Marshal unsigned 16 integers */ 1704 MARSHAL_TEST (UINT16, DBUS_BIG_ENDIAN, 0x1234); 1705 MARSHAL_TEST (UINT16, DBUS_LITTLE_ENDIAN, 0x1234); 1706 1707 /* Marshal signed integers */ 1708 MARSHAL_TEST (INT32, DBUS_BIG_ENDIAN, -12345678); 1709 MARSHAL_TEST (INT32, DBUS_LITTLE_ENDIAN, -12345678); 1710 1711 /* Marshal unsigned integers */ 1712 MARSHAL_TEST (UINT32, DBUS_BIG_ENDIAN, 0x12345678); 1713 MARSHAL_TEST (UINT32, DBUS_LITTLE_ENDIAN, 0x12345678); 1714 1715 #ifdef DBUS_HAVE_INT64 1716 /* Marshal signed integers */ 1717 MARSHAL_TEST (INT64, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)); 1718 MARSHAL_TEST (INT64, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)); 1719 1720 /* Marshal unsigned integers */ 1721 MARSHAL_TEST (UINT64, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)); 1722 MARSHAL_TEST (UINT64, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)); 1723 #endif /* DBUS_HAVE_INT64 */ 1724 1725 /* Marshal byte */ 1726 MARSHAL_TEST (BYTE, DBUS_BIG_ENDIAN, 5); 1727 MARSHAL_TEST (BYTE, DBUS_LITTLE_ENDIAN, 5); 1728 1729 /* Marshal all possible bools! */ 1730 MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, FALSE); 1731 MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, FALSE); 1732 MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, TRUE); 1733 MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, TRUE); 1734 1735 /* Marshal strings */ 1736 MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, ""); 1737 MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, ""); 1738 MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "This is the dbus test string"); 1739 MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "This is the dbus test string"); 1740 1741 /* object paths */ 1742 MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_BIG_ENDIAN, "/a/b/c"); 1743 MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_LITTLE_ENDIAN, "/a/b/c"); 1744 1745 /* signatures */ 1746 MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, ""); 1747 MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, ""); 1748 MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "a(ii)"); 1749 MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "a(ii)"); 1750 1751 /* Arrays */ 1752 MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_BIG_ENDIAN, array2); 1753 MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_LITTLE_ENDIAN, array2); 1754 MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_BIG_ENDIAN, array2); 1755 MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_LITTLE_ENDIAN, array2); 1756 1757 MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_BIG_ENDIAN, array4); 1758 MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_LITTLE_ENDIAN, array4); 1759 MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_BIG_ENDIAN, array4); 1760 MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_LITTLE_ENDIAN, array4); 1761 1762 MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_BIG_ENDIAN, array1); 1763 MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_LITTLE_ENDIAN, array1); 1764 1765 #ifdef DBUS_HAVE_INT64 1766 MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_BIG_ENDIAN, array8); 1767 MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_LITTLE_ENDIAN, array8); 1768 #endif 1769 1770 #if 0 1771 1772 /* 1773 * FIXME restore the set/pack tests 1774 */ 1775 1776 #ifdef DBUS_HAVE_INT64 1777 /* set/pack 64-bit integers */ 1778 _dbus_string_set_length (&str, 8); 1779 1780 /* signed little */ 1781 _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN, 1782 0, DBUS_INT64_CONSTANT (-0x123456789abc7)); 1783 1784 _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) == 1785 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN, 1786 _dbus_string_get_const_data (&str))); 1787 1788 /* signed big */ 1789 _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN, 1790 0, DBUS_INT64_CONSTANT (-0x123456789abc7)); 1791 1792 _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) == 1793 _dbus_unpack_int64 (DBUS_BIG_ENDIAN, 1794 _dbus_string_get_const_data (&str))); 1795 1796 /* signed little pack */ 1797 _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7), 1798 DBUS_LITTLE_ENDIAN, 1799 _dbus_string_get_data (&str)); 1800 1801 _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) == 1802 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN, 1803 _dbus_string_get_const_data (&str))); 1804 1805 /* signed big pack */ 1806 _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7), 1807 DBUS_BIG_ENDIAN, 1808 _dbus_string_get_data (&str)); 1809 1810 _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) == 1811 _dbus_unpack_int64 (DBUS_BIG_ENDIAN, 1812 _dbus_string_get_const_data (&str))); 1813 1814 /* unsigned little */ 1815 _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN, 1816 0, DBUS_UINT64_CONSTANT (0x123456789abc7)); 1817 1818 _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) == 1819 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN, 1820 _dbus_string_get_const_data (&str))); 1821 1822 /* unsigned big */ 1823 _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN, 1824 0, DBUS_UINT64_CONSTANT (0x123456789abc7)); 1825 1826 _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) == 1827 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN, 1828 _dbus_string_get_const_data (&str))); 1829 1830 /* unsigned little pack */ 1831 _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7), 1832 DBUS_LITTLE_ENDIAN, 1833 _dbus_string_get_data (&str)); 1834 1835 _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) == 1836 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN, 1837 _dbus_string_get_const_data (&str))); 1838 1839 /* unsigned big pack */ 1840 _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7), 1841 DBUS_BIG_ENDIAN, 1842 _dbus_string_get_data (&str)); 1843 1844 _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) == 1845 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN, 1846 _dbus_string_get_const_data (&str))); 1847 #endif /* DBUS_HAVE_INT64 */ 1848 1849 /* set/pack 32-bit integers */ 1850 _dbus_string_set_length (&str, 4); 1851 1852 /* signed little */ 1853 _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN, 1854 0, -0x123456); 1855 1856 _dbus_assert (-0x123456 == 1857 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN, 1858 _dbus_string_get_const_data (&str))); 1859 1860 /* signed big */ 1861 _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN, 1862 0, -0x123456); 1863 1864 _dbus_assert (-0x123456 == 1865 _dbus_unpack_int32 (DBUS_BIG_ENDIAN, 1866 _dbus_string_get_const_data (&str))); 1867 1868 /* signed little pack */ 1869 _dbus_pack_int32 (-0x123456, 1870 DBUS_LITTLE_ENDIAN, 1871 _dbus_string_get_data (&str)); 1872 1873 _dbus_assert (-0x123456 == 1874 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN, 1875 _dbus_string_get_const_data (&str))); 1876 1877 /* signed big pack */ 1878 _dbus_pack_int32 (-0x123456, 1879 DBUS_BIG_ENDIAN, 1880 _dbus_string_get_data (&str)); 1881 1882 _dbus_assert (-0x123456 == 1883 _dbus_unpack_int32 (DBUS_BIG_ENDIAN, 1884 _dbus_string_get_const_data (&str))); 1885 1886 /* unsigned little */ 1887 _dbus_marshal_set_uint32 (&str, 1888 0, 0x123456, 1889 DBUS_LITTLE_ENDIAN); 1890 1891 _dbus_assert (0x123456 == 1892 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, 1893 _dbus_string_get_const_data (&str))); 1894 1895 /* unsigned big */ 1896 _dbus_marshal_set_uint32 (&str, 1897 0, 0x123456, 1898 DBUS_BIG_ENDIAN); 1899 1900 _dbus_assert (0x123456 == 1901 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, 1902 _dbus_string_get_const_data (&str))); 1903 1904 /* unsigned little pack */ 1905 _dbus_pack_uint32 (0x123456, 1906 DBUS_LITTLE_ENDIAN, 1907 _dbus_string_get_data (&str)); 1908 1909 _dbus_assert (0x123456 == 1910 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, 1911 _dbus_string_get_const_data (&str))); 1912 1913 /* unsigned big pack */ 1914 _dbus_pack_uint32 (0x123456, 1915 DBUS_BIG_ENDIAN, 1916 _dbus_string_get_data (&str)); 1917 1918 _dbus_assert (0x123456 == 1919 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, 1920 _dbus_string_get_const_data (&str))); 1921 1922 #endif /* set/pack tests for integers */ 1923 1924 /* Strings in-place set */ 1925 byte_order = DBUS_LITTLE_ENDIAN; 1926 while (TRUE) 1927 { 1928 /* Init a string */ 1929 _dbus_string_set_length (&str, 0); 1930 1931 /* reset pos for the macros */ 1932 pos = 0; 1933 1934 MARSHAL_TEST_STRCMP (STRING, byte_order, "Hello world"); 1935 1936 /* Set it to something longer */ 1937 _dbus_string_init_const (&t, "Hello world foo"); 1938 1939 v_STRING = _dbus_string_get_const_data (&t); 1940 _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING, 1941 &v_STRING, byte_order, NULL, NULL); 1942 1943 _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING, 1944 &v_STRING, byte_order, 1945 NULL); 1946 _dbus_assert (strcmp (v_STRING, "Hello world foo") == 0); 1947 1948 /* Set it to something shorter */ 1949 _dbus_string_init_const (&t, "Hello"); 1950 1951 v_STRING = _dbus_string_get_const_data (&t); 1952 _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING, 1953 &v_STRING, byte_order, NULL, NULL); 1954 _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING, 1955 &v_STRING, byte_order, 1956 NULL); 1957 _dbus_assert (strcmp (v_STRING, "Hello") == 0); 1958 1959 /* Do the other byte order */ 1960 if (byte_order == DBUS_LITTLE_ENDIAN) 1961 byte_order = DBUS_BIG_ENDIAN; 1962 else 1963 break; 1964 } 1965 1966 /* Clean up */ 1967 _dbus_string_free (&str); 1968 1969 return TRUE; 1970 } 1971 1972 #endif /* DBUS_BUILD_TESTS */ 1973