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

Why is BitReader::refill marked safe? #305

Open
CodesInChaos opened this issue Feb 25, 2025 · 3 comments
Open

Why is BitReader::refill marked safe? #305

CodesInChaos opened this issue Feb 25, 2025 · 3 comments

Comments

@CodesInChaos
Copy link

BitReader::refill appears to have the safety critical pre-condition self.bytes_remaining() >= 8. However it is marked safe, which looks like a soundness issue.

pub unsafe fn refill(&mut self) {
    debug_assert!(self.bytes_remaining() >= 8);

    // SAFETY: assertion above ensures we have 8 bytes to read for a u64.
    let read = unsafe { core::ptr::read_unaligned(self.ptr.cast::<u64>()) }.to_le();
    self.bit_buffer |= read << self.bits_used;
    let increment = (63 - self.bits_used) >> 3;
    self.ptr = self.ptr.wrapping_add(increment as usize);
    self.bits_used |= 56;
}
@folkertdev
Copy link
Collaborator

There is no soundness issue in practice because all call sites are in a context where we've already guaranteed sufficient input.

However, we should document the pre-condition and and mark the function as unsafe. You want to make a PR for that?

@CodesInChaos
Copy link
Author

I don't think I'm familiar enough with the callers to write the safety comments for them.

inflate_fast_help_impl seems to have an undocumented safety precondition as well (presumably something similar to the loop condition remaining >= INFLATE_FAST_MIN_HAVE && writer.remaining() >= INFLATE_FAST_MIN_LEFT) and it's not obvious to me why the refill inside 'dodist is guaranteed to have enough data available.

@CodesInChaos
Copy link
Author

CodesInChaos commented Feb 25, 2025

return_unused_bytes seems to have a safety pre-condition as well, which then turns into len_and_friends requiring bit_reader.bits_in_buffer() < 8. So I think return_unused_bytes should become unsafe too.

Not sure about len_and_friends, perhaps it's cold enough to verify that? I also tried moving the verification to update_slice, but there it doesn't appear to hold (which should be fine, since those places don't call return_unused_bytes).

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

No branches or pull requests

2 participants