Skip to content

printf: arithmetic overflow (overflow-checks) on a %*d dynamic field width of i64::MIN #13766

Description

@leeewee

printf's %* dynamic field width takes the width from an argument (printf '%*d' <width> <value>). For a negative width, resolve_asterisk_width computes -(nb as isize) to get the magnitude.

fn resolve_asterisk_width(
option: Option<CanAsterisk<usize>>,
args: &mut FormatArguments,
) -> Option<(usize, bool)> {
match option {
None => None,
Some(CanAsterisk::Asterisk(loc)) => {
let nb = args.next_i64(loc);
if nb < 0 {
Some((usize::try_from(-(nb as isize)).ok().unwrap_or(0), true))
} else {
Some((usize::try_from(nb).ok().unwrap_or(0), false))
}
}
Some(CanAsterisk::Fixed(w)) => Some((w, false)),
}
}

When the width argument is i64::MIN (-9223372036854775808), nb as isize is isize::MIN, and negating it overflows (it has no positive counterpart), panicking with attempt to negate with overflow under -C overflow-checks (exit 134).

$ printf '%*d' -9223372036854775808 1
thread 'main' panicked at src/uucore/src/lib/features/format/spec.rs:520:39:
attempt to negate with overflow
$ echo $?
134

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions