Skip to content

Commit 32fdf42

Browse files
committed
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>
1 parent 13d3180 commit 32fdf42

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

src/backend/utils/adt/varbit.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ bit_recv(PG_FUNCTION_ARGS)
305305
bits8 mask;
306306

307307
bitlen = pq_getmsgint(buf, sizeof(int32));
308-
if (bitlen < 0)
308+
if (bitlen < 0 || bitlen > VARBITMAXLEN)
309309
ereport(ERROR,
310310
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
311311
errmsg("invalid length in external bit string")));
@@ -368,7 +368,7 @@ bit(PG_FUNCTION_ARGS)
368368
bits8 mask;
369369

370370
/* No work if typmod is invalid or supplied data matches it already */
371-
if (len <= 0 || len == VARBITLEN(arg))
371+
if (len <= 0 || len > VARBITMAXLEN || len == VARBITLEN(arg))
372372
PG_RETURN_VARBIT_P(arg);
373373

374374
if (!isExplicit)
@@ -621,7 +621,7 @@ varbit_recv(PG_FUNCTION_ARGS)
621621
bits8 mask;
622622

623623
bitlen = pq_getmsgint(buf, sizeof(int32));
624-
if (bitlen < 0)
624+
if (bitlen < 0 || bitlen > VARBITMAXLEN)
625625
ereport(ERROR,
626626
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
627627
errmsg("invalid length in external bit string")));
@@ -1387,9 +1387,14 @@ bitshiftleft(PG_FUNCTION_ARGS)
13871387

13881388
/* Negative shift is a shift to the right */
13891389
if (shft < 0)
1390+
{
1391+
/* Prevent integer overflow in negation */
1392+
if (shft < -VARBITMAXLEN)
1393+
shft = -VARBITMAXLEN;
13901394
PG_RETURN_DATUM(DirectFunctionCall2(bitshiftright,
13911395
VarBitPGetDatum(arg),
13921396
Int32GetDatum(-shft)));
1397+
}
13931398

13941399
result = (VarBit *) palloc(VARSIZE(arg));
13951400
SET_VARSIZE(result, VARSIZE(arg));
@@ -1447,9 +1452,14 @@ bitshiftright(PG_FUNCTION_ARGS)
14471452

14481453
/* Negative shift is a shift to the left */
14491454
if (shft < 0)
1455+
{
1456+
/* Prevent integer overflow in negation */
1457+
if (shft < -VARBITMAXLEN)
1458+
shft = -VARBITMAXLEN;
14501459
PG_RETURN_DATUM(DirectFunctionCall2(bitshiftleft,
14511460
VarBitPGetDatum(arg),
14521461
Int32GetDatum(-shft)));
1462+
}
14531463

14541464
result = (VarBit *) palloc(VARSIZE(arg));
14551465
SET_VARSIZE(result, VARSIZE(arg));
@@ -1507,7 +1517,7 @@ bitfromint4(PG_FUNCTION_ARGS)
15071517
int destbitsleft,
15081518
srcbitsleft;
15091519

1510-
if (typmod <= 0)
1520+
if (typmod <= 0 || typmod > VARBITMAXLEN)
15111521
typmod = 1; /* default bit length */
15121522

15131523
rlen = VARBITTOTALLEN(typmod);
@@ -1587,7 +1597,7 @@ bitfromint8(PG_FUNCTION_ARGS)
15871597
int destbitsleft,
15881598
srcbitsleft;
15891599

1590-
if (typmod <= 0)
1600+
if (typmod <= 0 || typmod > VARBITMAXLEN)
15911601
typmod = 1; /* default bit length */
15921602

15931603
rlen = VARBITTOTALLEN(typmod);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy