Archive extraction panics on armv7-unknown-linux-musleabihf architecture
Closed this issue · 4 comments
When trying to extract .rar file on armv7-unknown-linux-musleabihf architecture, library panics with:
thread \'main\' panicked at \'attempt to shift left with overflow\', /cargo/registry/src/index.crates.io-6f17d22bba15001f/unrar-0.5.1/src/open_archive.rs:647:5
Used code:
pub fn unpack_archive(archive_path: &Path, output_folder: &Path) -> crate::Result<usize> {
assert!(output_folder.read_dir().expect("dir exists").count() == 0);
let mut archive = Archive::new(archive_path).open_for_processing()?;
let mut unpacked = 0;
while let Some(header) = archive.read_header()? {
let entry = header.entry();
archive = if entry.is_file() {
unpacked += 1;
header.extract_with_base(output_folder)?
} else {
header.skip()?
};
}
Ok(unpacked)
}
Same code is working fine on x86_64.
Thank you for opening an issue. Seems this has to do with 32-bit architecture.
The problem is the code in the specified line which translates to let foo: u64 = 0 << 8 * std::mem::size_of::<u32>()
on 64-bit architecture which works fine and to let x: u32 = 0 << 8 * std::mem::size_of::<u32>()
on 32-bit architecture which panics (playground link
May I ask what behavior would you expect if the file is larger than u32::MAX
? Would it be even possible to extract?
Your playground link panics for me even on 64-bit architecture :)
I've looked at the code as well, here's the panicking function for reference:
fn unpack_unp_size(unp_size: c_uint, unp_size_high: c_uint) -> usize {
((unp_size_high as usize) << (8 * std::mem::size_of::<c_uint>())) | (unp_size as usize)
}
I think that the culprit here is that above code implicitly assumes that size_of::<usize>() > size_of::<c_uint>()
.
Unfortunately, since usize
size is target-dependent, that implicit assumption is not true on 32-bit architecture.
(Actually, c_uint
size also target-dependent, but usually is 32-bit long)
Do you see any issue with explicitly using u64
instead of usize
to avoid this pitfall ?
May I ask what behavior would you expect if the file is larger than u32::MAX? Would it be even possible to extract?
Speaking from the user perspective:
I'd say that if underlying filesystem allows it (looking at you, FAT32), extraction should be possible.
Ah, sorry, I've corrected the first snippet now (should've been u64). If you change let _foo: u32
to let _foo: u64
in the playground link, it doesn't panic and that is the behavior on 64-bit architecture.
Yes changing to u64
is probably the best solution, I'm just not sure if a patch release is sufficient, but probably is.
Taking into account that such solution won't change anything for 64-bit arch, and on 32-bit it didn't work in the first place, I think a patch release would be a good way forward.
Would you like me to propose a PR for this or will you change it yourself?