Fix possible overflow when calculating short name checksum

Affects debug build only. Overflow was not handled when calculating
checksum used for short name generation when avoiding a conflict.
LFN checksum was working properly but got refactored in this commit to
use num::Wrapping as well.
This commit is contained in:
Rafał Harabień 2018-06-17 21:58:39 +02:00
parent 674d1f8182
commit 4afd38a150

View File

@ -1,6 +1,6 @@
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
use core::{slice, iter}; use core::{slice, iter};
use core::{str, char, cmp}; use core::{str, char, cmp, num};
use io::prelude::*; use io::prelude::*;
use io; use io;
@ -537,11 +537,11 @@ fn validate_long_name(name: &str) -> io::Result<()> {
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
fn lfn_checksum(short_name: &[u8]) -> u8 { fn lfn_checksum(short_name: &[u8]) -> u8 {
let mut chksum = 0u8; let mut chksum = num::Wrapping(0u8);
for i in 0..11 { for i in 0..11 {
chksum = (((chksum & 1) << 7) as u16 + (chksum >> 1) as u16 + short_name[i] as u16) as u8; chksum = (chksum << 7) + (chksum >> 1) + num::Wrapping(short_name[i]);
} }
chksum chksum.0
} }
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
@ -796,11 +796,11 @@ impl ShortNameGenerator {
fn checksum(name: &str) -> u16 { fn checksum(name: &str) -> u16 {
// BSD checksum algorithm // BSD checksum algorithm
let mut chksum = 0u16; let mut chksum = num::Wrapping(0u16);
for c in name.chars() { for c in name.chars() {
chksum = (chksum >> 1) + ((chksum & 1) << 15) + (c as u16); chksum = (chksum >> 1) + (chksum << 15) + num::Wrapping(c as u16);
} }
chksum chksum.0
} }
fn generate(&self) -> io::Result<[u8; 11]> { fn generate(&self) -> io::Result<[u8; 11]> {
@ -873,6 +873,16 @@ mod tests {
assert_eq!(&ShortNameGenerator::new(".bashrc.swp").generate().unwrap(), "BASHRC~1SWP".as_bytes()); assert_eq!(&ShortNameGenerator::new(".bashrc.swp").generate().unwrap(), "BASHRC~1SWP".as_bytes());
} }
#[test]
fn test_short_name_checksum_overflow() {
ShortNameGenerator::checksum("\u{FF5A}\u{FF5A}\u{FF5A}\u{FF5A}");
}
#[test]
fn test_lfn_checksum_overflow() {
lfn_checksum(&[0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8]);
}
#[test] #[test]
fn test_generate_short_name_collisions_long() { fn test_generate_short_name_collisions_long() {
let mut buf: [u8; 11]; let mut buf: [u8; 11];