[nstool] Fix critical bug in HashTreeWrappedIFile (bumped to v1.0.5)

This commit is contained in:
jakcron 2018-09-26 21:48:38 +08:00
parent 8bb759292d
commit 3716bf0b82
3 changed files with 38 additions and 35 deletions

View file

@ -34,7 +34,7 @@ else
endif
BIN_DIR = bin
OUTPUT = $(BIN_DIR)/$(shell basename $(CURDIR))
OUTPUT = $(BIN_DIR)/$(shell basename "$(CURDIR)")
all: build

View file

@ -23,45 +23,49 @@ void HashTreeWrappedIFile::seek(size_t offset)
void HashTreeWrappedIFile::read(byte_t* out, size_t len)
{
size_t offset_in_start_block = getOffsetInBlock(mDataOffset);
size_t offset_in_end_block = getOffsetInBlock(offset_in_start_block + len);
size_t start_block = getOffsetBlock(mDataOffset);
size_t block_num = align(offset_in_start_block + len, mDataBlockSize) / mDataBlockSize;
size_t partial_last_block_num = block_num % mCacheBlockNum;
bool has_partial_block_num = partial_last_block_num > 0;
size_t read_iterations = (block_num / mCacheBlockNum) + has_partial_block_num;
size_t block_read_len;
size_t block_export_offset;
size_t block_export_size;
size_t block_export_pos = 0;
for (size_t i = 0; i < read_iterations; i++)
struct sBlockPosition
{
// how many blocks to read from source file
block_read_len = (i+1 == read_iterations && has_partial_block_num) ? partial_last_block_num : mCacheBlockNum;
size_t index;
size_t pos;
} start_blk, end_blk;
// offset in this current read to copy from
block_export_offset = (i == 0) ? offset_in_start_block : 0;
start_blk.index = getOffsetBlock(mDataOffset);
start_blk.pos = getOffsetInBlock(mDataOffset);
// size of current read to copy
block_export_size = (block_read_len * mDataBlockSize) - block_export_offset;
end_blk.index = getOffsetBlock(mDataOffset + len);
end_blk.pos = getOffsetInBlock(mDataOffset + len);
if (end_blk.pos == 0 && len != 0)
{
end_blk.index -= 1;
end_blk.pos = mDataBlockSize;
}
// if last read, reduce the export size by one block less offset_in_end_block
if (i+1 == read_iterations)
{
block_export_size -= (mDataBlockSize - offset_in_end_block);
}
size_t total_blk_num = (end_blk.index - start_blk.index) + 1;
// read the blocks
readData(start_block + (i * mCacheBlockNum), block_read_len);
size_t read_blk_num = 0;
size_t cache_export_start_pos, cache_export_end_pos, cache_export_size;
size_t export_pos = 0;
for (size_t i = 0; i < total_blk_num; i += read_blk_num, export_pos += cache_export_size)
{
read_blk_num = _MIN(mCacheBlockNum, (total_blk_num - i));
readData(start_blk.index + i, read_blk_num);
// export the section of data that is relevant
memcpy(out + block_export_pos, mCache.data() + block_export_offset, block_export_size);
// if this is the first read, adjust offset
if (i == 0)
cache_export_start_pos = start_blk.pos;
else
cache_export_start_pos = 0;
// update export position
block_export_pos += block_export_size;
// if this is the last block, adjust end offset
if ((i + read_blk_num) == total_blk_num)
cache_export_end_pos = ((read_blk_num - 1) * mDataBlockSize) + end_blk.pos;
else
cache_export_end_pos = read_blk_num * mDataBlockSize;
// determine cache export size
cache_export_size = cache_export_end_pos - cache_export_start_pos;
memcpy(out + export_pos, mCache.data() + cache_export_start_pos, cache_export_size);
}
// update offset
@ -150,7 +154,6 @@ void HashTreeWrappedIFile::initialiseDataLayer(const HashTreeMeta& hdr)
void HashTreeWrappedIFile::readData(size_t block_offset, size_t block_num)
{
(*mData)->seek(block_offset * mDataBlockSize);
fnd::sha::sSha256Hash hash;
// determine read size

View file

@ -3,5 +3,5 @@
#define BIN_NAME "nstool"
#define VER_MAJOR 1
#define VER_MINOR 0
#define VER_PATCH 4
#define VER_PATCH 5
#define AUTHORS "jakcron"