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