libarchive: Port upstream issue 320 second fix
Port upstream commit 6cf33c93 (Issue 320: Rewrite (again) to avoid the left shift that CLang dislikes so much, 2013-12-07) into CMake. Inspired-by: Tim Kientzle <kientzle@freebsd.org>
This commit is contained in:
parent
5ee1297d6b
commit
61b39af353
|
@ -2412,9 +2412,10 @@ tar_atol(const char *p, size_t char_cnt)
|
||||||
static int64_t
|
static int64_t
|
||||||
tar_atol_base_n(const char *p, size_t char_cnt, int base)
|
tar_atol_base_n(const char *p, size_t char_cnt, int base)
|
||||||
{
|
{
|
||||||
int64_t l, limit, last_digit_limit;
|
int64_t l, maxval, limit, last_digit_limit;
|
||||||
int digit, sign;
|
int digit, sign;
|
||||||
|
|
||||||
|
maxval = INT64_MAX;
|
||||||
limit = INT64_MAX / base;
|
limit = INT64_MAX / base;
|
||||||
last_digit_limit = INT64_MAX % base;
|
last_digit_limit = INT64_MAX % base;
|
||||||
|
|
||||||
|
@ -2431,6 +2432,10 @@ tar_atol_base_n(const char *p, size_t char_cnt, int base)
|
||||||
sign = -1;
|
sign = -1;
|
||||||
p++;
|
p++;
|
||||||
char_cnt--;
|
char_cnt--;
|
||||||
|
|
||||||
|
maxval = INT64_MIN;
|
||||||
|
limit = -(INT64_MIN / base);
|
||||||
|
last_digit_limit = INT64_MIN % base;
|
||||||
}
|
}
|
||||||
|
|
||||||
l = 0;
|
l = 0;
|
||||||
|
@ -2438,8 +2443,7 @@ tar_atol_base_n(const char *p, size_t char_cnt, int base)
|
||||||
digit = *p - '0';
|
digit = *p - '0';
|
||||||
while (digit >= 0 && digit < base && char_cnt != 0) {
|
while (digit >= 0 && digit < base && char_cnt != 0) {
|
||||||
if (l>limit || (l == limit && digit > last_digit_limit)) {
|
if (l>limit || (l == limit && digit > last_digit_limit)) {
|
||||||
l = INT64_MAX; /* Truncate on overflow. */
|
return maxval; /* Truncate on overflow. */
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
l = (l * base) + digit;
|
l = (l * base) + digit;
|
||||||
digit = *++p - '0';
|
digit = *++p - '0';
|
||||||
|
@ -2462,32 +2466,56 @@ tar_atol10(const char *p, size_t char_cnt)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse a base-256 integer. This is just a straight signed binary
|
* Parse a base-256 integer. This is just a variable-length
|
||||||
* value in big-endian order, except that the high-order bit is
|
* twos-complement signed binary value in big-endian order, except
|
||||||
* ignored.
|
* that the high-order bit is ignored. The values here can be up to
|
||||||
|
* 12 bytes, so we need to be careful about overflowing 64-bit
|
||||||
|
* (8-byte) integers.
|
||||||
|
*
|
||||||
|
* This code unashamedly assumes that the local machine uses 8-bit
|
||||||
|
* bytes and twos-complement arithmetic.
|
||||||
*/
|
*/
|
||||||
static int64_t
|
static int64_t
|
||||||
tar_atol256(const char *_p, size_t char_cnt)
|
tar_atol256(const char *_p, size_t char_cnt)
|
||||||
{
|
{
|
||||||
int64_t l, upper_limit, lower_limit;
|
uint64_t l;
|
||||||
const unsigned char *p = (const unsigned char *)_p;
|
const unsigned char *p = (const unsigned char *)_p;
|
||||||
|
unsigned char c, neg;
|
||||||
|
|
||||||
upper_limit = INT64_MAX / 256;
|
/* Extend 7-bit 2s-comp to 8-bit 2s-comp, decide sign. */
|
||||||
lower_limit = INT64_MIN / 256;
|
c = *p;
|
||||||
|
if (c & 0x40) {
|
||||||
/* Sign-extend the 7-bit value to 64 bits. */
|
neg = 0xff;
|
||||||
if ((0x40 & *p) == 0x40)
|
c |= 0x80;
|
||||||
l = ~((int64_t)0x3f) | *p++;
|
l = ~0ULL;
|
||||||
else
|
} else {
|
||||||
l = 0x3f & *p++;
|
neg = 0;
|
||||||
while (--char_cnt > 0) {
|
c &= 0x7f;
|
||||||
if (l > upper_limit)
|
l = 0;
|
||||||
return (INT64_MAX); /* Truncate on overflow */
|
|
||||||
else if (l < lower_limit)
|
|
||||||
return (INT64_MIN);
|
|
||||||
l = (l << 8) | (0xff & (int64_t)*p++);
|
|
||||||
}
|
}
|
||||||
return (l);
|
|
||||||
|
/* If more than 8 bytes, check that we can ignore
|
||||||
|
* high-order bits without overflow. */
|
||||||
|
while (char_cnt > sizeof(int64_t)) {
|
||||||
|
--char_cnt;
|
||||||
|
if (c != neg)
|
||||||
|
return neg ? INT64_MIN : INT64_MAX;
|
||||||
|
c = *++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* c is first byte that fits; if sign mismatch, return overflow */
|
||||||
|
if ((c ^ neg) & 0x80) {
|
||||||
|
return neg ? INT64_MIN : INT64_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Accumulate remaining bytes. */
|
||||||
|
while (--char_cnt > 0) {
|
||||||
|
l = (l << 8) | c;
|
||||||
|
c = *++p;
|
||||||
|
}
|
||||||
|
l = (l << 8) | c;
|
||||||
|
/* Return signed twos-complement value. */
|
||||||
|
return (int64_t)(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue