diff options
| author | 2017-03-26 20:06:57 +0200 | |
|---|---|---|
| committer | 2017-03-26 20:06:57 +0200 | |
| commit | dccd9290745345896e3a4a73154576a599fd8b7b (patch) | |
| tree | 595a83e656503420d0a6b10c0173b680cbedac08 /src/bplist.c | |
| parent | 71bcd3b65e0a40bcdd2bfbdea07f96cce03a8a8f (diff) | |
| download | libplist-dccd9290745345896e3a4a73154576a599fd8b7b.tar.gz libplist-dccd9290745345896e3a4a73154576a599fd8b7b.tar.bz2 | |
bplist: Make sure sanity checks work on 32bit platforms
Because on 32-bit platforms 32-bit pointers and 64-bit sizes have been
used for the sanity checks of the offset table and object references,
the range checks would fail in certain interger-overflowish situations,
causing heap buffer overflows or other unwanted behavior.
Fixed by wideing the operands in question to 64-bit.
Diffstat (limited to 'src/bplist.c')
| -rw-r--r-- | src/bplist.c | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/src/bplist.c b/src/bplist.c index 7d21b27..eede7a7 100644 --- a/src/bplist.c +++ b/src/bplist.c | |||
| @@ -561,6 +561,8 @@ static plist_t parse_bin_node(struct bplist_data *bplist, const char** object) | |||
| 561 | { | 561 | { |
| 562 | uint16_t type = 0; | 562 | uint16_t type = 0; |
| 563 | uint64_t size = 0; | 563 | uint64_t size = 0; |
| 564 | uint64_t pobject = 0; | ||
| 565 | uint64_t poffset_table = (uint64_t)bplist->offset_table; | ||
| 564 | 566 | ||
| 565 | if (!object) | 567 | if (!object) |
| 566 | return NULL; | 568 | return NULL; |
| @@ -598,6 +600,8 @@ static plist_t parse_bin_node(struct bplist_data *bplist, const char** object) | |||
| 598 | } | 600 | } |
| 599 | } | 601 | } |
| 600 | 602 | ||
| 603 | pobject = (uint64_t)*object; | ||
| 604 | |||
| 601 | switch (type) | 605 | switch (type) |
| 602 | { | 606 | { |
| 603 | 607 | ||
| @@ -629,14 +633,14 @@ static plist_t parse_bin_node(struct bplist_data *bplist, const char** object) | |||
| 629 | } | 633 | } |
| 630 | 634 | ||
| 631 | case BPLIST_UINT: | 635 | case BPLIST_UINT: |
| 632 | if (*object + (uint64_t)(1 << size) > bplist->offset_table) { | 636 | if (pobject + (uint64_t)(1 << size) > poffset_table) { |
| 633 | PLIST_BIN_ERR("%s: BPLIST_UINT data bytes point outside of valid range\n", __func__); | 637 | PLIST_BIN_ERR("%s: BPLIST_UINT data bytes point outside of valid range\n", __func__); |
| 634 | return NULL; | 638 | return NULL; |
| 635 | } | 639 | } |
| 636 | return parse_uint_node(object, size); | 640 | return parse_uint_node(object, size); |
| 637 | 641 | ||
| 638 | case BPLIST_REAL: | 642 | case BPLIST_REAL: |
| 639 | if (*object + (uint64_t)(1 << size) > bplist->offset_table) { | 643 | if (pobject + (uint64_t)(1 << size) > poffset_table) { |
| 640 | PLIST_BIN_ERR("%s: BPLIST_REAL data bytes point outside of valid range\n", __func__); | 644 | PLIST_BIN_ERR("%s: BPLIST_REAL data bytes point outside of valid range\n", __func__); |
| 641 | return NULL; | 645 | return NULL; |
| 642 | } | 646 | } |
| @@ -647,21 +651,21 @@ static plist_t parse_bin_node(struct bplist_data *bplist, const char** object) | |||
| 647 | PLIST_BIN_ERR("%s: invalid data size for BPLIST_DATE node\n", __func__); | 651 | PLIST_BIN_ERR("%s: invalid data size for BPLIST_DATE node\n", __func__); |
| 648 | return NULL; | 652 | return NULL; |
| 649 | } | 653 | } |
| 650 | if (*object + (uint64_t)(1 << size) > bplist->offset_table) { | 654 | if (pobject + (uint64_t)(1 << size) > poffset_table) { |
| 651 | PLIST_BIN_ERR("%s: BPLIST_DATE data bytes point outside of valid range\n", __func__); | 655 | PLIST_BIN_ERR("%s: BPLIST_DATE data bytes point outside of valid range\n", __func__); |
| 652 | return NULL; | 656 | return NULL; |
| 653 | } | 657 | } |
| 654 | return parse_date_node(object, size); | 658 | return parse_date_node(object, size); |
| 655 | 659 | ||
| 656 | case BPLIST_DATA: | 660 | case BPLIST_DATA: |
| 657 | if (*object + size < *object || *object + size > bplist->offset_table) { | 661 | if (pobject + size < pobject || pobject + size > poffset_table) { |
| 658 | PLIST_BIN_ERR("%s: BPLIST_DATA data bytes point outside of valid range\n", __func__); | 662 | PLIST_BIN_ERR("%s: BPLIST_DATA data bytes point outside of valid range\n", __func__); |
| 659 | return NULL; | 663 | return NULL; |
| 660 | } | 664 | } |
| 661 | return parse_data_node(object, size); | 665 | return parse_data_node(object, size); |
| 662 | 666 | ||
| 663 | case BPLIST_STRING: | 667 | case BPLIST_STRING: |
| 664 | if (*object + size < *object || *object + size > bplist->offset_table) { | 668 | if (pobject + size < pobject || pobject + size > poffset_table) { |
| 665 | PLIST_BIN_ERR("%s: BPLIST_STRING data bytes point outside of valid range\n", __func__); | 669 | PLIST_BIN_ERR("%s: BPLIST_STRING data bytes point outside of valid range\n", __func__); |
| 666 | return NULL; | 670 | return NULL; |
| 667 | } | 671 | } |
| @@ -672,7 +676,7 @@ static plist_t parse_bin_node(struct bplist_data *bplist, const char** object) | |||
| 672 | PLIST_BIN_ERR("%s: Integer overflow when calculating BPLIST_UNICODE data size.\n", __func__); | 676 | PLIST_BIN_ERR("%s: Integer overflow when calculating BPLIST_UNICODE data size.\n", __func__); |
| 673 | return NULL; | 677 | return NULL; |
| 674 | } | 678 | } |
| 675 | if (*object + size*2 < *object || *object + size*2 > bplist->offset_table) { | 679 | if (pobject + size*2 < pobject || pobject + size*2 > poffset_table) { |
| 676 | PLIST_BIN_ERR("%s: BPLIST_UNICODE data bytes point outside of valid range\n", __func__); | 680 | PLIST_BIN_ERR("%s: BPLIST_UNICODE data bytes point outside of valid range\n", __func__); |
| 677 | return NULL; | 681 | return NULL; |
| 678 | } | 682 | } |
| @@ -680,21 +684,21 @@ static plist_t parse_bin_node(struct bplist_data *bplist, const char** object) | |||
| 680 | 684 | ||
| 681 | case BPLIST_SET: | 685 | case BPLIST_SET: |
| 682 | case BPLIST_ARRAY: | 686 | case BPLIST_ARRAY: |
| 683 | if (*object + size < *object || *object + size > bplist->offset_table) { | 687 | if (pobject + size < pobject || pobject + size > poffset_table) { |
| 684 | PLIST_BIN_ERR("%s: BPLIST_ARRAY data bytes point outside of valid range\n", __func__); | 688 | PLIST_BIN_ERR("%s: BPLIST_ARRAY data bytes point outside of valid range\n", __func__); |
| 685 | return NULL; | 689 | return NULL; |
| 686 | } | 690 | } |
| 687 | return parse_array_node(bplist, object, size); | 691 | return parse_array_node(bplist, object, size); |
| 688 | 692 | ||
| 689 | case BPLIST_UID: | 693 | case BPLIST_UID: |
| 690 | if (*object + size+1 > bplist->offset_table) { | 694 | if (pobject + size+1 > poffset_table) { |
| 691 | PLIST_BIN_ERR("%s: BPLIST_UID data bytes point outside of valid range\n", __func__); | 695 | PLIST_BIN_ERR("%s: BPLIST_UID data bytes point outside of valid range\n", __func__); |
| 692 | return NULL; | 696 | return NULL; |
| 693 | } | 697 | } |
| 694 | return parse_uid_node(object, size); | 698 | return parse_uid_node(object, size); |
| 695 | 699 | ||
| 696 | case BPLIST_DICT: | 700 | case BPLIST_DICT: |
| 697 | if (*object + size < *object || *object + size > bplist->offset_table) { | 701 | if (pobject + size < pobject || pobject + size > poffset_table) { |
| 698 | PLIST_BIN_ERR("%s: BPLIST_DICT data bytes point outside of valid range\n", __func__); | 702 | PLIST_BIN_ERR("%s: BPLIST_DICT data bytes point outside of valid range\n", __func__); |
| 699 | return NULL; | 703 | return NULL; |
| 700 | } | 704 | } |
| @@ -830,7 +834,7 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * | |||
| 830 | return; | 834 | return; |
| 831 | } | 835 | } |
| 832 | 836 | ||
| 833 | if (offset_table + num_objects * offset_size > end_data) { | 837 | if ((uint64_t)offset_table + num_objects * offset_size > (uint64_t)end_data) { |
| 834 | PLIST_BIN_ERR("offset table points outside of valid range\n"); | 838 | PLIST_BIN_ERR("offset table points outside of valid range\n"); |
| 835 | return; | 839 | return; |
| 836 | } | 840 | } |
