]> granicus.if.org Git - postgresql/commitdiff
Fix RelationBuildPartitionKey's processing of partition key expressions.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 5 Feb 2018 15:37:30 +0000 (10:37 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 5 Feb 2018 15:37:30 +0000 (10:37 -0500)
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

src/backend/utils/cache/relcache.c
src/test/regress/expected/create_table.out
src/test/regress/sql/create_table.sql

index c081b88b7334d5ada81a7a271e1c463234d308ab..d5cc246156bf10a8c7d90f2d4608402cbccb21a2 100644 (file)
@@ -983,9 +983,14 @@ RelationBuildPartitionKey(Relation relation)
                }
                else
                {
+                       if (partexprs_item == NULL)
+                               elog(ERROR, "wrong number of partition key expressions");
+
                        key->parttypid[i] = exprType(lfirst(partexprs_item));
                        key->parttypmod[i] = exprTypmod(lfirst(partexprs_item));
                        key->parttypcoll[i] = exprCollation(lfirst(partexprs_item));
+
+                       partexprs_item = lnext(partexprs_item);
                }
                get_typlenbyvalalign(key->parttypid[i],
                                                         &key->parttyplen[i],
index e554ec484449f49d52c2ae35d52197aee81ecca1..f5e56365f58809a679f3d7550d55daeeef876153 100644 (file)
@@ -419,8 +419,9 @@ DETAIL:  table partitioned depends on function plusone(integer)
 HINT:  Use DROP ... CASCADE to drop the dependent objects too.
 -- partitioned table cannot participate in regular inheritance
 CREATE TABLE partitioned2 (
-       a int
-) PARTITION BY LIST ((a+1));
+       a int,
+       b text
+) PARTITION BY RANGE ((a+1), substr(b, 1, 5));
 CREATE TABLE fail () INHERITS (partitioned2);
 ERROR:  cannot inherit from partitioned table "partitioned2"
 -- Partition key in describe output
@@ -436,13 +437,27 @@ Partition key: RANGE (a oid_ops, plusone(b), c, d COLLATE "C")
 Number of partitions: 0
 
 \d+ partitioned2
-                               Table "public.partitioned2"
- Column |  Type   | Collation | Nullable | Default | Storage | Stats target | Description 
---------+---------+-----------+----------+---------+---------+--------------+-------------
- a      | integer |           |          |         | plain   |              | 
-Partition key: LIST (((a + 1)))
+                                Table "public.partitioned2"
+ Column |  Type   | Collation | Nullable | Default | Storage  | Stats target | Description 
+--------+---------+-----------+----------+---------+----------+--------------+-------------
+ a      | integer |           |          |         | plain    |              | 
+ b      | text    |           |          |         | extended |              | 
+Partition key: RANGE (((a + 1)), substr(b, 1, 5))
 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;
 --
 -- Partitions
index a71d9ae7abc337f5389d3a158cca310073cb6283..fdd6d141044e786719dbbefcbe309a58e385ed03 100644 (file)
@@ -419,14 +419,19 @@ DROP FUNCTION plusone(int);
 
 -- partitioned table cannot participate in regular inheritance
 CREATE TABLE partitioned2 (
-       a int
-) PARTITION BY LIST ((a+1));
+       a int,
+       b text
+) PARTITION BY RANGE ((a+1), substr(b, 1, 5));
 CREATE TABLE fail () INHERITS (partitioned2);
 
 -- Partition key in describe output
 \d partitioned
 \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;
 
 --