From 0d476a853eae2578c5c835a6b68feb27d665b4e9 Mon Sep 17 00:00:00 2001 From: TristanInSec Date: Fri, 12 Jun 2026 12:29:40 -0400 Subject: [PATCH] Fix heap OOB reads in B-tree and extended attribute parsing pst_build_id_ptr: validate item_count * entry_size against block size. pst_build_desc_ptr: validate entry_size is positive. Extended attributes: validate tint + offset against headerbuffer size. --- src/libpst.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/libpst.c b/src/libpst.c index 1938854..dc117af 100644 --- a/src/libpst.c +++ b/src/libpst.c @@ -777,11 +777,16 @@ int pst_load_extended_attributes(pst_file *pf) { xattrib.extended, xattrib.type, xattrib.map)); if (xattrib.type & 0x0001) { // if the Bit 1 is set // pointer to Unicode field in buffer - if (xattrib.extended < hsize) { + if (xattrib.extended + sizeof(tint) <= hsize) { char *wt; // copy the size of the header. It is 32 bit int memcpy(&tint, &(headerbuffer[xattrib.extended]), sizeof(tint)); LE32_CPU(tint); + if (tint < 0 || xattrib.extended + sizeof(tint) + (size_t)tint > hsize) { + DEBUG_WARN(("xattrib Unicode field length %i exceeds buffer\n", tint)); + free(ptr); + continue; + } wt = (char*) pst_malloc((size_t)(tint+2)); // plus 2 for a uni-code zero memset(wt, 0, (size_t)(tint+2)); memcpy(wt, &(headerbuffer[xattrib.extended+sizeof(tint)]), (size_t)tint); @@ -1077,6 +1082,12 @@ static int pst_build_id_ptr(pst_file *pf, int64_t offset, int32_t depth, uint64_ } int entry_size = (int32_t)(unsigned)(buf[ENTRY_SIZE_OFFSET]); DEBUG_INFO(("count %" PRIi32 " max %" PRIi32 " size %i\n", item_count, count_max, entry_size)); + if (entry_size <= 0 || (int64_t)item_count * entry_size > read_size) { + DEBUG_WARN(("item_count * entry_size exceeds block size\n")); + if (buf) free(buf); + DEBUG_RET(); + return -1; + } if (buf[LEVEL_INDICATOR_OFFSET] == '\0') { // this node contains leaf pointers x = 0; @@ -1180,6 +1191,12 @@ static int pst_build_desc_ptr (pst_file *pf, int64_t offset, int32_t depth, uint return -1; } int32_t entry_size = (int32_t)(unsigned)(buf[ENTRY_SIZE_OFFSET]); + if (entry_size <= 0) { + DEBUG_WARN(("Invalid entry_size %i\n", entry_size)); + if (buf) free(buf); + DEBUG_RET(); + return -1; + } if (buf[LEVEL_INDICATOR_OFFSET] == '\0') { // this node contains leaf pointers DEBUG_HEXDUMPC(buf, DESC_BLOCK_SIZE, entry_size);