Fix RelationBuildPartitionKey's processing of partition key expressions.
authorTom Lane
Mon, 5 Feb 2018 15:37:30 +0000 (10:37 -0500)
committerTom Lane
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 6bd93b03d080162fbe6116ef689fd797ab8bfdea..5e497aee9fe351d0de4c662271b8bc28015942e1 100644 (file)
@@ -964,9 +964,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 34305a96d02d4fc154945a633d9781f66a1ec484..f887781c6df21e6707a98e7df116d84d70636d27 100644 (file)
@@ -414,8 +414,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
@@ -429,12 +430,26 @@ ERROR:  cannot inherit from partitioned table "partitioned2"
  d      | text    |           |          | 
 Partition key: RANGE (a oid_ops, plusone(b), c, d COLLATE "C")
 
-\d partitioned2
-            Table "public.partitioned2"
- Column |  Type   | Collation | Nullable | Default 
---------+---------+-----------+----------+---------
- a      | integer |           |          | 
-Partition key: LIST (((a + 1)))
+\d+ partitioned2
+                                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))
+
+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;
 --
index c43fc56647f276b3510b6cff9dfa70e523d2db1d..9e8fc2f11f2ef89da261bb4a9957130ffb52d6ad 100644 (file)
@@ -415,13 +415,18 @@ 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
+\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;