File libplist-boo1029631-32bit.patch of Package libplist.6782
From dccd9290745345896e3a4a73154576a599fd8b7b Mon Sep 17 00:00:00 2001
From: Nikias Bassen <nikias@gmx.li>
Date: Sun, 26 Mar 2017 20:06:57 +0200
Subject: [PATCH] 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.
Backported by Mike Gorse <mgorse@suse.com>
---
diff -urp libplist-1.12.orig/src/bplist.c libplist-1.12/src/bplist.c
--- libplist-1.12.orig/src/bplist.c 2017-05-01 13:03:48.037796333 -0500
+++ libplist-1.12/src/bplist.c 2017-05-02 14:12:25.669352857 -0500
@@ -544,6 +544,8 @@ static plist_t parse_bin_node(struct bpl
{
uint16_t type = 0;
uint64_t size = 0;
+ uint64_t pobject = 0;
+ uint64_t poffset_table = (uint64_t)bplist->offset_table;
if (!object)
return NULL;
@@ -577,6 +579,8 @@ static plist_t parse_bin_node(struct bpl
}
}
+ pobject = (uint64_t)*object;
+
switch (type)
{
@@ -608,12 +612,12 @@ static plist_t parse_bin_node(struct bpl
}
case BPLIST_UINT:
- if (*object - bplist->data + (uint64_t)(1 << size) >= bplist->size)
+ if (pobject + (uint64_t)(1 << size) > poffset_table)
return NULL;
return parse_uint_node(object, size);
case BPLIST_REAL:
- if (*object - bplist->data + (uint64_t)(1 << size) >= bplist->size)
+ if (pobject + (uint64_t)(1 << size) > poffset_table)
return NULL;
return parse_real_node(object, size);
@@ -621,36 +625,38 @@ static plist_t parse_bin_node(struct bpl
if (3 != size)
return NULL;
else
- if (*object - bplist->data + (uint64_t)(1 << size) >= bplist->size)
+ if (pobject + (uint64_t)(1 << size) > poffset_table)
return NULL;
return parse_date_node(object, size);
case BPLIST_DATA:
- if (*object - bplist->data + size >= bplist->size)
+ if (pobject + size < pobject || pobject + size > poffset_table)
return NULL;
return parse_data_node(object, size);
case BPLIST_STRING:
- if (*object - bplist->data + size >= bplist->size)
+ if (pobject + size < pobject || pobject + size > poffset_table)
return NULL;
return parse_string_node(object, size);
case BPLIST_UNICODE:
- if (*object - bplist->data + size * 2 >= bplist->size)
+ if (pobject + size*2 < pobject || pobject + size*2 > poffset_table)
return NULL;
return parse_unicode_node(object, size);
case BPLIST_SET:
case BPLIST_ARRAY:
- if (*object - bplist->data + size >= bplist->size)
+ if (pobject + size < pobject || pobject + size > poffset_table)
return NULL;
return parse_array_node(bplist, object, size);
case BPLIST_UID:
+ if (pobject + size+1 > poffset_table)
+ return NULL;
return parse_uid_node(object, size);
case BPLIST_DICT:
- if (*object - bplist->data + size >= bplist->size)
+ if (pobject + size < pobject || pobject + size > poffset_table)
return NULL;
return parse_dict_node(bplist, object, size);