Avoid an overflow on negation in format_helper_exit_status

Part of 13104; patch from teor.
This commit is contained in:
Nick Mathewson 2014-09-11 00:00:13 -04:00
parent 59f9a5c786
commit 284cc9a224
2 changed files with 30 additions and 1 deletions

View File

@ -3555,7 +3555,13 @@ format_helper_exit_status(unsigned char child_state, int saved_errno,
/* Convert errno to be unsigned for hex conversion */
if (saved_errno < 0) {
unsigned_errno = (unsigned int) -saved_errno;
// Avoid overflow on the cast to unsigned int when result is INT_MIN
// by adding 1 to the signed int negative value,
// then, after it has been negated and cast to unsigned,
// adding the original 1 back (the double-addition is intentional).
// Otherwise, the cast to signed could cause a temporary int
// to equal INT_MAX + 1, which is undefined.
unsigned_errno = ((unsigned int) -(saved_errno + 1)) + 1;
} else {
unsigned_errno = (unsigned int) saved_errno;
}

View File

@ -2561,12 +2561,17 @@ test_util_exit_status(void *ptr)
int n;
(void)ptr;
clear_hex_errno(hex_errno);
test_streq("", hex_errno);
clear_hex_errno(hex_errno);
n = format_helper_exit_status(0, 0, hex_errno);
test_streq("0/0\n", hex_errno);
test_eq(n, strlen(hex_errno));
#if SIZEOF_INT == 4
clear_hex_errno(hex_errno);
n = format_helper_exit_status(0, 0x7FFFFFFF, hex_errno);
test_streq("0/7FFFFFFF\n", hex_errno);
@ -2577,6 +2582,21 @@ test_util_exit_status(void *ptr)
test_streq("FF/-80000000\n", hex_errno);
test_eq(n, strlen(hex_errno));
test_eq(n, HEX_ERRNO_SIZE);
#elif SIZEOF_INT == 8
clear_hex_errno(hex_errno);
n = format_helper_exit_status(0, 0x7FFFFFFFFFFFFFFF, hex_errno);
test_streq("0/7FFFFFFFFFFFFFFF\n", hex_errno);
test_eq(n, strlen(hex_errno));
clear_hex_errno(hex_errno);
n = format_helper_exit_status(0xFF, -0x8000000000000000, hex_errno);
test_streq("FF/-8000000000000000\n", hex_errno);
test_eq(n, strlen(hex_errno));
test_eq(n, HEX_ERRNO_SIZE);
#endif
clear_hex_errno(hex_errno);
n = format_helper_exit_status(0x7F, 0, hex_errno);
@ -2587,6 +2607,9 @@ test_util_exit_status(void *ptr)
n = format_helper_exit_status(0x08, -0x242, hex_errno);
test_streq("8/-242\n", hex_errno);
test_eq(n, strlen(hex_errno));
clear_hex_errno(hex_errno);
test_streq("", hex_errno);
done:
;