diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2009-12-12 19:25:04 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2009-12-12 19:25:04 +0000 |
commit | 3bd13da63ba3be6ff143190fc234e15783d51357 (patch) | |
tree | 9eed9c463b3ea4bcd765980ac2e9424fcc88db03 /src/backend/utils/adt/varbit.c | |
parent | c89eec506415829a8ebb892a80c6aabc645c90cf (diff) | |
download | postgresql-3bd13da63ba3be6ff143190fc234e15783d51357.tar.gz postgresql-3bd13da63ba3be6ff143190fc234e15783d51357.zip |
Fix integer-to-bit-string conversions to handle the first fractional byte
correctly when the output bit width is wider than the given integer by
something other than a multiple of 8 bits.
This has been wrong since I first wrote that code for 8.0 :-(. Kudos to
Roman Kononov for being the first to notice, though I didn't use his
patch. Per bug #5237.
Diffstat (limited to 'src/backend/utils/adt/varbit.c')
-rw-r--r-- | src/backend/utils/adt/varbit.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c index 389749961c6..e027a017dcc 100644 --- a/src/backend/utils/adt/varbit.c +++ b/src/backend/utils/adt/varbit.c @@ -9,7 +9,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.47.2.1 2007/08/21 02:40:18 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.47.2.2 2009/12/12 19:25:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1265,7 +1265,12 @@ bitfromint4(PG_FUNCTION_ARGS) /* store first fractional byte */ if (destbitsleft > srcbitsleft) { - *r++ = (bits8) ((a >> (srcbitsleft - 8)) & BITMASK); + int val = (int) (a >> (destbitsleft - 8)); + + /* Force sign-fill in case the compiler implements >> as zero-fill */ + if (a < 0) + val |= (-1) << (srcbitsleft + 8 - destbitsleft); + *r++ = (bits8) (val & BITMASK); destbitsleft -= 8; } /* Now srcbitsleft and destbitsleft are the same, need not track both */ @@ -1344,7 +1349,12 @@ bitfromint8(PG_FUNCTION_ARGS) /* store first fractional byte */ if (destbitsleft > srcbitsleft) { - *r++ = (bits8) ((a >> (srcbitsleft - 8)) & BITMASK); + int val = (int) (a >> (destbitsleft - 8)); + + /* Force sign-fill in case the compiler implements >> as zero-fill */ + if (a < 0) + val |= (-1) << (srcbitsleft + 8 - destbitsleft); + *r++ = (bits8) (val & BITMASK); destbitsleft -= 8; } /* Now srcbitsleft and destbitsleft are the same, need not track both */ |