Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bitstream: fixes #257

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft

bitstream: fixes #257

wants to merge 2 commits into from

Conversation

mildsunrise
Copy link
Contributor

@mildsunrise mildsunrise commented Feb 22, 2024

Fixes several issues in bitstream.h (BitReader and BitWriter):

  • in C++, it is undefined behavior to do dword >> 32 or dword << 32. And we are doing that in several points of the code. This is one of the UBs that hardly leads to crashes, but it did lead to an actual bug, which is observed in h264: full SPS parsing #253 (see description). In Get(), when we combine cache with ret:

    ret = cache >> (32-n);

    This assumes that the lower bits of cache are zero. Which is guaranteed since SkipCached() does a right shift:

    cache = cache << n;

    ...except when n is 32, in which case this invokes UB. In most implementations / architectures this will result in leaving cache unchanged rather than zeroed.

  • GetVariableLengthUnsigned makes no sense. It is an AV1 primitive (essentially identical to H.264 ue(v)) and it should be implemented as:
    Screenshot from 2024-02-22 21-29-42

  • Get() doesn't set error condition if there are not enough bits to read (or rather, it only does that in specific cases).

@mildsunrise
Copy link
Contributor Author

More issues that I have:

  • GolombExpDecoder::Decode() invokes UB with certain user input.
  • BitWritter::Put() does not signal error if there isn't enough space in buffer (at least, not immediately).
  • It is possible to underflow cached, for example by reading more bits than present. this can then cause Left() to underflow as well.

@@ -91,6 +91,9 @@ class BitReader
ret = cache >> (32-n);
//Cache next
Cache();
//Check available
if (cached<a)
Copy link
Member

Choose a reason for hiding this comment

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

shouldn't this check be done inside GetChached() ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

GetCached() is called from two places, and only this call site needs the check. but if you prefer to move it there for clarity, we can do that too

Copy link
Member

Choose a reason for hiding this comment

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

better do it in the inner most layer always

include/bitstream.h Outdated Show resolved Hide resolved
@@ -414,6 +422,8 @@ class BitWritter{
//Increase cached
cached = b;
} else {
//Don't invoke UB if empty
if (!n) return v;
Copy link
Member

Choose a reason for hiding this comment

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

should we put this check on the else?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the idea was to skip the FlushCache() call afterwards, but yes, we can also do that if you prefer

Copy link
Member

Choose a reason for hiding this comment

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

we can put it at the begginging of the function, or as a first clause of the if-else-if

@@ -414,6 +422,8 @@ class BitWritter{
//Increase cached
cached = b;
} else {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
} else {
} else if (n) {

Copy link
Member

@murillo128 murillo128 left a comment

Choose a reason for hiding this comment

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

lgtm with just to minor comments, feel free to merge it when you are confortable with it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants