moodmosaic

Appendix: Varint Shift Bug

This post is part of the Input Coverage > Code Coverage series.

Classic edge: overlong LEB128 varint. Missing shift cap leads to panic.

Buggy decode:

pub fn decode_varint(data: &[u8]) -> Result<(u64, usize), ()> {
    let mut acc: u64 = 0;
    let mut shift: u32 = 0;
    for (i, &b) in data.iter().enumerate() {
        let v = (b & 0x7f) as u64;
        acc |= v << shift; // Panic when shift >= 64.
        if (b & 0x80) == 0 { return Ok((acc, i + 1)); }
        shift += 7;
    }
    Err(())
}

Property tests round-trip only valid encodings. No crash. libFuzzer feeds 10+ continuation bytes, hits the panic.

Fix:

if shift >= 64 { return Err(()); }

Next: Appendix: Commands, Flags, And Gotchas