diff options
author | Yann Collet <cyan@fb.com> | 2024-03-08 14:55:38 -0800 |
---|---|---|
committer | Yann Collet <cyan@fb.com> | 2024-03-08 15:26:06 -0800 |
commit | a9fb8d4c41bf3cc829adf20aea3768863d03cd0d (patch) | |
tree | 5c874b13f9c253da73e08aedcd1af0d5963dd120 /lib | |
parent | e127139ceb60065917c43ab01634aa9563ec46a4 (diff) | |
download | zstd-a9fb8d4c41bf3cc829adf20aea3768863d03cd0d.tar.gz |
new method to deal with offset==0
in this new method, when an `offset==0` is detected,
it's converted into (size_t)(-1), instead of 1.
The logic is that (size_t)(-1) is effectively an extremely large positive number,
which will not pass the offset distance test at next stage (`execSequence()`).
Checked the source code, and offset is always checked (as it should),
using a formula which is not vulnerable to arithmetic overflow:
```
RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart),
```
The benefit is that such a case (offset==0) is always detected as corrupted data
as opposed to relying on the checksum to detect the error.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/decompress/zstd_decompress_block.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/lib/decompress/zstd_decompress_block.c b/lib/decompress/zstd_decompress_block.c index 8d9fea5f..76d7332e 100644 --- a/lib/decompress/zstd_decompress_block.c +++ b/lib/decompress/zstd_decompress_block.c @@ -1305,7 +1305,7 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, c } else { offset = ofBase + ll0 + BIT_readBitsFast(&seqState->DStream, 1); { size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset]; - temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */ + temp -= !temp; /* 0 is not valid: input corrupted => force offset to -1 => corruption detected at execSequence */ if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1]; seqState->prevOffset[1] = seqState->prevOffset[0]; seqState->prevOffset[0] = offset = temp; |