Skip to content

Commit

Permalink
Fix crashes/freezes in VSS stripping code (#913)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
raineth and raineth authored Apr 14, 2023
1 parent e54de24 commit ed1e60f
Showing 1 changed file with 7 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/bfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down

0 comments on commit ed1e60f

Please sign in to comment.