diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/jplist.c | 79 |
1 files changed, 48 insertions, 31 deletions
diff --git a/src/jplist.c b/src/jplist.c index 88cce28..2182079 100644 --- a/src/jplist.c +++ b/src/jplist.c | |||
| @@ -418,16 +418,21 @@ PLIST_API int plist_to_json(plist_t plist, char **json, uint32_t* length, int pr | |||
| 418 | return PLIST_ERR_SUCCESS; | 418 | return PLIST_ERR_SUCCESS; |
| 419 | } | 419 | } |
| 420 | 420 | ||
| 421 | static plist_t parse_primitive(const char* js, jsmntok_t* tokens, int* index) | 421 | typedef struct { |
| 422 | jsmntok_t* tokens; | ||
| 423 | int count; | ||
| 424 | } jsmntok_info_t; | ||
| 425 | |||
| 426 | static plist_t parse_primitive(const char* js, jsmntok_info_t* ti, int* index) | ||
| 422 | { | 427 | { |
| 423 | if (tokens[*index].type != JSMN_PRIMITIVE) { | 428 | if (ti->tokens[*index].type != JSMN_PRIMITIVE) { |
| 424 | PLIST_JSON_ERR("%s: token type != JSMN_PRIMITIVE\n", __func__); | 429 | PLIST_JSON_ERR("%s: token type != JSMN_PRIMITIVE\n", __func__); |
| 425 | return NULL; | 430 | return NULL; |
| 426 | } | 431 | } |
| 427 | plist_t val = NULL; | 432 | plist_t val = NULL; |
| 428 | const char* str_val = js + tokens[*index].start; | 433 | const char* str_val = js + ti->tokens[*index].start; |
| 429 | const char* str_end = js + tokens[*index].end; | 434 | const char* str_end = js + ti->tokens[*index].end; |
| 430 | size_t str_len = tokens[*index].end - tokens[*index].start; | 435 | size_t str_len = ti->tokens[*index].end - ti->tokens[*index].start; |
| 431 | if (!strncmp("false", str_val, str_len)) { | 436 | if (!strncmp("false", str_val, str_len)) { |
| 432 | val = plist_new_bool(0); | 437 | val = plist_new_bool(0); |
| 433 | } else if (!strncmp("true", str_val, str_len)) { | 438 | } else if (!strncmp("true", str_val, str_len)) { |
| @@ -540,15 +545,15 @@ static char* unescape_string(const char* str_val, size_t str_len, size_t *new_le | |||
| 540 | return strval; | 545 | return strval; |
| 541 | } | 546 | } |
| 542 | 547 | ||
| 543 | static plist_t parse_string(const char* js, jsmntok_t* tokens, int* index) | 548 | static plist_t parse_string(const char* js, jsmntok_info_t* ti, int* index) |
| 544 | { | 549 | { |
| 545 | if (tokens[*index].type != JSMN_STRING) { | 550 | if (ti->tokens[*index].type != JSMN_STRING) { |
| 546 | PLIST_JSON_ERR("%s: token type != JSMN_STRING\n", __func__); | 551 | PLIST_JSON_ERR("%s: token type != JSMN_STRING\n", __func__); |
| 547 | return NULL; | 552 | return NULL; |
| 548 | } | 553 | } |
| 549 | 554 | ||
| 550 | size_t str_len = 0; ; | 555 | size_t str_len = 0; ; |
| 551 | char* strval = unescape_string(js + tokens[*index].start, tokens[*index].end - tokens[*index].start, &str_len); | 556 | char* strval = unescape_string(js + ti->tokens[*index].start, ti->tokens[*index].end - ti->tokens[*index].start, &str_len); |
| 552 | if (!strval) { | 557 | if (!strval) { |
| 553 | return NULL; | 558 | return NULL; |
| 554 | } | 559 | } |
| @@ -564,32 +569,36 @@ static plist_t parse_string(const char* js, jsmntok_t* tokens, int* index) | |||
| 564 | return node; | 569 | return node; |
| 565 | } | 570 | } |
| 566 | 571 | ||
| 567 | static plist_t parse_object(const char* js, jsmntok_t* tokens, int* index); | 572 | static plist_t parse_object(const char* js, jsmntok_info_t* ti, int* index); |
| 568 | 573 | ||
| 569 | static plist_t parse_array(const char* js, jsmntok_t* tokens, int* index) | 574 | static plist_t parse_array(const char* js, jsmntok_info_t* ti, int* index) |
| 570 | { | 575 | { |
| 571 | if (tokens[*index].type != JSMN_ARRAY) { | 576 | if (ti->tokens[*index].type != JSMN_ARRAY) { |
| 572 | PLIST_JSON_ERR("%s: token type != JSMN_ARRAY\n", __func__); | 577 | PLIST_JSON_ERR("%s: token type != JSMN_ARRAY\n", __func__); |
| 573 | return NULL; | 578 | return NULL; |
| 574 | } | 579 | } |
| 575 | plist_t arr = plist_new_array(); | 580 | plist_t arr = plist_new_array(); |
| 576 | int num_tokens = tokens[*index].size; | 581 | int num_tokens = ti->tokens[*index].size; |
| 577 | int num; | 582 | int num; |
| 578 | int j = (*index)+1; | 583 | int j = (*index)+1; |
| 579 | for (num = 0; num < num_tokens; num++) { | 584 | for (num = 0; num < num_tokens; num++) { |
| 585 | if (j >= ti->count) { | ||
| 586 | PLIST_JSON_ERR("%s: token index out of valid range\n", __func__); | ||
| 587 | return NULL; | ||
| 588 | } | ||
| 580 | plist_t val = NULL; | 589 | plist_t val = NULL; |
| 581 | switch (tokens[j].type) { | 590 | switch (ti->tokens[j].type) { |
| 582 | case JSMN_OBJECT: | 591 | case JSMN_OBJECT: |
| 583 | val = parse_object(js, tokens, &j); | 592 | val = parse_object(js, ti, &j); |
| 584 | break; | 593 | break; |
| 585 | case JSMN_ARRAY: | 594 | case JSMN_ARRAY: |
| 586 | val = parse_array(js, tokens, &j); | 595 | val = parse_array(js, ti, &j); |
| 587 | break; | 596 | break; |
| 588 | case JSMN_STRING: | 597 | case JSMN_STRING: |
| 589 | val = parse_string(js, tokens, &j); | 598 | val = parse_string(js, ti, &j); |
| 590 | break; | 599 | break; |
| 591 | case JSMN_PRIMITIVE: | 600 | case JSMN_PRIMITIVE: |
| 592 | val = parse_primitive(js, tokens, &j); | 601 | val = parse_primitive(js, ti, &j); |
| 593 | break; | 602 | break; |
| 594 | default: | 603 | default: |
| 595 | break; | 604 | break; |
| @@ -605,19 +614,23 @@ static plist_t parse_array(const char* js, jsmntok_t* tokens, int* index) | |||
| 605 | return arr; | 614 | return arr; |
| 606 | } | 615 | } |
| 607 | 616 | ||
| 608 | static plist_t parse_object(const char* js, jsmntok_t* tokens, int* index) | 617 | static plist_t parse_object(const char* js, jsmntok_info_t* ti, int* index) |
| 609 | { | 618 | { |
| 610 | if (tokens[*index].type != JSMN_OBJECT) { | 619 | if (ti->tokens[*index].type != JSMN_OBJECT) { |
| 611 | PLIST_JSON_ERR("%s: token type != JSMN_OBJECT\n", __func__); | 620 | PLIST_JSON_ERR("%s: token type != JSMN_OBJECT\n", __func__); |
| 612 | return NULL; | 621 | return NULL; |
| 613 | } | 622 | } |
| 614 | plist_t obj = plist_new_dict(); | 623 | plist_t obj = plist_new_dict(); |
| 615 | int num_tokens = tokens[*index].size; | 624 | int num_tokens = ti->tokens[*index].size; |
| 616 | int num; | 625 | int num; |
| 617 | int j = (*index)+1; | 626 | int j = (*index)+1; |
| 618 | for (num = 0; num < num_tokens; num++) { | 627 | for (num = 0; num < num_tokens; num++) { |
| 619 | if (tokens[j].type == JSMN_STRING) { | 628 | if (j >= ti->count) { |
| 620 | char* key = unescape_string(js + tokens[j].start, tokens[j].end - tokens[j].start, NULL); | 629 | PLIST_JSON_ERR("%s: token index out of valid range\n", __func__); |
| 630 | return NULL; | ||
| 631 | } | ||
| 632 | if (ti->tokens[j].type == JSMN_STRING) { | ||
| 633 | char* key = unescape_string(js + ti->tokens[j].start, ti->tokens[j].end - ti->tokens[j].start, NULL); | ||
| 621 | if (!key) { | 634 | if (!key) { |
| 622 | plist_free(obj); | 635 | plist_free(obj); |
| 623 | return NULL; | 636 | return NULL; |
| @@ -625,24 +638,27 @@ static plist_t parse_object(const char* js, jsmntok_t* tokens, int* index) | |||
| 625 | plist_t val = NULL; | 638 | plist_t val = NULL; |
| 626 | j++; | 639 | j++; |
| 627 | num++; | 640 | num++; |
| 628 | switch (tokens[j].type) { | 641 | switch (ti->tokens[j].type) { |
| 629 | case JSMN_OBJECT: | 642 | case JSMN_OBJECT: |
| 630 | val = parse_object(js, tokens, &j); | 643 | val = parse_object(js, ti, &j); |
| 631 | break; | 644 | break; |
| 632 | case JSMN_ARRAY: | 645 | case JSMN_ARRAY: |
| 633 | val = parse_array(js, tokens, &j); | 646 | val = parse_array(js, ti, &j); |
| 634 | break; | 647 | break; |
| 635 | case JSMN_STRING: | 648 | case JSMN_STRING: |
| 636 | val = parse_string(js, tokens, &j); | 649 | val = parse_string(js, ti, &j); |
| 637 | break; | 650 | break; |
| 638 | case JSMN_PRIMITIVE: | 651 | case JSMN_PRIMITIVE: |
| 639 | val = parse_primitive(js, tokens, &j); | 652 | val = parse_primitive(js, ti, &j); |
| 640 | break; | 653 | break; |
| 641 | default: | 654 | default: |
| 642 | break; | 655 | break; |
| 643 | } | 656 | } |
| 644 | if (val) { | 657 | if (val) { |
| 645 | plist_dict_set_item(obj, key, val); | 658 | plist_dict_set_item(obj, key, val); |
| 659 | } else { | ||
| 660 | plist_free(obj); | ||
| 661 | return NULL; | ||
| 646 | } | 662 | } |
| 647 | free(key); | 663 | free(key); |
| 648 | } else { | 664 | } else { |
| @@ -707,18 +723,19 @@ PLIST_API int plist_from_json(const char *json, uint32_t length, plist_t * plist | |||
| 707 | } | 723 | } |
| 708 | 724 | ||
| 709 | int startindex = 0; | 725 | int startindex = 0; |
| 726 | jsmntok_info_t ti = { tokens, parser.toknext }; | ||
| 710 | switch (tokens[startindex].type) { | 727 | switch (tokens[startindex].type) { |
| 711 | case JSMN_PRIMITIVE: | 728 | case JSMN_PRIMITIVE: |
| 712 | *plist = parse_primitive(json, tokens, &startindex); | 729 | *plist = parse_primitive(json, &ti, &startindex); |
| 713 | break; | 730 | break; |
| 714 | case JSMN_STRING: | 731 | case JSMN_STRING: |
| 715 | *plist = parse_string(json, tokens, &startindex); | 732 | *plist = parse_string(json, &ti, &startindex); |
| 716 | break; | 733 | break; |
| 717 | case JSMN_ARRAY: | 734 | case JSMN_ARRAY: |
| 718 | *plist = parse_array(json, tokens, &startindex); | 735 | *plist = parse_array(json, &ti, &startindex); |
| 719 | break; | 736 | break; |
| 720 | case JSMN_OBJECT: | 737 | case JSMN_OBJECT: |
| 721 | *plist = parse_object(json, tokens, &startindex); | 738 | *plist = parse_object(json, &ti, &startindex); |
| 722 | break; | 739 | break; |
| 723 | default: | 740 | default: |
| 724 | break; | 741 | break; |
