The zigzag decode helper sign, on input u64::MAX, panics in debug builds and silently returns 0 instead of i64::MIN in release builds.
In src/lib.rs:
fn sign(value: u64) -> i64 {
if value & 1 != 0 {
-(((value + 1) / 2) as i64)
} else {
(value / 2) as i64
}
}
u64::MAX is odd, so we enter the if-branch. u64::MAX + 1 overflows u64:
- Debug: panic with "attempt to add with overflow"
- Release: wraps to 0, so sign(u64::MAX) silently returns 0 instead of the correct i64::MIN (-9223372036854775808)
This can lead to data corruption. Unit test to reproduce:
#[test]
fn test_roundtrip_i64_min() {
let mut buf = [0u8; 10];
let n = signed_encode(i64::MIN, &mut buf);
let mut out = 0i64;
signed_decode(&buf[..n], &mut out);
assert_eq!(out, i64::MIN); // fails: out == 0
}
The encode side (unsign) has a similar overflow (i64::MIN * -2), but wrapping arithmetic accidentally produces the correct result (u64::MAX), so encode works in release.
The zigzag decode helper sign, on input u64::MAX, panics in debug builds and silently returns 0 instead of i64::MIN in release builds.
In src/lib.rs:
u64::MAX is odd, so we enter the if-branch. u64::MAX + 1 overflows u64:
This can lead to data corruption. Unit test to reproduce:
The encode side (unsign) has a similar overflow (i64::MIN * -2), but wrapping arithmetic accidentally produces the correct result (u64::MAX), so encode works in release.