Skip to content

Conversation

vivekmig
Copy link

Adding check if block size exceeds maximum.

Tested by creating a frame with a fake frame with raw block of size approximately 500 kb, and verifying the output:
Screen Shot 2019-07-15 at 12 16 24 PM

@facebook-github-bot
Copy link

Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file. In order for us to review and merge your code, please sign up at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need the corporate CLA signed.

If you have received this in error or have any questions, please contact us at cla@fb.com. Thanks!

@vivekmig vivekmig marked this pull request as ready for review July 15, 2019 19:20
@facebook-github-bot
Copy link

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks!

{ blockProperties_t bp;
size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
if (ZSTD_isError(cBlockSize)) return cBlockSize;
RETURN_ERROR_IF(cBlockSize > ZSTD_BLOCKSIZE_MAX, corruption_detected, "Block Size Exceeds Maximum");
Copy link
Contributor

@Cyan4973 Cyan4973 Jul 15, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is a first good place for this check.
It controls the compressed size, and no block shall have its compressed size larger than maximum block size.

However :

  • No block shall have its decompressed size larger than maximum block size. This is more complex, and must be controlled elsewhere.
  • ZSTD_BLOCKSIZE_MAX is the "maximum maximum block size". But the specifications make it clear that the maximum block size can be smaller than that, depending on frame header instructions. It actually depends on the window size. This value should be computed once, at header decoding stage, stored into dctx, and then used for later checks.

You may consider the 2nd point as an extension.
Comparing with a constant ZSTD_BLOCKSIZE_MAX is a useful first step, which is already valuable.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much, this was really helpful! I think the maximum block size (min of window size and block size) seemed to already be stored in dctx->fParams.blockSizeMax, so I switched to using that. I've also added a check for the decompressed block size by checking rSize returned after decompressing a block.

@Cyan4973
Copy link
Contributor

Thanks @vivekmig !
The change looks good to me !

Now, it seems it generates errors in the decodecorpus test.

It might be because decodecorpus is generating incorrect frames.
This seems plausible, as this block size property was never enforced so far.
But this is pure speculation. One would need an investigation to understand the problem.

@vivekmig
Copy link
Author

Updated decodecorpus test to not create an RLE block if frame content size is 0, this eliminates the possibility that an RLE block exceeds the max block size.

@Cyan4973
Copy link
Contributor

Great work @vivekmig !

We are in the middle of a new release, so we'll wait a little bit for the actual merge.
But this patch is validated, and it will be merged soon after.

@Cyan4973
Copy link
Contributor

Release completed, we can merge

@Cyan4973 Cyan4973 merged commit f262069 into facebook:dev Jul 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants