mirror of git://gcc.gnu.org/git/gcc.git
floatformat.c (get_field): Fix segfault with little-endian word order on 64-bit hosts.
* floatformat.c (get_field): Fix segfault with little-endian word order on 64-bit hosts. (put_field): Likewise. (min): Move definition. From-SVN: r118552
This commit is contained in:
parent
d81ecf52ff
commit
36b8206084
|
@ -1,3 +1,10 @@
|
||||||
|
2006-11-07 Julian Brown <julian@codesourcery.com>
|
||||||
|
|
||||||
|
* floatformat.c (get_field): Fix segfault with little-endian word
|
||||||
|
order on 64-bit hosts.
|
||||||
|
(put_field): Likewise.
|
||||||
|
(min): Move definition.
|
||||||
|
|
||||||
2006-10-26 Danny Smith <dannysmith@users.sourceforge.net>
|
2006-10-26 Danny Smith <dannysmith@users.sourceforge.net>
|
||||||
|
|
||||||
pex-win32.c (argv_to_cmdline): Replace xmalloc with XNEWVEC.
|
pex-win32.c (argv_to_cmdline): Replace xmalloc with XNEWVEC.
|
||||||
|
|
|
@ -249,53 +249,51 @@ const struct floatformat floatformat_ia64_quad_little =
|
||||||
floatformat_always_valid
|
floatformat_always_valid
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef min
|
||||||
|
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Extract a field which starts at START and is LEN bits long. DATA and
|
/* Extract a field which starts at START and is LEN bits long. DATA and
|
||||||
TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */
|
TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */
|
||||||
static unsigned long
|
static unsigned long
|
||||||
get_field (const unsigned char *data, enum floatformat_byteorders order,
|
get_field (const unsigned char *data, enum floatformat_byteorders order,
|
||||||
unsigned int total_len, unsigned int start, unsigned int len)
|
unsigned int total_len, unsigned int start, unsigned int len)
|
||||||
{
|
{
|
||||||
unsigned long result;
|
unsigned long result = 0;
|
||||||
unsigned int cur_byte;
|
unsigned int cur_byte;
|
||||||
int cur_bitshift;
|
int lo_bit, hi_bit, cur_bitshift = 0;
|
||||||
|
int nextbyte = (order == floatformat_little) ? 1 : -1;
|
||||||
|
|
||||||
|
/* Start is in big-endian bit order! Fix that first. */
|
||||||
|
start = total_len - (start + len);
|
||||||
|
|
||||||
/* Start at the least significant part of the field. */
|
/* Start at the least significant part of the field. */
|
||||||
cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
|
|
||||||
if (order == floatformat_little)
|
if (order == floatformat_little)
|
||||||
cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - cur_byte - 1;
|
cur_byte = start / FLOATFORMAT_CHAR_BIT;
|
||||||
cur_bitshift =
|
|
||||||
((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
|
|
||||||
result = *(data + cur_byte) >> (-cur_bitshift);
|
|
||||||
cur_bitshift += FLOATFORMAT_CHAR_BIT;
|
|
||||||
if (order == floatformat_little)
|
|
||||||
++cur_byte;
|
|
||||||
else
|
else
|
||||||
--cur_byte;
|
cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
|
||||||
|
|
||||||
/* Move towards the most significant part of the field. */
|
lo_bit = start % FLOATFORMAT_CHAR_BIT;
|
||||||
while ((unsigned int) cur_bitshift < len)
|
hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
|
||||||
|
|
||||||
|
do
|
||||||
{
|
{
|
||||||
if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT)
|
unsigned int shifted = *(data + cur_byte) >> lo_bit;
|
||||||
/* This is the last byte; zero out the bits which are not part of
|
unsigned int bits = hi_bit - lo_bit;
|
||||||
this field. */
|
unsigned int mask = (1 << bits) - 1;
|
||||||
result |=
|
result |= (shifted & mask) << cur_bitshift;
|
||||||
(*(data + cur_byte) & ((1 << (len - cur_bitshift)) - 1))
|
len -= bits;
|
||||||
<< cur_bitshift;
|
cur_bitshift += bits;
|
||||||
else
|
cur_byte += nextbyte;
|
||||||
result |= *(data + cur_byte) << cur_bitshift;
|
lo_bit = 0;
|
||||||
cur_bitshift += FLOATFORMAT_CHAR_BIT;
|
hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
|
||||||
if (order == floatformat_little)
|
|
||||||
++cur_byte;
|
|
||||||
else
|
|
||||||
--cur_byte;
|
|
||||||
}
|
}
|
||||||
|
while (len != 0);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef min
|
|
||||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Convert from FMT to a double.
|
/* Convert from FMT to a double.
|
||||||
FROM is the address of the extended float.
|
FROM is the address of the extended float.
|
||||||
Store the double in *TO. */
|
Store the double in *TO. */
|
||||||
|
@ -428,43 +426,34 @@ put_field (unsigned char *data, enum floatformat_byteorders order,
|
||||||
unsigned long stuff_to_put)
|
unsigned long stuff_to_put)
|
||||||
{
|
{
|
||||||
unsigned int cur_byte;
|
unsigned int cur_byte;
|
||||||
int cur_bitshift;
|
int lo_bit, hi_bit;
|
||||||
|
int nextbyte = (order == floatformat_little) ? 1 : -1;
|
||||||
|
|
||||||
|
/* Start is in big-endian bit order! Fix that first. */
|
||||||
|
start = total_len - (start + len);
|
||||||
|
|
||||||
/* Start at the least significant part of the field. */
|
/* Start at the least significant part of the field. */
|
||||||
cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
|
|
||||||
if (order == floatformat_little)
|
if (order == floatformat_little)
|
||||||
cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - cur_byte - 1;
|
cur_byte = start / FLOATFORMAT_CHAR_BIT;
|
||||||
cur_bitshift =
|
|
||||||
((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
|
|
||||||
*(data + cur_byte) &=
|
|
||||||
~(((1 << ((start + len) % FLOATFORMAT_CHAR_BIT)) - 1) << (-cur_bitshift));
|
|
||||||
*(data + cur_byte) |=
|
|
||||||
(stuff_to_put & ((1 << FLOATFORMAT_CHAR_BIT) - 1)) << (-cur_bitshift);
|
|
||||||
cur_bitshift += FLOATFORMAT_CHAR_BIT;
|
|
||||||
if (order == floatformat_little)
|
|
||||||
++cur_byte;
|
|
||||||
else
|
else
|
||||||
--cur_byte;
|
cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
|
||||||
|
|
||||||
/* Move towards the most significant part of the field. */
|
lo_bit = start % FLOATFORMAT_CHAR_BIT;
|
||||||
while ((unsigned int) cur_bitshift < len)
|
hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
|
||||||
|
|
||||||
|
do
|
||||||
{
|
{
|
||||||
if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT)
|
unsigned char *byte_ptr = data + cur_byte;
|
||||||
{
|
unsigned int bits = hi_bit - lo_bit;
|
||||||
/* This is the last byte. */
|
unsigned int mask = ((1 << bits) - 1) << lo_bit;
|
||||||
*(data + cur_byte) &=
|
*byte_ptr = (*byte_ptr & ~mask) | ((stuff_to_put << lo_bit) & mask);
|
||||||
~((1 << (len - cur_bitshift)) - 1);
|
stuff_to_put >>= bits;
|
||||||
*(data + cur_byte) |= (stuff_to_put >> cur_bitshift);
|
len -= bits;
|
||||||
}
|
cur_byte += nextbyte;
|
||||||
else
|
lo_bit = 0;
|
||||||
*(data + cur_byte) = ((stuff_to_put >> cur_bitshift)
|
hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
|
||||||
& ((1 << FLOATFORMAT_CHAR_BIT) - 1));
|
|
||||||
cur_bitshift += FLOATFORMAT_CHAR_BIT;
|
|
||||||
if (order == floatformat_little)
|
|
||||||
++cur_byte;
|
|
||||||
else
|
|
||||||
--cur_byte;
|
|
||||||
}
|
}
|
||||||
|
while (len != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The converse: convert the double *FROM to an extended float
|
/* The converse: convert the double *FROM to an extended float
|
||||||
|
|
Loading…
Reference in New Issue