[sqlsmith] Infinite recursion in bitshift

Started by Andreas Seltenreichabout 9 years ago6 messages
#1Andreas Seltenreich
seltenreich@gmx.de
1 attachment(s)

Hi,

sqlsmith just found another crasher:

select bit '1' >> (-2^31)::int;

This is due to an integer overflow in bitshiftright()/bitshiftleft()
leading to them recursively calling each other. Patch attached.

regards,
Andreas

Attachments:

0001-Fix-possible-infinite-recursion-on-bitshift.patchtext/x-diffDownload
From cfdc425f75da268e1c2af08f936c59f34b69e577 Mon Sep 17 00:00:00 2001
From: Andreas Seltenreich <seltenreich@gmx.de>
Date: Fri, 14 Oct 2016 20:52:52 +0200
Subject: [PATCH] Fix possible infinite recursion on bitshift.

bitshiftright() and bitshiftleft() would recursively call each other
infinitely when the user passed a MIN_INT for the shift amount due to
an integer overflow.  This patch reduces a negative shift amount to
-VARBITMAXLEN to avoid overflow.
---
 src/backend/utils/adt/varbit.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c
index 75e6a46..d8ecfb6 100644
--- a/src/backend/utils/adt/varbit.c
+++ b/src/backend/utils/adt/varbit.c
@@ -1387,9 +1387,15 @@ bitshiftleft(PG_FUNCTION_ARGS)
 
 	/* Negative shift is a shift to the right */
 	if (shft < 0)
+	{
+		/* Protect against overflow */
+		if (shft < -VARBITMAXLEN)
+			shft = -VARBITMAXLEN;
+
 		PG_RETURN_DATUM(DirectFunctionCall2(bitshiftright,
 											VarBitPGetDatum(arg),
 											Int32GetDatum(-shft)));
+	}
 
 	result = (VarBit *) palloc(VARSIZE(arg));
 	SET_VARSIZE(result, VARSIZE(arg));
@@ -1447,9 +1453,15 @@ bitshiftright(PG_FUNCTION_ARGS)
 
 	/* Negative shift is a shift to the left */
 	if (shft < 0)
+	{
+		/* Protect against overflow */
+		if (shft < -VARBITMAXLEN)
+			shft = -VARBITMAXLEN;
+
 		PG_RETURN_DATUM(DirectFunctionCall2(bitshiftleft,
 											VarBitPGetDatum(arg),
 											Int32GetDatum(-shft)));
+	}
 
 	result = (VarBit *) palloc(VARSIZE(arg));
 	SET_VARSIZE(result, VARSIZE(arg));
-- 
2.9.3

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andreas Seltenreich (#1)
Re: [sqlsmith] Infinite recursion in bitshift

Andreas Seltenreich <seltenreich@gmx.de> writes:

sqlsmith just found another crasher:
select bit '1' >> (-2^31)::int;

Nice catch :-)

This is due to an integer overflow in bitshiftright()/bitshiftleft()
leading to them recursively calling each other. Patch attached.

Seems sane, though I wonder if it'd be better to use -INT_MAX rather
than -VARBITMAXLEN.

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#3Andreas Seltenreich
seltenreich@gmx.de
In reply to: Tom Lane (#2)
Re: [sqlsmith] Infinite recursion in bitshift

Tom Lane writes:

This is due to an integer overflow in bitshiftright()/bitshiftleft()
leading to them recursively calling each other. Patch attached.

Seems sane, though I wonder if it'd be better to use -INT_MAX rather
than -VARBITMAXLEN.

I am undecided between those two. -INT_MAX might be a more precise fix
for the problem, but the extra distance to the danger zone was kind of
soothing :-).

regards,
Andreas

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andreas Seltenreich (#3)
Re: [sqlsmith] Infinite recursion in bitshift

Andreas Seltenreich <seltenreich@gmx.de> writes:

Tom Lane writes:

Seems sane, though I wonder if it'd be better to use -INT_MAX rather
than -VARBITMAXLEN.

I am undecided between those two. -INT_MAX might be a more precise fix
for the problem, but the extra distance to the danger zone was kind of
soothing :-).

Yeah, might as well use the tighter limit.

Poking around in varbit.c, I noticed some other places that were assuming
that a typmod couldn't exceed VARBITMAXLEN. anybit_typmodin() enforces
that, but there are places where a user can shove in an arbitrary integer,
eg

regression=# select "bit"(42, 2147483647);
ERROR: invalid memory alloc request size 18446744073441116169

I fixed those too and pushed it. Thanks for the report!

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#5Merlin Moncure
mmoncure@gmail.com
In reply to: Tom Lane (#4)
Re: [sqlsmith] Infinite recursion in bitshift

On Fri, Oct 14, 2016 at 3:31 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Andreas Seltenreich <seltenreich@gmx.de> writes:

Tom Lane writes:

Seems sane, though I wonder if it'd be better to use -INT_MAX rather
than -VARBITMAXLEN.

I am undecided between those two. -INT_MAX might be a more precise fix
for the problem, but the extra distance to the danger zone was kind of
soothing :-).

Yeah, might as well use the tighter limit.

Poking around in varbit.c, I noticed some other places that were assuming
that a typmod couldn't exceed VARBITMAXLEN. anybit_typmodin() enforces
that, but there are places where a user can shove in an arbitrary integer,
eg

regression=# select "bit"(42, 2147483647);
ERROR: invalid memory alloc request size 18446744073441116169

I fixed those too and pushed it. Thanks for the report!

Curious -- are there real world scenarios where this would happen?

merlin

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#6Tom Lane
tgl@sss.pgh.pa.us
In reply to: Merlin Moncure (#5)
Re: [sqlsmith] Infinite recursion in bitshift

Merlin Moncure <mmoncure@gmail.com> writes:

On Fri, Oct 14, 2016 at 3:31 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Poking around in varbit.c, I noticed some other places that were assuming
that a typmod couldn't exceed VARBITMAXLEN.

Curious -- are there real world scenarios where this would happen?

I think you'd have to be intentionally trying to break it. The largest
varbit typmod you're allowed to declare normally is only ~ 80 million.

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers