mirror of
https://github.com/mirror/wget.git
synced 2025-01-23 18:50:11 +08:00
[svn] Don't assume that strtoll_type is 64 bits wide. Don't rely on undefined
behavior to check overflow.
This commit is contained in:
parent
f2756871a6
commit
48f21f4a71
@ -1,3 +1,9 @@
|
|||||||
|
2006-06-26 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
|
* cmpt.c (strtoll): Check for overflow and underflow without
|
||||||
|
relying on (technically) undefined behavior. Don't assume that
|
||||||
|
strtoll_type is 64 bits wide.
|
||||||
|
|
||||||
2006-06-21 Hrvoje Niksic <hniksic@xemacs.org>
|
2006-06-21 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
* utils.c (base64_encode): Cast void pointer to char * before
|
* utils.c (base64_encode): Cast void pointer to char * before
|
||||||
|
55
src/cmpt.c
55
src/cmpt.c
@ -1315,18 +1315,19 @@ char_value (char c, int base)
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LL strtoll_type /* long long or __int64 */
|
#define TYPE_MAXIMUM(t) ((t) (~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
|
||||||
|
|
||||||
/* These constants assume 64-bit strtoll_type. */
|
#define STRTOLL_MAX TYPE_MAXIMUM (strtoll_type)
|
||||||
|
/* This definition assumes two's complement arithmetic */
|
||||||
|
#define STRTOLL_MIN (-STRTOLL_MAX - 1)
|
||||||
|
|
||||||
/* A roundabout way of writing 2**63-1 = 9223372036854775807 */
|
/* Like a%b, but always returns a positive number when A is negative.
|
||||||
#define STRTOLL_OVERFLOW (((LL) 1 << 62) - 1 + ((LL) 1 << 62))
|
(C doesn't guarantee the sign of the result.) */
|
||||||
/* A roundabout way of writing -2**63 = -9223372036854775808 */
|
#define MOD(a, b) ((strtoll_type) -1 % 2 == 1 ? (a) % (b) : - ((a) % (b)))
|
||||||
#define STRTOLL_UNDERFLOW (-STRTOLL_OVERFLOW - 1)
|
|
||||||
|
|
||||||
/* A strtoll replacement for systems that have LFS but don't supply
|
/* A strtoll-like replacement for systems that have an integral type
|
||||||
strtoll. The headers typedef strtoll_type to long long or to
|
larger than long but don't supply strtoll. This implementation
|
||||||
__int64. */
|
makes no assumptions about the size of strtoll_type. */
|
||||||
|
|
||||||
strtoll_type
|
strtoll_type
|
||||||
strtoll (const char *nptr, char **endptr, int base)
|
strtoll (const char *nptr, char **endptr, int base)
|
||||||
@ -1355,7 +1356,7 @@ strtoll (const char *nptr, char **endptr, int base)
|
|||||||
else
|
else
|
||||||
negative = false;
|
negative = false;
|
||||||
|
|
||||||
/* If base is 0, determine the real base based on the beginning on
|
/* If BASE is 0, determine the real base based on the beginning on
|
||||||
the number; octal numbers begin with "0", hexadecimal with "0x",
|
the number; octal numbers begin with "0", hexadecimal with "0x",
|
||||||
and the others are considered octal. */
|
and the others are considered octal. */
|
||||||
if (*nptr == '0')
|
if (*nptr == '0')
|
||||||
@ -1383,33 +1384,38 @@ strtoll (const char *nptr, char **endptr, int base)
|
|||||||
if (!negative)
|
if (!negative)
|
||||||
{
|
{
|
||||||
/* Parse positive number, checking for overflow. */
|
/* Parse positive number, checking for overflow. */
|
||||||
int val;
|
int digit;
|
||||||
for (; (val = char_value (*nptr, base)) != -1; ++nptr)
|
/* Overflow watermark. If RESULT exceeds it, overflow occurs on
|
||||||
|
this digit. If result==WATERMARK, current digit may not
|
||||||
|
exceed the last digit of maximum value. */
|
||||||
|
const strtoll_type WATERMARK = STRTOLL_MAX / base;
|
||||||
|
for (; (digit = char_value (*nptr, base)) != -1; ++nptr)
|
||||||
{
|
{
|
||||||
strtoll_type newresult = base * result + val;
|
if (result > WATERMARK
|
||||||
if (newresult < result)
|
|| (result == WATERMARK && digit > STRTOLL_MAX % base))
|
||||||
{
|
{
|
||||||
result = STRTOLL_OVERFLOW;
|
result = STRTOLL_MAX;
|
||||||
errno = ERANGE;
|
errno = ERANGE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
result = newresult;
|
result = base * result + digit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Parse negative number, checking for underflow. */
|
/* Parse negative number, checking for underflow. */
|
||||||
int val;
|
int digit;
|
||||||
for (; (val = char_value (*nptr, base)) != -1; ++nptr)
|
const strtoll_type WATERMARK = STRTOLL_MIN / base;
|
||||||
|
for (; (digit = char_value (*nptr, base)) != -1; ++nptr)
|
||||||
{
|
{
|
||||||
strtoll_type newresult = base * result - val;
|
if (result < WATERMARK
|
||||||
if (newresult > result)
|
|| (result == WATERMARK && digit > MOD (STRTOLL_MIN, base)))
|
||||||
{
|
{
|
||||||
result = STRTOLL_UNDERFLOW;
|
result = STRTOLL_MIN;
|
||||||
errno = ERANGE;
|
errno = ERANGE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
result = newresult;
|
result = base * result - digit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
@ -1417,4 +1423,9 @@ strtoll (const char *nptr, char **endptr, int base)
|
|||||||
*endptr = (char *) nptr;
|
*endptr = (char *) nptr;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef STRTOLL_MAX
|
||||||
|
#undef STRTOLL_MIN
|
||||||
|
#undef ABS
|
||||||
|
|
||||||
#endif /* NEED_STRTOLL */
|
#endif /* NEED_STRTOLL */
|
||||||
|
Loading…
Reference in New Issue
Block a user