Commit 3492a0af authored by Tom Lane's avatar Tom Lane

Fix RelationBuildPartitionKey's processing of partition key expressions.

Failure to advance the list pointer while reading partition expressions
from a list results in invoking an input function with inappropriate data,
possibly leading to crashes or, with carefully crafted input, disclosure
of arbitrary backend memory.

Bug discovered independently by Álvaro Herrera and David Rowley.
This patch is by Álvaro but owes something to David's proposed fix.
Back-patch to v10 where the issue was introduced.

Security: CVE-2018-1052
parent 05d0f13f
...@@ -983,9 +983,14 @@ RelationBuildPartitionKey(Relation relation) ...@@ -983,9 +983,14 @@ RelationBuildPartitionKey(Relation relation)
} }
else else
{ {
if (partexprs_item == NULL)
elog(ERROR, "wrong number of partition key expressions");
key->parttypid[i] = exprType(lfirst(partexprs_item)); key->parttypid[i] = exprType(lfirst(partexprs_item));
key->parttypmod[i] = exprTypmod(lfirst(partexprs_item)); key->parttypmod[i] = exprTypmod(lfirst(partexprs_item));
key->parttypcoll[i] = exprCollation(lfirst(partexprs_item)); key->parttypcoll[i] = exprCollation(lfirst(partexprs_item));
partexprs_item = lnext(partexprs_item);
} }
get_typlenbyvalalign(key->parttypid[i], get_typlenbyvalalign(key->parttypid[i],
&key->parttyplen[i], &key->parttyplen[i],
......
...@@ -419,8 +419,9 @@ DETAIL: table partitioned depends on function plusone(integer) ...@@ -419,8 +419,9 @@ DETAIL: table partitioned depends on function plusone(integer)
HINT: Use DROP ... CASCADE to drop the dependent objects too. HINT: Use DROP ... CASCADE to drop the dependent objects too.
-- partitioned table cannot participate in regular inheritance -- partitioned table cannot participate in regular inheritance
CREATE TABLE partitioned2 ( CREATE TABLE partitioned2 (
a int a int,
) PARTITION BY LIST ((a+1)); b text
) PARTITION BY RANGE ((a+1), substr(b, 1, 5));
CREATE TABLE fail () INHERITS (partitioned2); CREATE TABLE fail () INHERITS (partitioned2);
ERROR: cannot inherit from partitioned table "partitioned2" ERROR: cannot inherit from partitioned table "partitioned2"
-- Partition key in describe output -- Partition key in describe output
...@@ -436,13 +437,27 @@ Partition key: RANGE (a oid_ops, plusone(b), c, d COLLATE "C") ...@@ -436,13 +437,27 @@ Partition key: RANGE (a oid_ops, plusone(b), c, d COLLATE "C")
Number of partitions: 0 Number of partitions: 0
\d+ partitioned2 \d+ partitioned2
Table "public.partitioned2" Table "public.partitioned2"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
--------+---------+-----------+----------+---------+---------+--------------+------------- --------+---------+-----------+----------+---------+----------+--------------+-------------
a | integer | | | | plain | | a | integer | | | | plain | |
Partition key: LIST (((a + 1))) b | text | | | | extended | |
Partition key: RANGE (((a + 1)), substr(b, 1, 5))
Number of partitions: 0 Number of partitions: 0
INSERT INTO partitioned2 VALUES (1, 'hello');
ERROR: no partition of relation "partitioned2" found for row
DETAIL: Partition key of the failing row contains ((a + 1), substr(b, 1, 5)) = (2, hello).
CREATE TABLE part2_1 PARTITION OF partitioned2 FOR VALUES FROM (-1, 'aaaaa') TO (100, 'ccccc');
\d+ part2_1
Table "public.part2_1"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
--------+---------+-----------+----------+---------+----------+--------------+-------------
a | integer | | | | plain | |
b | text | | | | extended | |
Partition of: partitioned2 FOR VALUES FROM ('-1', 'aaaaa') TO (100, 'ccccc')
Partition constraint: (((a + 1) IS NOT NULL) AND (substr(b, 1, 5) IS NOT NULL) AND (((a + 1) > '-1'::integer) OR (((a + 1) = '-1'::integer) AND (substr(b, 1, 5) >= 'aaaaa'::text))) AND (((a + 1) < 100) OR (((a + 1) = 100) AND (substr(b, 1, 5) < 'ccccc'::text))))
DROP TABLE partitioned, partitioned2; DROP TABLE partitioned, partitioned2;
-- --
-- Partitions -- Partitions
......
...@@ -419,14 +419,19 @@ DROP FUNCTION plusone(int); ...@@ -419,14 +419,19 @@ DROP FUNCTION plusone(int);
-- partitioned table cannot participate in regular inheritance -- partitioned table cannot participate in regular inheritance
CREATE TABLE partitioned2 ( CREATE TABLE partitioned2 (
a int a int,
) PARTITION BY LIST ((a+1)); b text
) PARTITION BY RANGE ((a+1), substr(b, 1, 5));
CREATE TABLE fail () INHERITS (partitioned2); CREATE TABLE fail () INHERITS (partitioned2);
-- Partition key in describe output -- Partition key in describe output
\d partitioned \d partitioned
\d+ partitioned2 \d+ partitioned2
INSERT INTO partitioned2 VALUES (1, 'hello');
CREATE TABLE part2_1 PARTITION OF partitioned2 FOR VALUES FROM (-1, 'aaaaa') TO (100, 'ccccc');
\d+ part2_1
DROP TABLE partitioned, partitioned2; DROP TABLE partitioned, partitioned2;
-- --
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment