Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions contrib/seekable_format/tests/seekable_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,62 @@ int main(int argc, const char** argv)
}
printf("Success!\n");

printf("Test %u - decompress at and past the end of the data: ", testNb++);
{ char const inBuffer[] = "Lorem ipsum dolor sit amet";
size_t const inSize = sizeof(inBuffer);

size_t const seekCapacity = 5000;
void* const seekBuffer = malloc(seekCapacity);
assert(seekBuffer != NULL);
size_t seekSize;

char outBuffer[16];

ZSTD_seekable_CStream* const zscs = ZSTD_seekable_createCStream();
assert(zscs != NULL);
{ size_t const initStatus = ZSTD_seekable_initCStream(zscs, 9, 0 /* checksumFlag */, 0 /* maxFrameSize */);
assert(!ZSTD_isError(initStatus));
}

{ ZSTD_outBuffer outb = { .dst=seekBuffer, .pos=0, .size=seekCapacity };
ZSTD_inBuffer inb = { .src=inBuffer, .pos=0, .size=inSize };

size_t const cStatus = ZSTD_seekable_compressStream(zscs, &outb, &inb);
assert(!ZSTD_isError(cStatus));
assert(inb.pos == inb.size);

size_t const endStatus = ZSTD_seekable_endStream(zscs, &outb);
assert(!ZSTD_isError(endStatus));
seekSize = outb.pos;
}

ZSTD_seekable* const stream = ZSTD_seekable_create();
assert(stream != NULL);
{ size_t const initStatus = ZSTD_seekable_initBuff(stream, seekBuffer, seekSize);
assert(!ZSTD_isError(initStatus)); }

{ size_t const atEnd = ZSTD_seekable_decompress(stream, outBuffer, sizeof(outBuffer), inSize);
size_t const pastEnd = ZSTD_seekable_decompress(stream, outBuffer, sizeof(outBuffer), inSize + 5000);
int failed = atEnd != 0 || !ZSTD_isError(pastEnd);
if (!failed) {
/* offset + len wraps around to 0 */
size_t const wrapped = ZSTD_seekable_decompress(stream, outBuffer, sizeof(outBuffer), 0ULL - sizeof(outBuffer));
failed = !ZSTD_isError(wrapped);
}
if (failed) {
free(seekBuffer);
ZSTD_seekable_freeCStream(zscs);
ZSTD_seekable_free(stream);
goto _test_error;
}
}

free(seekBuffer);
ZSTD_seekable_freeCStream(zscs);
ZSTD_seekable_free(stream);
}
printf("Success!\n");

/* TODO: Add more tests */
printf("Finished tests\n");
return 0;
Expand Down
3 changes: 3 additions & 0 deletions contrib/seekable_format/zstd_seekable.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ ZSTDLIB_API size_t ZSTD_seekable_writeSeekTable(ZSTD_frameLog* fl, ZSTD_outBuffe
* consecutive range of data, it will efficiently retain the decompressor object
* and avoid redecompressing frame prefixes. The return value is the number of
* bytes decompressed, or an error code checkable with ZSTD_isError().
* It is smaller than `dstSize` only when the data ends before
* `offset + dstSize`, and it is 0 when `offset` is the end of the data.
* An `offset` past the end of the data is an error.
*
* The seek table access functions can be used to obtain the data contained
* in the seek table. If frameIndex is larger than the value returned by
Expand Down
5 changes: 3 additions & 2 deletions contrib/seekable_format/zstdseek_decompress.c
Original file line number Diff line number Diff line change
Expand Up @@ -496,8 +496,9 @@ size_t ZSTD_seekable_initAdvanced(ZSTD_seekable* zs, ZSTD_seekable_customFile sr
size_t ZSTD_seekable_decompress(ZSTD_seekable* zs, void* dst, size_t len, unsigned long long offset)
{
unsigned long long const eos = zs->seekTable.entries[zs->seekTable.tableLen].dOffset;
if (offset + len > eos) {
len = eos - offset;
if (offset > eos) return ERROR(parameter_outOfBound);
if (len > eos - offset) {
len = (size_t)(eos - offset);
}

U32 targetFrame = ZSTD_seekable_offsetToFrameIndex(zs, offset);
Expand Down
Loading