From 5a2967412f63f3b9390aa7b3af95e2fae0965ff8 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 4 Nov 2019 08:30:00 +0100
Subject: [PATCH] Catch invalid typlens in a couple of places

Rearrange the logic in record_image_cmp() and datum_image_eq() to
error out on unexpected typlens (either not supported there or
completely invalid due to corruption).  Barring corruption, this is
not possible today but it seems more future-proof and robust to fix
this.

Reported-by: Peter Geoghegan <pg@bowt.ie>
---
 src/backend/utils/adt/datum.c    | 22 ++++++++++++----------
 src/backend/utils/adt/rowtypes.c | 24 +++++++++++++-----------
 2 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/src/backend/utils/adt/datum.c b/src/backend/utils/adt/datum.c
index 81ea5a48e59..76bd7ee1aa0 100644
--- a/src/backend/utils/adt/datum.c
+++ b/src/backend/utils/adt/datum.c
@@ -265,7 +265,17 @@ datum_image_eq(Datum value1, Datum value2, bool typByVal, int typLen)
 {
 	bool		result = true;
 
-	if (typLen == -1)
+	if (typByVal)
+	{
+		result = (value1 == value2);
+	}
+	else if (typLen > 0)
+	{
+		result = (memcmp(DatumGetPointer(value1),
+						 DatumGetPointer(value2),
+						 typLen) == 0);
+	}
+	else if (typLen == -1)
 	{
 		Size		len1,
 					len2;
@@ -294,16 +304,8 @@ datum_image_eq(Datum value1, Datum value2, bool typByVal, int typLen)
 				pfree(arg2val);
 		}
 	}
-	else if (typByVal)
-	{
-		result = (value1 == value2);
-	}
 	else
-	{
-		result = (memcmp(DatumGetPointer(value1),
-						 DatumGetPointer(value2),
-						 typLen) == 0);
-	}
+		elog(ERROR, "unexpected typLen: %d", typLen);
 
 	return result;
 }
diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c
index aa7ec8735c4..4d6cfc68b86 100644
--- a/src/backend/utils/adt/rowtypes.c
+++ b/src/backend/utils/adt/rowtypes.c
@@ -1443,7 +1443,18 @@ record_image_cmp(FunctionCallInfo fcinfo)
 			}
 
 			/* Compare the pair of elements */
-			if (att1->attlen == -1)
+			if (att1->attbyval)
+			{
+				if (values1[i1] != values2[i2])
+					cmpresult = (values1[i1] < values2[i2]) ? -1 : 1;
+			}
+			else if (att1->attlen > 0)
+			{
+				cmpresult = memcmp(DatumGetPointer(values1[i1]),
+								   DatumGetPointer(values2[i2]),
+								   att1->attlen);
+			}
+			else if (att1->attlen == -1)
 			{
 				Size		len1,
 							len2;
@@ -1466,17 +1477,8 @@ record_image_cmp(FunctionCallInfo fcinfo)
 				if ((Pointer) arg2val != (Pointer) values2[i2])
 					pfree(arg2val);
 			}
-			else if (att1->attbyval)
-			{
-				if (values1[i1] != values2[i2])
-					cmpresult = (values1[i1] < values2[i2]) ? -1 : 1;
-			}
 			else
-			{
-				cmpresult = memcmp(DatumGetPointer(values1[i1]),
-								   DatumGetPointer(values2[i2]),
-								   att1->attlen);
-			}
+				elog(ERROR, "unexpected attlen: %d", att1->attlen);
 
 			if (cmpresult < 0)
 			{
-- 
GitLab