1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 2 /* dbus-signature.c Routines for reading recursive type signatures 3 * 4 * Copyright (C) 2005 Red Hat, Inc. 5 * 6 * Licensed under the Academic Free License version 2.1 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 * 22 */ 23 24 #include <config.h> 25 26 #include "dbus-signature.h" 27 #include "dbus-marshal-recursive.h" 28 #include "dbus-marshal-basic.h" 29 #include "dbus-internals.h" 30 #include "dbus-test.h" 31 32 /** 33 * Implementation details of #DBusSignatureIter, all fields are private 34 */ 35 typedef struct 36 { 37 const char *pos; /**< current position in the signature string */ 38 unsigned int finished : 1; /**< true if we are at the end iter */ 39 unsigned int in_array : 1; /**< true if we are a subiterator pointing to an array's element type */ 40 } DBusSignatureRealIter; 41 42 /** macro that checks whether a typecode is a container type */ 43 #define TYPE_IS_CONTAINER(typecode) \ 44 ((typecode) == DBUS_TYPE_STRUCT || \ 45 (typecode) == DBUS_TYPE_DICT_ENTRY || \ 46 (typecode) == DBUS_TYPE_VARIANT || \ 47 (typecode) == DBUS_TYPE_ARRAY) 48 49 50 /** 51 * @defgroup DBusSignature Type signature parsing 52 * @ingroup DBus 53 * @brief Parsing D-Bus type signatures 54 * @{ 55 */ 56 57 /** 58 * Initializes a #DBusSignatureIter for reading a type signature. This 59 * function is not safe to use on invalid signatures; be sure to 60 * validate potentially invalid signatures with dbus_signature_validate 61 * before using this function. 62 * 63 * @param iter pointer to an iterator to initialize 64 * @param signature the type signature 65 */ 66 void 67 dbus_signature_iter_init (DBusSignatureIter *iter, 68 const char *signature) 69 { 70 DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter; 71 72 real_iter->pos = signature; 73 real_iter->finished = FALSE; 74 real_iter->in_array = FALSE; 75 } 76 77 /** 78 * Returns the current type pointed to by the iterator. 79 * If the iterator is pointing at a type code such as 's', then 80 * it will be returned directly. 81 * 82 * However, when the parser encounters a container type start 83 * character such as '(' for a structure, the corresponding type for 84 * the container will be returned, e.g. DBUS_TYPE_STRUCT, not '('. 85 * In this case, you should initialize a sub-iterator with 86 * dbus_signature_iter_recurse() to parse the container type. 87 * 88 * @param iter pointer to an iterator 89 * @returns current type (e.g. #DBUS_TYPE_STRING, #DBUS_TYPE_ARRAY) 90 */ 91 int 92 dbus_signature_iter_get_current_type (const DBusSignatureIter *iter) 93 { 94 DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter; 95 96 return _dbus_first_type_in_signature_c_str (real_iter->pos, 0); 97 } 98 99 /** 100 * Returns the signature of the single complete type starting at the 101 * given iterator. 102 * 103 * For example, if the iterator is pointing at the start of "(ii)ii" 104 * (which is "a struct of two ints, followed by an int, followed by an 105 * int"), then "(ii)" would be returned. If the iterator is pointing at 106 * one of the "i" then just that "i" would be returned. 107 * 108 * @param iter pointer to an iterator 109 * @returns current signature; or #NULL if no memory. Should be freed with dbus_free() 110 */ 111 char * 112 dbus_signature_iter_get_signature (const DBusSignatureIter *iter) 113 { 114 DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter; 115 DBusString str; 116 char *ret; 117 int pos; 118 119 if (!_dbus_string_init (&str)) 120 return NULL; 121 122 pos = 0; 123 _dbus_type_signature_next (real_iter->pos, &pos); 124 125 if (!_dbus_string_append_len (&str, real_iter->pos, pos)) 126 return NULL; 127 if (!_dbus_string_steal_data (&str, &ret)) 128 ret = NULL; 129 _dbus_string_free (&str); 130 131 return ret; 132 } 133 134 /** 135 * Convenience function for returning the element type of an array; 136 * This function allows you to avoid initializing a sub-iterator and 137 * getting its current type. 138 * 139 * Undefined behavior results if you invoke this function when the 140 * current type of the iterator is not #DBUS_TYPE_ARRAY. 141 * 142 * @param iter pointer to an iterator 143 * @returns current array element type 144 */ 145 int 146 dbus_signature_iter_get_element_type (const DBusSignatureIter *iter) 147 { 148 DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter; 149 150 _dbus_return_val_if_fail (dbus_signature_iter_get_current_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID); 151 152 return _dbus_first_type_in_signature_c_str (real_iter->pos, 1); 153 } 154 155 /** 156 * Skip to the next value on this "level". e.g. the next field in a 157 * struct, the next value in an array. Returns #FALSE at the end of the 158 * current container. 159 * 160 * @param iter the iterator 161 * @returns FALSE if nothing more to read at or below this level 162 */ 163 dbus_bool_t 164 dbus_signature_iter_next (DBusSignatureIter *iter) 165 { 166 DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter; 167 168 if (real_iter->finished) 169 return FALSE; 170 else 171 { 172 int pos; 173 174 if (real_iter->in_array) 175 { 176 real_iter->finished = TRUE; 177 return FALSE; 178 } 179 180 pos = 0; 181 _dbus_type_signature_next (real_iter->pos, &pos); 182 real_iter->pos += pos; 183 184 if (*real_iter->pos == DBUS_STRUCT_END_CHAR 185 || *real_iter->pos == DBUS_DICT_ENTRY_END_CHAR) 186 { 187 real_iter->finished = TRUE; 188 return FALSE; 189 } 190 191 return *real_iter->pos != DBUS_TYPE_INVALID; 192 } 193 } 194 195 /** 196 * Initialize a new iterator pointing to the first type in the current 197 * container. 198 * 199 * The results are undefined when calling this if the current type is 200 * a non-container (i.e. if dbus_type_is_container() returns #FALSE 201 * for the result of dbus_signature_iter_get_current_type()). 202 * 203 * @param iter the current interator 204 * @param subiter an iterator to initialize pointing to the first child 205 */ 206 void 207 dbus_signature_iter_recurse (const DBusSignatureIter *iter, 208 DBusSignatureIter *subiter) 209 { 210 DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter; 211 DBusSignatureRealIter *real_sub_iter = (DBusSignatureRealIter *) subiter; 212 213 _dbus_return_if_fail (dbus_type_is_container (dbus_signature_iter_get_current_type (iter))); 214 215 *real_sub_iter = *real_iter; 216 real_sub_iter->in_array = FALSE; 217 real_sub_iter->pos++; 218 219 if (dbus_signature_iter_get_current_type (iter) == DBUS_TYPE_ARRAY) 220 real_sub_iter->in_array = TRUE; 221 } 222 223 /** 224 * Check a type signature for validity. Remember that #NULL can always 225 * be passed instead of a DBusError*, if you don't care about having 226 * an error name and message. 227 * 228 * @param signature a potentially invalid type signature 229 * @param error error return 230 * @returns #TRUE if signature is valid or #FALSE if an error is set 231 */ 232 dbus_bool_t 233 dbus_signature_validate (const char *signature, 234 DBusError *error) 235 236 { 237 DBusString str; 238 DBusValidity reason; 239 240 _dbus_string_init_const (&str, signature); 241 reason = _dbus_validate_signature_with_reason (&str, 0, _dbus_string_get_length (&str)); 242 243 if (reason == DBUS_VALID) 244 return TRUE; 245 else 246 { 247 dbus_set_error (error, DBUS_ERROR_INVALID_SIGNATURE, _dbus_validity_to_error_message (reason)); 248 return FALSE; 249 } 250 } 251 252 /** 253 * Check that a type signature is both valid and contains exactly one 254 * complete type. "One complete type" means a single basic type, 255 * array, struct, or dictionary, though the struct or array may be 256 * arbitrarily recursive and complex. More than one complete type 257 * would mean for example "ii" or two integers in sequence. 258 * 259 * @param signature a potentially invalid type signature 260 * @param error error return 261 * @returns #TRUE if signature is valid and has exactly one complete type 262 */ 263 dbus_bool_t 264 dbus_signature_validate_single (const char *signature, 265 DBusError *error) 266 { 267 DBusSignatureIter iter; 268 269 if (!dbus_signature_validate (signature, error)) 270 return FALSE; 271 272 dbus_signature_iter_init (&iter, signature); 273 if (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_INVALID) 274 goto lose; 275 if (!dbus_signature_iter_next (&iter)) 276 return TRUE; 277 lose: 278 dbus_set_error (error, DBUS_ERROR_INVALID_SIGNATURE, "Exactly one complete type required in signature"); 279 return FALSE; 280 } 281 282 /** 283 * A "container type" can contain basic types, or nested 284 * container types. #DBUS_TYPE_INVALID is not a container type. 285 * 286 * This function will crash if passed a typecode that isn't 287 * in dbus-protocol.h 288 * 289 * @returns #TRUE if type is a container 290 */ 291 dbus_bool_t 292 dbus_type_is_container (int typecode) 293 { 294 /* only reasonable (non-line-noise) typecodes are allowed */ 295 _dbus_return_val_if_fail (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID, 296 FALSE); 297 return TYPE_IS_CONTAINER (typecode); 298 } 299 300 /** 301 * A "basic type" is a somewhat arbitrary concept, but the intent is 302 * to include those types that are fully-specified by a single 303 * typecode, with no additional type information or nested values. So 304 * all numbers and strings are basic types and structs, arrays, and 305 * variants are not basic types. #DBUS_TYPE_INVALID is not a basic 306 * type. 307 * 308 * This function will crash if passed a typecode that isn't 309 * in dbus-protocol.h 310 * 311 * @returns #TRUE if type is basic 312 */ 313 dbus_bool_t 314 dbus_type_is_basic (int typecode) 315 { 316 /* only reasonable (non-line-noise) typecodes are allowed */ 317 _dbus_return_val_if_fail (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID, 318 FALSE); 319 320 /* everything that isn't invalid or a container */ 321 return !(typecode == DBUS_TYPE_INVALID || TYPE_IS_CONTAINER (typecode)); 322 } 323 324 /** 325 * Tells you whether values of this type can change length if you set 326 * them to some other value. For this purpose, you assume that the 327 * first byte of the old and new value would be in the same location, 328 * so alignment padding is not a factor. 329 * 330 * This function is useful to determine whether 331 * dbus_message_iter_get_fixed_array() may be used. 332 * 333 * Some structs are fixed-size (if they contain only fixed-size types) 334 * but struct is not considered a fixed type for purposes of this 335 * function. 336 * 337 * This function will crash if passed a typecode that isn't 338 * in dbus-protocol.h 339 * 340 * @returns #FALSE if the type can occupy different lengths 341 */ 342 dbus_bool_t 343 dbus_type_is_fixed (int typecode) 344 { 345 /* only reasonable (non-line-noise) typecodes are allowed */ 346 _dbus_return_val_if_fail (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID, 347 FALSE); 348 349 switch (typecode) 350 { 351 case DBUS_TYPE_BYTE: 352 case DBUS_TYPE_BOOLEAN: 353 case DBUS_TYPE_INT16: 354 case DBUS_TYPE_UINT16: 355 case DBUS_TYPE_INT32: 356 case DBUS_TYPE_UINT32: 357 case DBUS_TYPE_INT64: 358 case DBUS_TYPE_UINT64: 359 case DBUS_TYPE_DOUBLE: 360 case DBUS_TYPE_UNIX_FD: 361 return TRUE; 362 default: 363 return FALSE; 364 } 365 } 366 367 /** @} */ /* end of DBusSignature group */ 368 369 #ifdef DBUS_BUILD_TESTS 370 371 /** 372 * @ingroup DBusSignatureInternals 373 * Unit test for DBusSignature. 374 * 375 * @returns #TRUE on success. 376 */ 377 dbus_bool_t 378 _dbus_signature_test (void) 379 { 380 DBusSignatureIter iter; 381 DBusSignatureIter subiter; 382 DBusSignatureIter subsubiter; 383 DBusSignatureIter subsubsubiter; 384 const char *sig; 385 dbus_bool_t boolres; 386 387 _dbus_assert (sizeof (DBusSignatureIter) >= sizeof (DBusSignatureRealIter)); 388 389 sig = ""; 390 _dbus_assert (dbus_signature_validate (sig, NULL)); 391 _dbus_assert (!dbus_signature_validate_single (sig, NULL)); 392 dbus_signature_iter_init (&iter, sig); 393 _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_INVALID); 394 395 sig = DBUS_TYPE_STRING_AS_STRING; 396 _dbus_assert (dbus_signature_validate (sig, NULL)); 397 _dbus_assert (dbus_signature_validate_single (sig, NULL)); 398 dbus_signature_iter_init (&iter, sig); 399 _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRING); 400 401 sig = DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_BYTE_AS_STRING; 402 _dbus_assert (dbus_signature_validate (sig, NULL)); 403 dbus_signature_iter_init (&iter, sig); 404 _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRING); 405 boolres = dbus_signature_iter_next (&iter); 406 _dbus_assert (boolres); 407 _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_BYTE); 408 409 sig = DBUS_TYPE_UINT16_AS_STRING 410 DBUS_STRUCT_BEGIN_CHAR_AS_STRING 411 DBUS_TYPE_STRING_AS_STRING 412 DBUS_TYPE_UINT32_AS_STRING 413 DBUS_TYPE_VARIANT_AS_STRING 414 DBUS_TYPE_DOUBLE_AS_STRING 415 DBUS_STRUCT_END_CHAR_AS_STRING; 416 _dbus_assert (dbus_signature_validate (sig, NULL)); 417 dbus_signature_iter_init (&iter, sig); 418 _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_UINT16); 419 boolres = dbus_signature_iter_next (&iter); 420 _dbus_assert (boolres); 421 _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRUCT); 422 dbus_signature_iter_recurse (&iter, &subiter); 423 _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_STRING); 424 boolres = dbus_signature_iter_next (&subiter); 425 _dbus_assert (boolres); 426 _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_UINT32); 427 boolres = dbus_signature_iter_next (&subiter); 428 _dbus_assert (boolres); 429 _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_VARIANT); 430 boolres = dbus_signature_iter_next (&subiter); 431 _dbus_assert (boolres); 432 _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_DOUBLE); 433 434 sig = DBUS_TYPE_UINT16_AS_STRING 435 DBUS_STRUCT_BEGIN_CHAR_AS_STRING 436 DBUS_TYPE_UINT32_AS_STRING 437 DBUS_TYPE_BYTE_AS_STRING 438 DBUS_TYPE_ARRAY_AS_STRING 439 DBUS_TYPE_ARRAY_AS_STRING 440 DBUS_TYPE_DOUBLE_AS_STRING 441 DBUS_STRUCT_BEGIN_CHAR_AS_STRING 442 DBUS_TYPE_BYTE_AS_STRING 443 DBUS_STRUCT_END_CHAR_AS_STRING 444 DBUS_STRUCT_END_CHAR_AS_STRING; 445 _dbus_assert (dbus_signature_validate (sig, NULL)); 446 dbus_signature_iter_init (&iter, sig); 447 _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_UINT16); 448 boolres = dbus_signature_iter_next (&iter); 449 _dbus_assert (boolres); 450 _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRUCT); 451 dbus_signature_iter_recurse (&iter, &subiter); 452 _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_UINT32); 453 boolres = dbus_signature_iter_next (&subiter); 454 _dbus_assert (boolres); 455 _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_BYTE); 456 boolres = dbus_signature_iter_next (&subiter); 457 _dbus_assert (boolres); 458 _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_ARRAY); 459 _dbus_assert (dbus_signature_iter_get_element_type (&subiter) == DBUS_TYPE_ARRAY); 460 461 dbus_signature_iter_recurse (&subiter, &subsubiter); 462 _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_ARRAY); 463 _dbus_assert (dbus_signature_iter_get_element_type (&subsubiter) == DBUS_TYPE_DOUBLE); 464 465 dbus_signature_iter_recurse (&subsubiter, &subsubsubiter); 466 _dbus_assert (dbus_signature_iter_get_current_type (&subsubsubiter) == DBUS_TYPE_DOUBLE); 467 boolres = dbus_signature_iter_next (&subiter); 468 _dbus_assert (boolres); 469 _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_STRUCT); 470 dbus_signature_iter_recurse (&subiter, &subsubiter); 471 _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_BYTE); 472 473 sig = DBUS_TYPE_ARRAY_AS_STRING 474 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING 475 DBUS_TYPE_INT16_AS_STRING 476 DBUS_TYPE_STRING_AS_STRING 477 DBUS_DICT_ENTRY_END_CHAR_AS_STRING 478 DBUS_TYPE_VARIANT_AS_STRING; 479 _dbus_assert (dbus_signature_validate (sig, NULL)); 480 _dbus_assert (!dbus_signature_validate_single (sig, NULL)); 481 dbus_signature_iter_init (&iter, sig); 482 _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_ARRAY); 483 _dbus_assert (dbus_signature_iter_get_element_type (&iter) == DBUS_TYPE_DICT_ENTRY); 484 485 dbus_signature_iter_recurse (&iter, &subiter); 486 dbus_signature_iter_recurse (&subiter, &subsubiter); 487 _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_INT16); 488 boolres = dbus_signature_iter_next (&subsubiter); 489 _dbus_assert (boolres); 490 _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_STRING); 491 boolres = dbus_signature_iter_next (&subsubiter); 492 _dbus_assert (!boolres); 493 494 boolres = dbus_signature_iter_next (&iter); 495 _dbus_assert (boolres); 496 _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_VARIANT); 497 boolres = dbus_signature_iter_next (&iter); 498 _dbus_assert (!boolres); 499 500 sig = DBUS_TYPE_DICT_ENTRY_AS_STRING; 501 _dbus_assert (!dbus_signature_validate (sig, NULL)); 502 503 sig = DBUS_TYPE_ARRAY_AS_STRING; 504 _dbus_assert (!dbus_signature_validate (sig, NULL)); 505 506 sig = DBUS_TYPE_UINT32_AS_STRING 507 DBUS_TYPE_ARRAY_AS_STRING; 508 _dbus_assert (!dbus_signature_validate (sig, NULL)); 509 510 sig = DBUS_TYPE_ARRAY_AS_STRING 511 DBUS_TYPE_DICT_ENTRY_AS_STRING; 512 _dbus_assert (!dbus_signature_validate (sig, NULL)); 513 514 sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING; 515 _dbus_assert (!dbus_signature_validate (sig, NULL)); 516 517 sig = DBUS_DICT_ENTRY_END_CHAR_AS_STRING; 518 _dbus_assert (!dbus_signature_validate (sig, NULL)); 519 520 sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING 521 DBUS_TYPE_INT32_AS_STRING; 522 _dbus_assert (!dbus_signature_validate (sig, NULL)); 523 524 sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING 525 DBUS_TYPE_INT32_AS_STRING 526 DBUS_TYPE_STRING_AS_STRING; 527 _dbus_assert (!dbus_signature_validate (sig, NULL)); 528 529 sig = DBUS_STRUCT_END_CHAR_AS_STRING 530 DBUS_STRUCT_BEGIN_CHAR_AS_STRING; 531 _dbus_assert (!dbus_signature_validate (sig, NULL)); 532 533 sig = DBUS_STRUCT_BEGIN_CHAR_AS_STRING 534 DBUS_TYPE_BOOLEAN_AS_STRING; 535 _dbus_assert (!dbus_signature_validate (sig, NULL)); 536 return TRUE; 537 #if 0 538 oom: 539 _dbus_assert_not_reached ("out of memory"); 540 return FALSE; 541 #endif 542 } 543 544 #endif 545 546