|
3 | 3 |
|
4 | 4 | use std::collections::HashSet; |
5 | 5 |
|
6 | | -use fvm_ipld_bitfield::{bitfield, BitField}; |
| 6 | +use fvm_ipld_bitfield::{bitfield, BitField, UnvalidatedBitField}; |
7 | 7 | use rand::{Rng, SeedableRng}; |
8 | 8 | use rand_xorshift::XorShiftRng; |
9 | 9 |
|
@@ -232,3 +232,67 @@ fn exceeds_bitfield_range() { |
232 | 232 | BitField::try_from_bits([0, 1, 4, 99, u64::MAX - 1]) |
233 | 233 | .expect("expected setting u64::MAX-1 to succeed"); |
234 | 234 | } |
| 235 | + |
| 236 | +#[test] |
| 237 | +fn bitfield_custom() { |
| 238 | + let mut bf = BitField::new(); |
| 239 | + |
| 240 | + // Set alternating bits for worst-case size performance |
| 241 | + let mut i = 0; |
| 242 | + while i < 1_000_000 { |
| 243 | + bf.set(i); |
| 244 | + i += 2; |
| 245 | + } |
| 246 | + println!("# Set bits: {}", bf.len()); |
| 247 | + |
| 248 | + // Standard serialization catches MAX_ENCODING_SIZE issues |
| 249 | + println!("Attempting to serialize..."); |
| 250 | + match fvm_ipld_encoding::to_vec(&bf) { |
| 251 | + Ok(_) => panic!("This should have failed!"), |
| 252 | + Err(_) => println!("Standard serialization failed, as expected"), |
| 253 | + } |
| 254 | + |
| 255 | + // Bypass to_vec enc size check so we can test deserialization |
| 256 | + println!("Manually serializing..."); |
| 257 | + // CBOR prefix for the bytes |
| 258 | + let mut cbor = vec![0x5A, 0x00, 0x01, 0xE8, 0x49]; |
| 259 | + cbor.extend_from_slice(&bf.to_bytes()); |
| 260 | + println!("Success!"); |
| 261 | + |
| 262 | + println!("# bytes of cbor: {}", cbor.len()); |
| 263 | + println!("Header: {:#010b}", cbor[0]); |
| 264 | + println!("-- maj type {}", (cbor[0] & 0xe0) >> 5); |
| 265 | + |
| 266 | + // Get size of payload size |
| 267 | + let info = cbor[0] & 0x1f; |
| 268 | + println!("-- adtl info {}", info); |
| 269 | + |
| 270 | + // Get payload size |
| 271 | + let size = match info { |
| 272 | + 0..=23 => info as usize, |
| 273 | + 24 => cbor[1] as usize, |
| 274 | + 25 => u16::from_be_bytes([cbor[1], cbor[2]]) as usize, |
| 275 | + 26 => u32::from_be_bytes([cbor[1], cbor[2], cbor[3], cbor[4]]) as usize, |
| 276 | + 27 => u64::from_be_bytes([ |
| 277 | + cbor[1], cbor[2], cbor[3], cbor[4], cbor[5], cbor[6], cbor[7], cbor[8], |
| 278 | + ]) as usize, |
| 279 | + _ => { |
| 280 | + println!("OUT OF RANGE"); |
| 281 | + 0 |
| 282 | + } |
| 283 | + }; |
| 284 | + |
| 285 | + println!("{} byte payload", size); |
| 286 | + |
| 287 | + // Deserialize and validate malicious payload |
| 288 | + println!("Attempting to deserialize and validate..."); |
| 289 | + match fvm_ipld_encoding::from_slice::<UnvalidatedBitField>(&cbor) { |
| 290 | + Ok(mut bitfield) => { |
| 291 | + bitfield.validate_mut().unwrap(); |
| 292 | + panic!("Error - deserialized/validated payload over 32768 bytes."); |
| 293 | + } |
| 294 | + Err(_) => { |
| 295 | + println!("Success - payload over 32768 bytes cannot be deserialized"); |
| 296 | + } |
| 297 | + } |
| 298 | +} |
0 commit comments