diff options
-rw-r--r-- | src/common/util.c | 8 | ||||
-rw-r--r-- | src/test/test_util.c | 23 |
2 files changed, 30 insertions, 1 deletions
diff --git a/src/common/util.c b/src/common/util.c index 297ae7806e..3acae1c118 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -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; } diff --git a/src/test/test_util.c b/src/test/test_util.c index f091fc95a1..eed37ca817 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -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: ; |