Skip to content

Commit 79fb853

Browse files
fix: apply sign extension when decoding int (#732)
Closes #730
1 parent 291df5a commit 79fb853

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

src/buf/buf_impl.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ macro_rules! buf_get_impl {
6666
}};
6767
}
6868

69+
// https://en.wikipedia.org/wiki/Sign_extension
70+
fn sign_extend(val: u64, nbytes: usize) -> i64 {
71+
let shift = (8 - nbytes) * 8;
72+
(val << shift) as i64 >> shift
73+
}
74+
6975
/// Read bytes from a buffer.
7076
///
7177
/// A buffer stores bytes in memory such that read operations are infallible.
@@ -923,7 +929,7 @@ pub trait Buf {
923929
/// This function panics if there is not enough remaining data in `self`, or
924930
/// if `nbytes` is greater than 8.
925931
fn get_int(&mut self, nbytes: usize) -> i64 {
926-
buf_get_impl!(be => self, i64, nbytes);
932+
sign_extend(self.get_uint(nbytes), nbytes)
927933
}
928934

929935
/// Gets a signed n-byte integer from `self` in little-endian byte order.
@@ -944,7 +950,7 @@ pub trait Buf {
944950
/// This function panics if there is not enough remaining data in `self`, or
945951
/// if `nbytes` is greater than 8.
946952
fn get_int_le(&mut self, nbytes: usize) -> i64 {
947-
buf_get_impl!(le => self, i64, nbytes);
953+
sign_extend(self.get_uint_le(nbytes), nbytes)
948954
}
949955

950956
/// Gets a signed n-byte integer from `self` in native-endian byte order.

tests/test_buf.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,19 @@ fn test_get_u16() {
3636
assert_eq!(0x5421, buf.get_u16_le());
3737
}
3838

39+
#[test]
40+
fn test_get_int() {
41+
let mut buf = &b"\xd6zomg"[..];
42+
assert_eq!(-42, buf.get_int(1));
43+
let mut buf = &b"\xd6zomg"[..];
44+
assert_eq!(-42, buf.get_int_le(1));
45+
46+
let mut buf = &b"\xfe\x1d\xc0zomg"[..];
47+
assert_eq!(0xffffffffffc01dfeu64 as i64, buf.get_int_le(3));
48+
let mut buf = &b"\xfe\x1d\xc0zomg"[..];
49+
assert_eq!(0xfffffffffffe1dc0u64 as i64, buf.get_int(3));
50+
}
51+
3952
#[test]
4053
#[should_panic]
4154
fn test_get_u16_buffer_underflow() {

0 commit comments

Comments
 (0)