1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 03:27:44 +00:00

Merge pull request #7656 from eduardorittner/main

printf: make negative values wrap around with unsigned/hex format
This commit is contained in:
Sylvestre Ledru 2025-04-10 06:48:50 -04:00 committed by GitHub
commit a89fc48388
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 69 additions and 13 deletions

View file

@ -165,23 +165,24 @@ impl ExtendedParser for u64 {
ExtendedBigDecimal::BigDecimal(bd) => { ExtendedBigDecimal::BigDecimal(bd) => {
let (digits, scale) = bd.into_bigint_and_scale(); let (digits, scale) = bd.into_bigint_and_scale();
if scale == 0 { if scale == 0 {
let negative = digits.sign() == Sign::Minus; let (sign, digits) = digits.into_parts();
match u64::try_from(digits) { match u64::try_from(digits) {
Ok(i) => Ok(i), Ok(i) => {
_ => Err(ExtendedParserError::Overflow(if negative { if sign == Sign::Minus {
// TODO: We should wrap around here #7488 Ok(!i + 1)
0
} else { } else {
u64::MAX Ok(i)
})), }
}
_ => Err(ExtendedParserError::Overflow(u64::MAX)),
} }
} else { } else {
// Should not happen. // Should not happen.
Err(ExtendedParserError::NotNumeric) Err(ExtendedParserError::NotNumeric)
} }
} }
// TODO: Handle -0 too #7488 ExtendedBigDecimal::MinusZero => Ok(0),
// No other case should not happen.
_ => Err(ExtendedParserError::NotNumeric), _ => Err(ExtendedParserError::NotNumeric),
} }
} }
@ -527,10 +528,28 @@ mod tests {
fn test_decimal_u64() { fn test_decimal_u64() {
assert_eq!(Ok(123), u64::extended_parse("123")); assert_eq!(Ok(123), u64::extended_parse("123"));
assert_eq!(Ok(u64::MAX), u64::extended_parse(&format!("{}", u64::MAX))); assert_eq!(Ok(u64::MAX), u64::extended_parse(&format!("{}", u64::MAX)));
// TODO: We should wrap around here #7488 assert_eq!(Ok(0), u64::extended_parse("-0"));
assert_eq!(Ok(u64::MAX), u64::extended_parse("-1"));
assert_eq!(
Ok(u64::MAX / 2 + 1),
u64::extended_parse("-9223372036854775808") // i64::MIN
);
assert_eq!(
Ok(1123372036854675616),
u64::extended_parse("-17323372036854876000") // 2*i64::MIN
);
assert_eq!(Ok(1), u64::extended_parse("-18446744073709551615")); // -u64::MAX
assert!(matches!( assert!(matches!(
u64::extended_parse("-123"), u64::extended_parse("-18446744073709551616"), // -u64::MAX - 1
Err(ExtendedParserError::Overflow(0)) Err(ExtendedParserError::Overflow(u64::MAX))
));
assert!(matches!(
u64::extended_parse("-92233720368547758150"),
Err(ExtendedParserError::Overflow(u64::MAX))
));
assert!(matches!(
u64::extended_parse("-170141183460469231731687303715884105729"),
Err(ExtendedParserError::Overflow(u64::MAX))
)); ));
assert!(matches!( assert!(matches!(
u64::extended_parse(""), u64::extended_parse(""),

View file

@ -2,6 +2,8 @@
// //
// For the full copyright and license information, please view the LICENSE // For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code. // file that was distributed with this source code.
// spell-checker:ignore fffffffffffffffc
use uutests::new_ucmd; use uutests::new_ucmd;
use uutests::util::TestScenario; use uutests::util::TestScenario;
use uutests::util_name; use uutests::util_name;
@ -791,6 +793,41 @@ fn partial_integer() {
.stderr_is("printf: '42x23': value not completely converted\n"); .stderr_is("printf: '42x23': value not completely converted\n");
} }
#[test]
fn unsigned_hex_negative_wraparound() {
new_ucmd!()
.args(&["%x", "-0b100"])
.succeeds()
.stdout_only("fffffffffffffffc");
new_ucmd!()
.args(&["%x", "-0100"])
.succeeds()
.stdout_only("ffffffffffffffc0");
new_ucmd!()
.args(&["%x", "-100"])
.succeeds()
.stdout_only("ffffffffffffff9c");
new_ucmd!()
.args(&["%x", "-0x100"])
.succeeds()
.stdout_only("ffffffffffffff00");
new_ucmd!()
.args(&["%x", "-92233720368547758150"])
.fails_with_code(1)
.stdout_is("ffffffffffffffff")
.stderr_is("printf: '-92233720368547758150': Numerical result out of range\n");
new_ucmd!()
.args(&["%u", "-1002233720368547758150"])
.fails_with_code(1)
.stdout_is("18446744073709551615")
.stderr_is("printf: '-1002233720368547758150': Numerical result out of range\n");
}
#[test] #[test]
fn test_overflow() { fn test_overflow() {
new_ucmd!() new_ucmd!()