Unsigned-to-signed cast of the same width may wrap to a negative value
ID |
rust.portability.cast_possible_wrap |
Severity |
low |
Remediation Complexity |
medium |
Remediation Risk |
low |
Remediation Effort |
medium |
Resource |
Numeric Conversion |
Language |
Rust |
Description
Detects an as cast from an unsigned integer to a signed integer of the same width, and the pointer-width variants between usize, isize and 64-bit integers.
Rationale
A same-width unsigned-to-signed cast keeps every bit and only reinterprets the top one as a sign bit, so any value above the signed maximum silently becomes negative. The usize/isize forms are additionally target-dependent: what fits on a 64-bit build wraps on a 32-bit one, so the defect only shows up on part of the supported platforms.
The following code illustrates the pattern detected by this rule:
pub fn header_fields(len: usize, flags: u32, count: u64, tag: u16, marker: u8) -> i64 {
// FLAGGED: Unsigned-to-signed cast of the same width may wrap to a negative value
let offset = len as isize;
// FLAGGED: Unsigned-to-signed cast of the same width may wrap to a negative value
let signed_flags = flags as i32;
// FLAGGED: Unsigned-to-signed cast of the same width may wrap to a negative value
let signed_count = count as i64;
// FLAGGED: Unsigned-to-signed cast of the same width may wrap to a negative value
let signed_tag = tag as i16;
// FLAGGED: Unsigned-to-signed cast of the same width may wrap to a negative value
let signed_marker = marker as i8;
// FLAGGED: Unsigned-to-signed cast of the same width may wrap to a negative value
let wide_len = len as i64;
offset as i64 + signed_flags as i64 + signed_count + signed_tag as i64 + signed_marker as i64 + wide_len
}