Skip to content

Commit 1fee24a

Browse files
committed
Catch invalid typlens in a couple of places
Rearrange the logic in record_image_cmp() and record_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>
1 parent 4077e9a commit 1fee24a

File tree

1 file changed

+61
-56
lines changed

1 file changed

+61
-56
lines changed

src/backend/utils/adt/rowtypes.c

Lines changed: 61 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,30 +1426,7 @@ record_image_cmp(FunctionCallInfo fcinfo)
14261426
}
14271427

14281428
/* Compare the pair of elements */
1429-
if (tupdesc1->attrs[i1]->attlen == -1)
1430-
{
1431-
Size len1,
1432-
len2;
1433-
struct varlena *arg1val;
1434-
struct varlena *arg2val;
1435-
1436-
len1 = toast_raw_datum_size(values1[i1]);
1437-
len2 = toast_raw_datum_size(values2[i2]);
1438-
arg1val = PG_DETOAST_DATUM_PACKED(values1[i1]);
1439-
arg2val = PG_DETOAST_DATUM_PACKED(values2[i2]);
1440-
1441-
cmpresult = memcmp(VARDATA_ANY(arg1val),
1442-
VARDATA_ANY(arg2val),
1443-
Min(len1, len2) - VARHDRSZ);
1444-
if ((cmpresult == 0) && (len1 != len2))
1445-
cmpresult = (len1 < len2) ? -1 : 1;
1446-
1447-
if ((Pointer) arg1val != (Pointer) values1[i1])
1448-
pfree(arg1val);
1449-
if ((Pointer) arg2val != (Pointer) values2[i2])
1450-
pfree(arg2val);
1451-
}
1452-
else if (tupdesc1->attrs[i1]->attbyval)
1429+
if (tupdesc1->attrs[i1]->attbyval)
14531430
{
14541431
switch (tupdesc1->attrs[i1]->attlen)
14551432
{
@@ -1491,12 +1468,37 @@ record_image_cmp(FunctionCallInfo fcinfo)
14911468
Assert(false); /* cannot happen */
14921469
}
14931470
}
1494-
else
1471+
else if (tupdesc1->attrs[i1]->attlen > 0)
14951472
{
14961473
cmpresult = memcmp(DatumGetPointer(values1[i1]),
14971474
DatumGetPointer(values2[i2]),
14981475
tupdesc1->attrs[i1]->attlen);
14991476
}
1477+
else if (tupdesc1->attrs[i1]->attlen == -1)
1478+
{
1479+
Size len1,
1480+
len2;
1481+
struct varlena *arg1val;
1482+
struct varlena *arg2val;
1483+
1484+
len1 = toast_raw_datum_size(values1[i1]);
1485+
len2 = toast_raw_datum_size(values2[i2]);
1486+
arg1val = PG_DETOAST_DATUM_PACKED(values1[i1]);
1487+
arg2val = PG_DETOAST_DATUM_PACKED(values2[i2]);
1488+
1489+
cmpresult = memcmp(VARDATA_ANY(arg1val),
1490+
VARDATA_ANY(arg2val),
1491+
Min(len1, len2) - VARHDRSZ);
1492+
if ((cmpresult == 0) && (len1 != len2))
1493+
cmpresult = (len1 < len2) ? -1 : 1;
1494+
1495+
if ((Pointer) arg1val != (Pointer) values1[i1])
1496+
pfree(arg1val);
1497+
if ((Pointer) arg2val != (Pointer) values2[i2])
1498+
pfree(arg2val);
1499+
}
1500+
else
1501+
elog(ERROR, "unexpected attlen: %d", tupdesc1->attrs[i1]->attlen);
15001502

15011503
if (cmpresult < 0)
15021504
{
@@ -1687,36 +1689,7 @@ record_image_eq(PG_FUNCTION_ARGS)
16871689
}
16881690

16891691
/* Compare the pair of elements */
1690-
if (tupdesc1->attrs[i1]->attlen == -1)
1691-
{
1692-
Size len1,
1693-
len2;
1694-
1695-
len1 = toast_raw_datum_size(values1[i1]);
1696-
len2 = toast_raw_datum_size(values2[i2]);
1697-
/* No need to de-toast if lengths don't match. */
1698-
if (len1 != len2)
1699-
result = false;
1700-
else
1701-
{
1702-
struct varlena *arg1val;
1703-
struct varlena *arg2val;
1704-
1705-
arg1val = PG_DETOAST_DATUM_PACKED(values1[i1]);
1706-
arg2val = PG_DETOAST_DATUM_PACKED(values2[i2]);
1707-
1708-
result = (memcmp(VARDATA_ANY(arg1val),
1709-
VARDATA_ANY(arg2val),
1710-
len1 - VARHDRSZ) == 0);
1711-
1712-
/* Only free memory if it's a copy made here. */
1713-
if ((Pointer) arg1val != (Pointer) values1[i1])
1714-
pfree(arg1val);
1715-
if ((Pointer) arg2val != (Pointer) values2[i2])
1716-
pfree(arg2val);
1717-
}
1718-
}
1719-
else if (tupdesc1->attrs[i1]->attbyval)
1692+
if (tupdesc1->attrs[i1]->attbyval)
17201693
{
17211694
switch (tupdesc1->attrs[i1]->attlen)
17221695
{
@@ -1742,12 +1715,44 @@ record_image_eq(PG_FUNCTION_ARGS)
17421715
Assert(false); /* cannot happen */
17431716
}
17441717
}
1745-
else
1718+
else if (tupdesc1->attrs[i1]->attlen > 0)
17461719
{
17471720
result = (memcmp(DatumGetPointer(values1[i1]),
17481721
DatumGetPointer(values2[i2]),
17491722
tupdesc1->attrs[i1]->attlen) == 0);
17501723
}
1724+
else if (tupdesc1->attrs[i1]->attlen == -1)
1725+
{
1726+
Size len1,
1727+
len2;
1728+
1729+
len1 = toast_raw_datum_size(values1[i1]);
1730+
len2 = toast_raw_datum_size(values2[i2]);
1731+
/* No need to de-toast if lengths don't match. */
1732+
if (len1 != len2)
1733+
result = false;
1734+
else
1735+
{
1736+
struct varlena *arg1val;
1737+
struct varlena *arg2val;
1738+
1739+
arg1val = PG_DETOAST_DATUM_PACKED(values1[i1]);
1740+
arg2val = PG_DETOAST_DATUM_PACKED(values2[i2]);
1741+
1742+
result = (memcmp(VARDATA_ANY(arg1val),
1743+
VARDATA_ANY(arg2val),
1744+
len1 - VARHDRSZ) == 0);
1745+
1746+
/* Only free memory if it's a copy made here. */
1747+
if ((Pointer) arg1val != (Pointer) values1[i1])
1748+
pfree(arg1val);
1749+
if ((Pointer) arg2val != (Pointer) values2[i2])
1750+
pfree(arg2val);
1751+
}
1752+
}
1753+
else
1754+
elog(ERROR, "unexpected attlen: %d", tupdesc1->attrs[i1]->attlen);
1755+
17511756
if (!result)
17521757
break;
17531758
}

0 commit comments

Comments
 (0)