diff --git a/api/src/checksum.rs b/api/src/checksum.rs index e22ddd3719..0bf2115958 100644 --- a/api/src/checksum.rs +++ b/api/src/checksum.rs @@ -2,7 +2,7 @@ /// Verify checksum pub fn verify_checksum(checksum: i32, cmd: u32, data: &[u8]) -> bool { - calc_checksum(cmd, data) - checksum == 0 + calc_checksum(cmd, data) == checksum } /// Calculate the checksum @@ -10,21 +10,47 @@ pub fn verify_checksum(checksum: i32, cmd: u32, data: &[u8]) -> bool { pub fn calc_checksum(cmd: u32, data: &[u8]) -> i32 { let mut checksum = 0i32; for c in cmd.to_le_bytes().iter() { - checksum += *c as i32; + checksum = checksum.wrapping_add(*c as i32); } for d in data { - checksum += *d as i32; + checksum = checksum.wrapping_add(*d as i32); } - - 0 - checksum + 0i32.wrapping_sub(checksum) } #[cfg(all(test, target_family = "unix"))] mod tests { use super::*; + #[test] + fn test_calc_checksum() { + assert_eq!(calc_checksum(0xe8dc3994, &[0x83, 0xe7, 0x25]), -1056); + } + + #[test] + fn test_checksum_overflow() { + let data = vec![0xff; 16843007]; + assert_eq!(calc_checksum(0xe8dc3994, &data), -146); + assert!(verify_checksum(-146, 0xe8dc3994, &data)); + } + #[test] fn test_verify_checksum() { + assert!(verify_checksum(-1056, 0xe8dc3994, &[0x83, 0xe7, 0x25])); + assert!(!verify_checksum(-1057, 0xe8dc3994, &[0x83, 0xe7, 0x25])); + assert!(!verify_checksum(-1055, 0xe8dc3994, &[0x83, 0xe7, 0x25])); + + // subtraction overflow; would panic in debug mode if non-wrapping + // subtraction was used. + assert!(!verify_checksum( + 2147483647, + 0xe8dc3994, + &[0x83, 0xe7, 0x25] + )); + } + + #[test] + fn test_round_trip() { let cmd = 0x00000001u32; let data = [0x00000000u32; 1]; let checksum = calc_checksum(cmd, data[0].to_le_bytes().as_ref()); diff --git a/api/src/lib.rs b/api/src/lib.rs index 5bf5d67ac6..c9f4abf8d2 100644 --- a/api/src/lib.rs +++ b/api/src/lib.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license -#![no_std] +#![cfg_attr(not(test), no_std)] mod capabilities; mod checksum;