Skip to content

Commit 158bff7

Browse files
authored
Ensure that FixedInt and FixedUInt handle zero-length integers (#762)
1 parent 892ef2d commit 158bff7

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

src/lazy/encoder/binary/v1_1/fixed_int.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,14 @@ impl FixedInt {
3434
}
3535

3636
let value: Int = if input.len() <= 8 {
37-
// Look at the last byte in the input that is part of the FixedInt; this is the most significant byte.
38-
let most_significant_byte = input[size_in_bytes - 1];
39-
let sign_bit = most_significant_byte & 0b1000_0000;
40-
// Create a buffer that is filled with the sign bit that we can write into.
41-
// Any bytes not overwritten will be an extension of the sign bit.
42-
let mut buffer = if sign_bit == 0 { [0x0; 8] } else { [0xFF; 8] };
43-
buffer[..size_in_bytes].copy_from_slice(input);
44-
i64::from_le_bytes(buffer).into()
37+
let mut buffer = [0x0; 8];
38+
// Copy the input into the buffer as the _most_ significant bits, read as i64, and then
39+
// shift right to the correct position, extending the sign.
40+
buffer[(8 - size_in_bytes)..8].copy_from_slice(input);
41+
i64::from_le_bytes(buffer)
42+
.checked_shr(64 - (size_in_bytes as u32 * 8))
43+
.unwrap_or(0)
44+
.into()
4545
} else {
4646
BigInt::from_signed_bytes_le(&input[..size_in_bytes]).into()
4747
};
@@ -255,6 +255,18 @@ mod tests {
255255
Ok(())
256256
}
257257

258+
#[test]
259+
fn decode_zero_length_fixed_int() -> IonResult<()> {
260+
let encoding = &[];
261+
let fixed_int = FixedInt::read(encoding, encoding.len(), 0)?;
262+
let actual_value = fixed_int.value().expect_i64()?;
263+
assert_eq!(
264+
actual_value, 0,
265+
"actual value {actual_value} was != expected value 0 for encoding {encoding:x?}"
266+
);
267+
Ok(())
268+
}
269+
258270
#[test]
259271
fn encode_fixed_int() -> IonResult<()> {
260272
// Make two copies of each of our tests. In the first, each i64 is turned into a Int.

src/lazy/encoder/binary/v1_1/fixed_uint.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,18 @@ mod tests {
172172
Ok(())
173173
}
174174

175+
#[test]
176+
fn decode_zero_length_fixed_uint() -> IonResult<()> {
177+
let encoding = &[];
178+
let fixed_uint = FixedUInt::read(encoding, encoding.len(), 0)?;
179+
let actual_value = fixed_uint.value().expect_u64()?;
180+
assert_eq!(
181+
actual_value, 0,
182+
"actual value {actual_value} was != expected value 0 for encoding {encoding:x?}"
183+
);
184+
Ok(())
185+
}
186+
175187
#[test]
176188
fn encode_fixed_uint() -> IonResult<()> {
177189
// Make two copies of each of our tests. In the first, each u64 is turned into a UInt.

0 commit comments

Comments
 (0)