mirror of
https://frontier.innolan.net/rainlance/amiga-tz.git
synced 2025-11-22 10:10:54 +00:00
Avoid left-shift-into-sign-bit undefined behavior
Problem reported by Joseph Myers in: https://gcc.gnu.org/ml/gcc-patches/2015-05/msg00704.html * localtime.c (detzcode, detzcode64): Don't rely on undefined behavior with left shift into sign bit. Port better to non-2's-complement machines. * private.h (TWOS_COMPLEMENT, MAXVAL, MINVAL): New macros. * private.h (time_t_min, time_t_max): * zic.c (min_time, max_time): Use them to avoid undefined behavior. * zdump.c (atime_shift): New constant. (absolute_min_time, absolute_max_time): Use it to avoid undefined behavior.
This commit is contained in:
32
localtime.c
32
localtime.c
@ -216,22 +216,44 @@ detzcode(const char *const codep)
|
||||
{
|
||||
register int_fast32_t result;
|
||||
register int i;
|
||||
int_fast32_t one = 1;
|
||||
int_fast32_t halfmaxval = one << (32 - 2);
|
||||
int_fast32_t maxval = halfmaxval - 1 + halfmaxval;
|
||||
int_fast32_t minval = -1 - maxval;
|
||||
|
||||
result = (codep[0] & 0x80) ? -1 : 0;
|
||||
for (i = 0; i < 4; ++i)
|
||||
result = codep[0] & 0x7f;
|
||||
for (i = 1; i < 4; ++i)
|
||||
result = (result << 8) | (codep[i] & 0xff);
|
||||
|
||||
if (codep[0] & 0x80) {
|
||||
/* Do two's-complement negation even on non-two's-complement machines.
|
||||
If the result would be minval - 1, return minval. */
|
||||
result -= !TWOS_COMPLEMENT(int_fast32_t) && result != 0;
|
||||
result += minval;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int_fast64_t
|
||||
detzcode64(const char *const codep)
|
||||
{
|
||||
register int_fast64_t result;
|
||||
register uint_fast64_t result;
|
||||
register int i;
|
||||
int_fast64_t one = 1;
|
||||
int_fast64_t halfmaxval = one << (64 - 2);
|
||||
int_fast64_t maxval = halfmaxval - 1 + halfmaxval;
|
||||
int_fast64_t minval = -TWOS_COMPLEMENT(int_fast64_t) - maxval;
|
||||
|
||||
result = (codep[0] & 0x80) ? -1 : 0;
|
||||
for (i = 0; i < 8; ++i)
|
||||
result = codep[0] & 0x7f;
|
||||
for (i = 1; i < 8; ++i)
|
||||
result = (result << 8) | (codep[i] & 0xff);
|
||||
|
||||
if (codep[0] & 0x80) {
|
||||
/* Do two's-complement negation even on non-two's-complement machines.
|
||||
If the result would be minval - 1, return minval. */
|
||||
result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0;
|
||||
result += minval;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user