Commit 36b82060 by Julian Brown Committed by Julian Brown

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
parent d81ecf52
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 = ...@@ -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, ...@@ -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)
cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - cur_byte - 1;
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) if (order == floatformat_little)
++cur_byte; cur_byte = start / FLOATFORMAT_CHAR_BIT;
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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment