Signed-to-unsigned cast turns negative values into huge positives
ID |
rust.portability.cast_sign_loss |
Severity |
low |
Remediation Complexity |
medium |
Remediation Risk |
low |
Remediation Effort |
medium |
Resource |
Numeric Conversion |
Language |
Rust |
Description
Detects an as cast from a signed integer to an unsigned one, covering the same-width pairs and the widening forms that are commonly used to build an index, such as i32 as usize.
Rationale
The cast reinterprets the two’s-complement bit pattern, so a negative value does not become zero or raise an error - it becomes a very large positive number. Used as a length or an index, that turns a small negative slip into an out-of-range access or an enormous allocation, and on usize the resulting value also depends on the target pointer width.
The following code illustrates the pattern detected by this rule:
pub fn indexing(delta: i32, offset: i64, cursor: isize, tag: i16, marker: i8) -> u64 {
// FLAGGED: Signed-to-unsigned cast turns negative values into huge positives
let a = delta as u32;
// FLAGGED: Signed-to-unsigned cast turns negative values into huge positives
let b = offset as u64;
// FLAGGED: Signed-to-unsigned cast turns negative values into huge positives
let c = cursor as usize;
// FLAGGED: Signed-to-unsigned cast turns negative values into huge positives
let d = tag as u16;
// FLAGGED: Signed-to-unsigned cast turns negative values into huge positives
let e = marker as u8;
// FLAGGED: Signed-to-unsigned cast turns negative values into huge positives
let f = delta as usize;
// FLAGGED: Signed-to-unsigned cast turns negative values into huge positives
let g = offset as usize;
// FLAGGED: Signed-to-unsigned cast turns negative values into huge positives
let h = delta as u64;
a as u64 + b + c as u64 + d as u64 + e as u64 + f as u64 + g as u64 + h
}