postgres.git / summary / log / commit / refs

commit    65a5d12be1651a2c535c8b8f5e99a695d4036159
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Sat Dec 12 19:24:51 2009 +0000
First released in: 9.0.0, 8.0.24, 8.1.20, 8.2.16, 8.3.10, 8.4.3

    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.


src/backend/utils/adt/varbit.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c index 23f8d2c9c25..3db46c690f1 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.57 2008/01/01 19:45:53 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.57.2.1 2009/12/12 19:24:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1346,7 +1346,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 */ @@ -1425,7 +1430,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 */ [parent: f25013104a1f]