summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2015-02-05 14:42:00 +0100
committerGravatar Nikias Bassen2015-02-05 14:42:00 +0100
commit40cf910a621445bf5c2638f39d245fc7c3c8f72a (patch)
tree66e3dad973a0677c29783d79d8e0978c0a8e3ae3
parent6a781e6f69cb820347bae02a1f947e6b01ccaa47 (diff)
downloadlibplist-40cf910a621445bf5c2638f39d245fc7c3c8f72a.tar.gz
libplist-40cf910a621445bf5c2638f39d245fc7c3c8f72a.tar.bz2
bplist: Refactor binary plist parsing in a recursive way
-rw-r--r--src/bplist.c376
1 files changed, 167 insertions, 209 deletions
diff --git a/src/bplist.c b/src/bplist.c
index 5ddca26..3ba46a2 100644
--- a/src/bplist.c
+++ b/src/bplist.c
@@ -1,8 +1,9 @@
1/* 1/*
2 * plist.c 2 * bplist.c
3 * Binary plist implementation 3 * Binary plist implementation
4 * 4 *
5 * Copyright (c) 2008 Jonathan Beck All Rights Reserved. 5 * Copyright (c) 2011-2015 Nikias Bassen, All Rights Reserved.
6 * Copyright (c) 2008-2010 Jonathan Beck, All Rights Reserved.
6 * 7 *
7 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public 9 * modify it under the terms of the GNU Lesser General Public
@@ -95,7 +96,7 @@ static void float_byte_convert(uint8_t * address, size_t size)
95 96
96union plist_uint_ptr 97union plist_uint_ptr
97{ 98{
98 void *src; 99 const void *src;
99 uint8_t *u8ptr; 100 uint8_t *u8ptr;
100 uint16_t *u16ptr; 101 uint16_t *u16ptr;
101 uint32_t *u32ptr; 102 uint32_t *u32ptr;
@@ -202,7 +203,20 @@ static uint32_t uint24_from_be(union plist_uint_ptr buf)
202 203
203#define NODE_IS_ROOT(x) (((node_t*)x)->isRoot) 204#define NODE_IS_ROOT(x) (((node_t*)x)->isRoot)
204 205
205static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object) 206struct bplist_data {
207 const char* data;
208 uint64_t size;
209 uint64_t num_objects;
210 uint8_t dict_size;
211 uint8_t offset_size;
212 const char* offset_table;
213 uint32_t level;
214 uint32_t *used_indexes;
215};
216
217static plist_t parse_bin_node_at_index(struct bplist_data *bplist, uint32_t node_index);
218
219static plist_t parse_uint_node(const char **bnode, uint8_t size)
206{ 220{
207 plist_data_t data = plist_new_plist_data(); 221 plist_data_t data = plist_new_plist_data();
208 222
@@ -213,12 +227,12 @@ static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object)
213 case sizeof(uint16_t): 227 case sizeof(uint16_t):
214 case sizeof(uint32_t): 228 case sizeof(uint32_t):
215 case sizeof(uint64_t): 229 case sizeof(uint64_t):
216 memcpy(&data->intval, bnode, size); 230 memcpy(&data->intval, *bnode, size);
217 data->intval = UINT_TO_HOST(&data->intval, size); 231 data->intval = UINT_TO_HOST(&data->intval, size);
218 data->length = sizeof(uint64_t); 232 data->length = sizeof(uint64_t);
219 break; 233 break;
220 case 16: 234 case 16:
221 memcpy(&data->intval, bnode+8, sizeof(uint64_t)); 235 memcpy(&data->intval, (*bnode)+8, sizeof(uint64_t));
222 data->intval = UINT_TO_HOST(&data->intval, sizeof(uint64_t)); 236 data->intval = UINT_TO_HOST(&data->intval, sizeof(uint64_t));
223 data->length = size; 237 data->length = size;
224 break; 238 break;
@@ -227,13 +241,13 @@ static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object)
227 return NULL; 241 return NULL;
228 }; 242 };
229 243
230 *next_object = bnode + size; 244 (*bnode) += size;
231 data->type = PLIST_UINT; 245 data->type = PLIST_UINT;
232 246
233 return node_create(NULL, data); 247 return node_create(NULL, data);
234} 248}
235 249
236static plist_t parse_real_node(char *bnode, uint8_t size) 250static plist_t parse_real_node(const char **bnode, uint8_t size)
237{ 251{
238 plist_data_t data = plist_new_plist_data(); 252 plist_data_t data = plist_new_plist_data();
239 float floatval = 0.0; 253 float floatval = 0.0;
@@ -241,7 +255,7 @@ static plist_t parse_real_node(char *bnode, uint8_t size)
241 255
242 size = 1 << size; // make length less misleading 256 size = 1 << size; // make length less misleading
243 buf = malloc (size); 257 buf = malloc (size);
244 memcpy (buf, bnode, size); 258 memcpy (buf, *bnode, size);
245 switch (size) 259 switch (size)
246 { 260 {
247 case sizeof(float): 261 case sizeof(float):
@@ -265,7 +279,7 @@ static plist_t parse_real_node(char *bnode, uint8_t size)
265 return node_create(NULL, data); 279 return node_create(NULL, data);
266} 280}
267 281
268static plist_t parse_date_node(char *bnode, uint8_t size) 282static plist_t parse_date_node(const char **bnode, uint8_t size)
269{ 283{
270 plist_t node = parse_real_node(bnode, size); 284 plist_t node = parse_real_node(bnode, size);
271 plist_data_t data = plist_get_data(node); 285 plist_data_t data = plist_get_data(node);
@@ -279,13 +293,13 @@ static plist_t parse_date_node(char *bnode, uint8_t size)
279 return node; 293 return node;
280} 294}
281 295
282static plist_t parse_string_node(char *bnode, uint64_t size) 296static plist_t parse_string_node(const char **bnode, uint64_t size)
283{ 297{
284 plist_data_t data = plist_new_plist_data(); 298 plist_data_t data = plist_new_plist_data();
285 299
286 data->type = PLIST_STRING; 300 data->type = PLIST_STRING;
287 data->strval = (char *) malloc(sizeof(char) * (size + 1)); 301 data->strval = (char *) malloc(sizeof(char) * (size + 1));
288 memcpy(data->strval, bnode, size); 302 memcpy(data->strval, *bnode, size);
289 data->strval[size] = '\0'; 303 data->strval[size] = '\0';
290 data->length = strlen(data->strval); 304 data->length = strlen(data->strval);
291 305
@@ -348,7 +362,7 @@ static char *plist_utf16_to_utf8(uint16_t *unistr, long len, long *items_read, l
348 return outbuf; 362 return outbuf;
349} 363}
350 364
351static plist_t parse_unicode_node(char *bnode, uint64_t size) 365static plist_t parse_unicode_node(const char **bnode, uint64_t size)
352{ 366{
353 plist_data_t data = plist_new_plist_data(); 367 plist_data_t data = plist_new_plist_data();
354 uint64_t i = 0; 368 uint64_t i = 0;
@@ -359,7 +373,7 @@ static plist_t parse_unicode_node(char *bnode, uint64_t size)
359 373
360 data->type = PLIST_STRING; 374 data->type = PLIST_STRING;
361 unicodestr = (uint16_t*) malloc(sizeof(uint16_t) * size); 375 unicodestr = (uint16_t*) malloc(sizeof(uint16_t) * size);
362 memcpy(unicodestr, bnode, sizeof(uint16_t) * size); 376 memcpy(unicodestr, *bnode, sizeof(uint16_t) * size);
363 for (i = 0; i < size; i++) 377 for (i = 0; i < size; i++)
364 byte_convert((uint8_t *) (unicodestr + i), sizeof(uint16_t)); 378 byte_convert((uint8_t *) (unicodestr + i), sizeof(uint16_t));
365 379
@@ -375,43 +389,112 @@ static plist_t parse_unicode_node(char *bnode, uint64_t size)
375 return node_create(NULL, data); 389 return node_create(NULL, data);
376} 390}
377 391
378static plist_t parse_data_node(char *bnode, uint64_t size) 392static plist_t parse_data_node(const char **bnode, uint64_t size)
379{ 393{
380 plist_data_t data = plist_new_plist_data(); 394 plist_data_t data = plist_new_plist_data();
381 395
382 data->type = PLIST_DATA; 396 data->type = PLIST_DATA;
383 data->length = size; 397 data->length = size;
384 data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size); 398 data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size);
385 memcpy(data->buff, bnode, sizeof(uint8_t) * size); 399 memcpy(data->buff, *bnode, sizeof(uint8_t) * size);
386 400
387 return node_create(NULL, data); 401 return node_create(NULL, data);
388} 402}
389 403
390static plist_t parse_dict_node(char *bnode, uint64_t size, uint32_t ref_size) 404static plist_t parse_dict_node(struct bplist_data *bplist, const char** bnode, uint64_t size)
391{ 405{
406 uint64_t j;
407 uint64_t str_i = 0, str_j = 0;
408 uint64_t index1, index2;
392 plist_data_t data = plist_new_plist_data(); 409 plist_data_t data = plist_new_plist_data();
393 410
394 data->type = PLIST_DICT; 411 data->type = PLIST_DICT;
395 data->length = size; 412 data->length = size;
396 data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size * ref_size * 2);
397 memcpy(data->buff, bnode, sizeof(uint8_t) * size * ref_size * 2);
398 413
399 return node_create(NULL, data); 414 plist_t node = node_create(NULL, data);
415
416 for (j = 0; j < data->length; j++) {
417 str_i = j * bplist->dict_size;
418 str_j = (j + size) * bplist->dict_size;
419
420 index1 = UINT_TO_HOST((*bnode) + str_i, bplist->dict_size);
421 index2 = UINT_TO_HOST((*bnode) + str_j, bplist->dict_size);
422
423 if (index1 >= bplist->num_objects) {
424 plist_free(node);
425 return NULL;
426 }
427 if (index2 >= bplist->num_objects) {
428 plist_free(node);
429 return NULL;
430 }
431
432 /* process key node */
433 plist_t key = parse_bin_node_at_index(bplist, index1);
434 if (!key) {
435 plist_free(node);
436 return NULL;
437 }
438 /* enforce key type */
439 plist_get_data(key)->type = PLIST_KEY;
440 if (!plist_get_data(key)->strval) {
441 fprintf(stderr, "ERROR: Malformed binary plist dict, invalid key node encountered!\n");
442 plist_free(key);
443 plist_free(node);
444 return NULL;
445 }
446
447 /* process value node */
448 plist_t val = parse_bin_node_at_index(bplist, index2);
449 if (!val) {
450 plist_free(key);
451 plist_free(node);
452 return NULL;
453 }
454
455 node_attach(node, key);
456 node_attach(node, val);
457 }
458
459 return node;
400} 460}
401 461
402static plist_t parse_array_node(char *bnode, uint64_t size, uint32_t ref_size) 462static plist_t parse_array_node(struct bplist_data *bplist, const char** bnode, uint64_t size)
403{ 463{
464 uint64_t j;
465 uint32_t str_j = 0;
466 uint32_t index1;
467
404 plist_data_t data = plist_new_plist_data(); 468 plist_data_t data = plist_new_plist_data();
405 469
406 data->type = PLIST_ARRAY; 470 data->type = PLIST_ARRAY;
407 data->length = size; 471 data->length = size;
408 data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size * ref_size);
409 memcpy(data->buff, bnode, sizeof(uint8_t) * size * ref_size);
410 472
411 return node_create(NULL, data); 473 plist_t node = node_create(NULL, data);
474
475 for (j = 0; j < data->length; j++) {
476 str_j = j * bplist->dict_size;
477 index1 = UINT_TO_HOST((*bnode) + str_j, bplist->dict_size);
478
479 if (index1 >= bplist->num_objects) {
480 plist_free(node);
481 return NULL;
482 }
483
484 /* process value node */
485 plist_t val = parse_bin_node_at_index(bplist, index1);
486 if (!val) {
487 plist_free(node);
488 return NULL;
489 }
490
491 node_attach(node, val);
492 }
493
494 return node;
412} 495}
413 496
414static plist_t parse_uid_node(char *bnode, uint8_t size, char **next_object) 497static plist_t parse_uid_node(const char **bnode, uint8_t size)
415{ 498{
416 plist_data_t data = plist_new_plist_data(); 499 plist_data_t data = plist_new_plist_data();
417 500
@@ -422,7 +505,7 @@ static plist_t parse_uid_node(char *bnode, uint8_t size, char **next_object)
422 case sizeof(uint16_t): 505 case sizeof(uint16_t):
423 case sizeof(uint32_t): 506 case sizeof(uint32_t):
424 case sizeof(uint64_t): 507 case sizeof(uint64_t):
425 memcpy(&data->intval, bnode, size); 508 memcpy(&data->intval, *bnode, size);
426 data->intval = UINT_TO_HOST(&data->intval, size); 509 data->intval = UINT_TO_HOST(&data->intval, size);
427 break; 510 break;
428 default: 511 default:
@@ -430,15 +513,13 @@ static plist_t parse_uid_node(char *bnode, uint8_t size, char **next_object)
430 return NULL; 513 return NULL;
431 }; 514 };
432 515
433 *next_object = bnode + size;
434 data->type = PLIST_UID; 516 data->type = PLIST_UID;
435 data->length = sizeof(uint64_t); 517 data->length = sizeof(uint64_t);
436 518
437 return node_create(NULL, data); 519 return node_create(NULL, data);
438} 520}
439 521
440 522static plist_t parse_bin_node(struct bplist_data *bplist, const char** object)
441static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_object)
442{ 523{
443 uint16_t type = 0; 524 uint16_t type = 0;
444 uint64_t size = 0; 525 uint64_t size = 0;
@@ -446,9 +527,9 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
446 if (!object) 527 if (!object)
447 return NULL; 528 return NULL;
448 529
449 type = (*object) & 0xF0; 530 type = (**object) & BPLIST_MASK;
450 size = (*object) & 0x0F; 531 size = (**object) & BPLIST_FILL;
451 object++; 532 (*object)++;
452 533
453 switch (type) 534 switch (type)
454 { 535 {
@@ -481,7 +562,7 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
481 } 562 }
482 563
483 case BPLIST_UINT: 564 case BPLIST_UINT:
484 return parse_uint_node(object, size, next_object); 565 return parse_uint_node(object, size);
485 566
486 case BPLIST_REAL: 567 case BPLIST_REAL:
487 return parse_real_node(object, size); 568 return parse_real_node(object, size);
@@ -493,9 +574,8 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
493 return parse_date_node(object, size); 574 return parse_date_node(object, size);
494 575
495 case BPLIST_DATA: 576 case BPLIST_DATA:
496 if (0x0F == size) 577 if (BPLIST_FILL == size) {
497 { 578 plist_t size_node = parse_bin_node(bplist, object);
498 plist_t size_node = parse_bin_node(object, dict_size, &object);
499 if (plist_get_node_type(size_node) != PLIST_UINT) 579 if (plist_get_node_type(size_node) != PLIST_UINT)
500 return NULL; 580 return NULL;
501 plist_get_uint_val(size_node, &size); 581 plist_get_uint_val(size_node, &size);
@@ -504,9 +584,8 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
504 return parse_data_node(object, size); 584 return parse_data_node(object, size);
505 585
506 case BPLIST_STRING: 586 case BPLIST_STRING:
507 if (0x0F == size) 587 if (BPLIST_FILL == size) {
508 { 588 plist_t size_node = parse_bin_node(bplist, object);
509 plist_t size_node = parse_bin_node(object, dict_size, &object);
510 if (plist_get_node_type(size_node) != PLIST_UINT) 589 if (plist_get_node_type(size_node) != PLIST_UINT)
511 return NULL; 590 return NULL;
512 plist_get_uint_val(size_node, &size); 591 plist_get_uint_val(size_node, &size);
@@ -515,9 +594,8 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
515 return parse_string_node(object, size); 594 return parse_string_node(object, size);
516 595
517 case BPLIST_UNICODE: 596 case BPLIST_UNICODE:
518 if (0x0F == size) 597 if (BPLIST_FILL == size) {
519 { 598 plist_t size_node = parse_bin_node(bplist, object);
520 plist_t size_node = parse_bin_node(object, dict_size, &object);
521 if (plist_get_node_type(size_node) != PLIST_UINT) 599 if (plist_get_node_type(size_node) != PLIST_UINT)
522 return NULL; 600 return NULL;
523 plist_get_uint_val(size_node, &size); 601 plist_get_uint_val(size_node, &size);
@@ -525,76 +603,64 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
525 } 603 }
526 return parse_unicode_node(object, size); 604 return parse_unicode_node(object, size);
527 605
528 case BPLIST_UNK_0x70: 606 case BPLIST_SET:
529 case BPLIST_ARRAY: 607 case BPLIST_ARRAY:
530 if (0x0F == size) 608 if (BPLIST_FILL == size) {
531 { 609 plist_t size_node = parse_bin_node(bplist, object);
532 plist_t size_node = parse_bin_node(object, dict_size, &object);
533 if (plist_get_node_type(size_node) != PLIST_UINT) 610 if (plist_get_node_type(size_node) != PLIST_UINT)
534 return NULL; 611 return NULL;
535 plist_get_uint_val(size_node, &size); 612 plist_get_uint_val(size_node, &size);
536 plist_free(size_node); 613 plist_free(size_node);
537 } 614 }
538 return parse_array_node(object, size, dict_size); 615 return parse_array_node(bplist, object, size);
539 616
540 case BPLIST_UID: 617 case BPLIST_UID:
541 return parse_uid_node(object, size, next_object); 618 return parse_uid_node(object, size);
542 619
543 case BPLIST_SET:
544 case BPLIST_DICT: 620 case BPLIST_DICT:
545 if (0x0F == size) 621 if (BPLIST_FILL == size) {
546 { 622 plist_t size_node = parse_bin_node(bplist, object);
547 plist_t size_node = parse_bin_node(object, dict_size, &object);
548 if (plist_get_node_type(size_node) != PLIST_UINT) 623 if (plist_get_node_type(size_node) != PLIST_UINT)
549 return NULL; 624 return NULL;
550 plist_get_uint_val(size_node, &size); 625 plist_get_uint_val(size_node, &size);
551 plist_free(size_node); 626 plist_free(size_node);
552 } 627 }
553 return parse_dict_node(object, size, dict_size); 628 return parse_dict_node(bplist, object, size);
554 default: 629 default:
555 return NULL; 630 return NULL;
556 } 631 }
557 return NULL; 632 return NULL;
558} 633}
559 634
560static void* copy_plist_data(const void* src) 635static plist_t parse_bin_node_at_index(struct bplist_data *bplist, uint32_t node_index)
561{ 636{
562 plist_data_t srcdata = (plist_data_t) src; 637 int i;
563 plist_data_t dstdata = plist_new_plist_data(); 638 const char* ptr;
639 plist_t plist;
564 640
565 dstdata->type = srcdata->type; 641 ptr = bplist->data + UINT_TO_HOST(bplist->offset_table + node_index * bplist->offset_size, bplist->offset_size);
566 dstdata->length = srcdata->length; 642 /* make sure the node offset is in a sane range */
567 switch (dstdata->type) 643 if ((ptr < bplist->data) || (ptr >= bplist->offset_table)) {
568 { 644 return NULL;
569 case PLIST_BOOLEAN:
570 dstdata->boolval = srcdata->boolval;
571 break;
572 case PLIST_UINT:
573 dstdata->intval = srcdata->intval;
574 break;
575 case PLIST_DATE:
576 dstdata->timeval.tv_sec = srcdata->timeval.tv_sec;
577 dstdata->timeval.tv_usec = srcdata->timeval.tv_usec;
578 break;
579 case PLIST_REAL:
580 dstdata->realval = srcdata->realval;
581 break;
582 case PLIST_KEY:
583 case PLIST_STRING:
584 dstdata->strval = strdup(srcdata->strval);
585 break;
586 case PLIST_DATA:
587 dstdata->buff = (uint8_t*) malloc(sizeof(uint8_t) * srcdata->length);
588 memcpy(dstdata->buff, srcdata->buff, sizeof(uint8_t) * srcdata->length);
589 break;
590 case PLIST_UID:
591 dstdata->intval = srcdata->intval;
592 break;
593 default:
594 break;
595 } 645 }
596 646
597 return dstdata; 647 /* store node_index for current recursion level */
648 bplist->used_indexes[bplist->level] = node_index;
649 /* recursion check */
650 if (bplist->level > 0) {
651 for (i = bplist->level-1; i >= 0; i--) {
652 if (bplist->used_indexes[i] == bplist->used_indexes[bplist->level]) {
653 fprintf(stderr, "Recursion detected in binary plist. Aborting.\n");
654 return NULL;
655 }
656 }
657 }
658
659 /* finally parse node */
660 bplist->level++;
661 plist = parse_bin_node(bplist, &ptr);
662 bplist->level--;
663 return plist;
598} 664}
599 665
600PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist) 666PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist)
@@ -602,19 +668,11 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t *
602 char *trailer = NULL; 668 char *trailer = NULL;
603 669
604 uint8_t offset_size = 0; 670 uint8_t offset_size = 0;
605 uint8_t dict_param_size = 0; 671 uint8_t dict_size = 0;
606 uint64_t num_objects = 0; 672 uint64_t num_objects = 0;
607 uint64_t root_object = 0; 673 uint64_t root_object = 0;
608 uint64_t offset_table_index = 0; 674 uint64_t offset_table_index = 0;
609 675
610 plist_t *nodeslist = NULL;
611 uint64_t i = 0;
612 uint64_t current_offset = 0;
613 char *offset_table = NULL;
614 uint32_t j = 0, str_i = 0, str_j = 0;
615 uint32_t index1 = 0, index2 = 0;
616
617
618 //first check we have enough data 676 //first check we have enough data
619 if (!(length >= BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE + BPLIST_TRL_SIZE)) 677 if (!(length >= BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE + BPLIST_TRL_SIZE))
620 return; 678 return;
@@ -629,7 +687,7 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t *
629 trailer = (char *) (plist_bin + (length - BPLIST_TRL_SIZE)); 687 trailer = (char *) (plist_bin + (length - BPLIST_TRL_SIZE));
630 688
631 offset_size = trailer[BPLIST_TRL_OFFSIZE_IDX]; 689 offset_size = trailer[BPLIST_TRL_OFFSIZE_IDX];
632 dict_param_size = trailer[BPLIST_TRL_PARMSIZE_IDX]; 690 dict_size = trailer[BPLIST_TRL_PARMSIZE_IDX];
633 num_objects = be64dec(trailer + BPLIST_TRL_NUMOBJ_IDX); 691 num_objects = be64dec(trailer + BPLIST_TRL_NUMOBJ_IDX);
634 root_object = be64dec(trailer + BPLIST_TRL_ROOTOBJ_IDX); 692 root_object = be64dec(trailer + BPLIST_TRL_ROOTOBJ_IDX);
635 offset_table_index = be64dec(trailer + BPLIST_TRL_OFFTAB_IDX); 693 offset_table_index = be64dec(trailer + BPLIST_TRL_OFFTAB_IDX);
@@ -637,122 +695,22 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t *
637 if (num_objects == 0) 695 if (num_objects == 0)
638 return; 696 return;
639 697
640 //allocate serialized array of nodes 698 if (root_object >= num_objects)
641 nodeslist = (plist_t *) malloc(sizeof(plist_t) * num_objects);
642
643 if (!nodeslist)
644 return; 699 return;
645 700
646 //parse serialized nodes 701 struct bplist_data bplist;
647 offset_table = (char *) (plist_bin + offset_table_index); 702 bplist.data = plist_bin;
648 for (i = 0; i < num_objects; i++) 703 bplist.size = length;
649 { 704 bplist.num_objects = num_objects;
650 char *obj = NULL; 705 bplist.dict_size = dict_size;
651 current_offset = UINT_TO_HOST(offset_table + i * offset_size, offset_size); 706 bplist.offset_size = offset_size;
652 707 bplist.offset_table = (char *) (plist_bin + offset_table_index);
653 obj = (char *) (plist_bin + current_offset); 708 bplist.level = 0;
654 nodeslist[i] = parse_bin_node(obj, dict_param_size, &obj); 709 bplist.used_indexes = (uint32_t*)malloc(sizeof(uint32_t) * num_objects);
655 }
656
657 //setup children for structured types
658 for (i = 0; i < num_objects; i++)
659 {
660
661 plist_data_t data = plist_get_data(nodeslist[i]);
662 if (!data) {
663 break;
664 }
665 710
666 switch (data->type) 711 *plist = parse_bin_node_at_index(&bplist, root_object);
667 {
668 case PLIST_DICT:
669 for (j = 0; j < data->length; j++)
670 {
671 node_t* n = NULL;
672 str_i = j * dict_param_size;
673 str_j = (j + data->length) * dict_param_size;
674
675 index1 = UINT_TO_HOST(data->buff + str_i, dict_param_size);
676 index2 = UINT_TO_HOST(data->buff + str_j, dict_param_size);
677
678 // process key node
679 if (index1 < num_objects)
680 {
681 // is node already attached?
682 if (NODE_IS_ROOT(nodeslist[index1])) {
683 // use original
684 n = nodeslist[index1];
685 } else {
686 // use a copy, because this node is already attached elsewhere
687 n = node_copy_deep(nodeslist[index1], copy_plist_data);
688 }
689
690 // enforce key type
691 plist_get_data(n)->type = PLIST_KEY;
692
693 // attach key node
694 node_attach(nodeslist[i], n);
695 }
696
697 // process value node
698 if (index2 < num_objects)
699 {
700 // is node already attached?
701 if (NODE_IS_ROOT(nodeslist[index2])) {
702 // use original
703 n = nodeslist[index2];
704 } else {
705 // use a copy, because this node is already attached elsewhere
706 n = node_copy_deep(nodeslist[index2], copy_plist_data);
707
708 // ensure key type is never used for values, especially if we copy a key node
709 if (plist_get_data(n)->type == PLIST_KEY) {
710 plist_get_data(n)->type = PLIST_STRING;
711 }
712 }
713
714 // attach value node
715 node_attach(nodeslist[i], n);
716 }
717 }
718 break;
719 712
720 case PLIST_ARRAY: 713 free(bplist.used_indexes);
721 for (j = 0; j < data->length; j++)
722 {
723 str_j = j * dict_param_size;
724 index1 = UINT_TO_HOST(data->buff + str_j, dict_param_size);
725
726 if (index1 < num_objects)
727 {
728 if (NODE_IS_ROOT(nodeslist[index1]))
729 node_attach(nodeslist[i], nodeslist[index1]);
730 else
731 node_attach(nodeslist[i], node_copy_deep(nodeslist[index1], copy_plist_data));
732 }
733 }
734 break;
735 default:
736 break;
737 }
738 }
739
740 *plist = nodeslist[root_object];
741
742 // free unreferenced nodes that would otherwise leak memory
743 for (i = 0; i < num_objects; i++) {
744 plist_data_t data = plist_get_data(nodeslist[i]);
745 if ((data->type == PLIST_DICT) || (data->type == PLIST_ARRAY)) {
746 free(data->buff);
747 data->buff = NULL;
748 }
749 if (i == root_object) continue;
750 node_t* node = (node_t*)nodeslist[i];
751 if (node && NODE_IS_ROOT(node)) {
752 plist_free(node);
753 }
754 }
755 free(nodeslist);
756} 714}
757 715
758static unsigned int plist_data_hash(const void* key) 716static unsigned int plist_data_hash(const void* key)