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