From ed1e60f0214b244a4ed188e2f424c4a5440aa557 Mon Sep 17 00:00:00 2001 From: raineth Date: Thu, 13 Apr 2023 21:45:33 -0400 Subject: [PATCH] Fix crashes/freezes in VSS stripping code (#913) * Fix VSS stripping behavior when headers span >1 network block. When VSS header data straddles multiple network blocks (i.e. got < bsidsize in bfile_write_vss_strip()), the pointer arithmatic when memcpy()ing the next block is incorrect. Since sid is a pointer to a structure, each addition by 1 increases the pointer address by sizeof(*sid); therefore, when sidlen > 0, the memcpy() unintentionally overwrites part of the struct BFILE it lives within or the memory situated after it. Casting sid to a char* in the memcpy() causes the addition to advance the pointer by single bytes as intended. * Don't hang when stripping VSS data from files with an empty stream. When stripping VSS data, an empty stream that has additional data following it will currently cause an infinite loop in bfile_write_vss_strip(). When encountering an empty stream, attempt to start reading a new VSS header instead. --------- Co-authored-by: Ben Winslow --- src/bfile.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/bfile.c b/src/bfile.c index 7e67ddb2..2b8caa20 100644 --- a/src/bfile.c +++ b/src/bfile.c @@ -47,14 +47,19 @@ static ssize_t bfile_write_vss_strip(struct BFILE *bfd, void *buf, size_t count) size_t sidlen=bsidsize-mysid->needed_s; int got=min(mysid->needed_s, mycount); - memcpy(sid+sidlen, cp, got); + memcpy((char *)sid+sidlen, cp, got); cp+=got; mycount-=got; mysid->needed_s-=got; - if(!mysid->needed_s) + if(!mysid->needed_s) { mysid->needed_d=sid->Size+sid->dwStreamNameSize; + // If the stream is completely empty, start + // reading a new VSS header. + if (!mysid->needed_d) + mysid->needed_s=bsidsize; + } } if(mysid->needed_d) {