mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-04 12:17:26 +02:00
Fix assorted integer-overflow hazards in varbit.c.
bitshiftright() and bitshiftleft() would recursively call each other infinitely if the user passed INT_MIN for the shift amount, due to integer overflow in negating the shift amount. To fix, clamp to -VARBITMAXLEN. That doesn't change the results since any shift distance larger than the input bit string's length produces an all-zeroes result. Also fix some places that seemed inadequately paranoid about input typmods exceeding VARBITMAXLEN. While a typmod accepted by anybit_typmodin() will certainly be much less than that, at least some of these spots are reachable with user-chosen integer values. Andreas Seltenreich and Tom Lane Discussion: <87d1j2zqtz.fsf@credativ.de>
This commit is contained in:
parent
3cd504254f
commit
75c9d9a674
@ -305,7 +305,7 @@ bit_recv(PG_FUNCTION_ARGS)
|
|||||||
bits8 mask;
|
bits8 mask;
|
||||||
|
|
||||||
bitlen = pq_getmsgint(buf, sizeof(int32));
|
bitlen = pq_getmsgint(buf, sizeof(int32));
|
||||||
if (bitlen < 0)
|
if (bitlen < 0 || bitlen > VARBITMAXLEN)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
||||||
errmsg("invalid length in external bit string")));
|
errmsg("invalid length in external bit string")));
|
||||||
@ -368,7 +368,7 @@ bit(PG_FUNCTION_ARGS)
|
|||||||
bits8 mask;
|
bits8 mask;
|
||||||
|
|
||||||
/* No work if typmod is invalid or supplied data matches it already */
|
/* No work if typmod is invalid or supplied data matches it already */
|
||||||
if (len <= 0 || len == VARBITLEN(arg))
|
if (len <= 0 || len > VARBITMAXLEN || len == VARBITLEN(arg))
|
||||||
PG_RETURN_VARBIT_P(arg);
|
PG_RETURN_VARBIT_P(arg);
|
||||||
|
|
||||||
if (!isExplicit)
|
if (!isExplicit)
|
||||||
@ -621,7 +621,7 @@ varbit_recv(PG_FUNCTION_ARGS)
|
|||||||
bits8 mask;
|
bits8 mask;
|
||||||
|
|
||||||
bitlen = pq_getmsgint(buf, sizeof(int32));
|
bitlen = pq_getmsgint(buf, sizeof(int32));
|
||||||
if (bitlen < 0)
|
if (bitlen < 0 || bitlen > VARBITMAXLEN)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
||||||
errmsg("invalid length in external bit string")));
|
errmsg("invalid length in external bit string")));
|
||||||
@ -1387,9 +1387,14 @@ bitshiftleft(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/* Negative shift is a shift to the right */
|
/* Negative shift is a shift to the right */
|
||||||
if (shft < 0)
|
if (shft < 0)
|
||||||
|
{
|
||||||
|
/* Prevent integer overflow in negation */
|
||||||
|
if (shft < -VARBITMAXLEN)
|
||||||
|
shft = -VARBITMAXLEN;
|
||||||
PG_RETURN_DATUM(DirectFunctionCall2(bitshiftright,
|
PG_RETURN_DATUM(DirectFunctionCall2(bitshiftright,
|
||||||
VarBitPGetDatum(arg),
|
VarBitPGetDatum(arg),
|
||||||
Int32GetDatum(-shft)));
|
Int32GetDatum(-shft)));
|
||||||
|
}
|
||||||
|
|
||||||
result = (VarBit *) palloc(VARSIZE(arg));
|
result = (VarBit *) palloc(VARSIZE(arg));
|
||||||
SET_VARSIZE(result, VARSIZE(arg));
|
SET_VARSIZE(result, VARSIZE(arg));
|
||||||
@ -1447,9 +1452,14 @@ bitshiftright(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/* Negative shift is a shift to the left */
|
/* Negative shift is a shift to the left */
|
||||||
if (shft < 0)
|
if (shft < 0)
|
||||||
|
{
|
||||||
|
/* Prevent integer overflow in negation */
|
||||||
|
if (shft < -VARBITMAXLEN)
|
||||||
|
shft = -VARBITMAXLEN;
|
||||||
PG_RETURN_DATUM(DirectFunctionCall2(bitshiftleft,
|
PG_RETURN_DATUM(DirectFunctionCall2(bitshiftleft,
|
||||||
VarBitPGetDatum(arg),
|
VarBitPGetDatum(arg),
|
||||||
Int32GetDatum(-shft)));
|
Int32GetDatum(-shft)));
|
||||||
|
}
|
||||||
|
|
||||||
result = (VarBit *) palloc(VARSIZE(arg));
|
result = (VarBit *) palloc(VARSIZE(arg));
|
||||||
SET_VARSIZE(result, VARSIZE(arg));
|
SET_VARSIZE(result, VARSIZE(arg));
|
||||||
@ -1507,7 +1517,7 @@ bitfromint4(PG_FUNCTION_ARGS)
|
|||||||
int destbitsleft,
|
int destbitsleft,
|
||||||
srcbitsleft;
|
srcbitsleft;
|
||||||
|
|
||||||
if (typmod <= 0)
|
if (typmod <= 0 || typmod > VARBITMAXLEN)
|
||||||
typmod = 1; /* default bit length */
|
typmod = 1; /* default bit length */
|
||||||
|
|
||||||
rlen = VARBITTOTALLEN(typmod);
|
rlen = VARBITTOTALLEN(typmod);
|
||||||
@ -1587,7 +1597,7 @@ bitfromint8(PG_FUNCTION_ARGS)
|
|||||||
int destbitsleft,
|
int destbitsleft,
|
||||||
srcbitsleft;
|
srcbitsleft;
|
||||||
|
|
||||||
if (typmod <= 0)
|
if (typmod <= 0 || typmod > VARBITMAXLEN)
|
||||||
typmod = 1; /* default bit length */
|
typmod = 1; /* default bit length */
|
||||||
|
|
||||||
rlen = VARBITTOTALLEN(typmod);
|
rlen = VARBITTOTALLEN(typmod);
|
||||||
|
Loading…
Reference in New Issue
Block a user