]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Enforce cube dimension limit in all cube construction functions
authorAlexander Korotkov <akorotkov@postgresql.org>
Thu, 30 Aug 2018 11:18:53 +0000 (14:18 +0300)
committerAlexander Korotkov <akorotkov@postgresql.org>
Fri, 31 Aug 2018 17:21:30 +0000 (20:21 +0300)
contrib/cube has a limit to 100 dimensions for cube datatype.  However, it's
not enforced everywhere, and one can actually construct cube with more than
100 dimensions having then trouble with dump/restore.  This commit add checks
for dimensions limit in all functions responsible for cube construction.
Backpatch to all supported versions.

Reported-by: Andrew Gierth
Discussion: https://postgr.es/m/87va7uybt4.fsf%40news-spur.riddles.org.uk
Author: Andrey Borodin with small additions by me
Review: Tom Lane
Backpatch-through: 9.3

contrib/cube/cube.c
contrib/cube/expected/cube.out
contrib/cube/sql/cube.sql

index 3e82a350629d5577e256ca5d5fabb16a102f9df7..de1cc1f9752cc418b34ed29ffeb6f8bc48576934 100644 (file)
@@ -190,6 +190,13 @@ cube_a_f8_f8(PG_FUNCTION_ARGS)
                                 errmsg("cannot work with arrays containing NULLs")));
 
        dim = ARRNELEMS(ur);
+       if (dim > CUBE_MAX_DIM)
+               ereport(ERROR,
+                               (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+                                errmsg("can't extend cube"),
+                                errdetail("A cube cannot have more than %d dimensions.",
+                                                          CUBE_MAX_DIM)));
+
        if (ARRNELEMS(ll) != dim)
                ereport(ERROR,
                                (errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
@@ -231,6 +238,12 @@ cube_a_f8(PG_FUNCTION_ARGS)
                                 errmsg("cannot work with arrays containing NULLs")));
 
        dim = ARRNELEMS(ur);
+       if (dim > CUBE_MAX_DIM)
+               ereport(ERROR,
+                               (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+                                errmsg("array is too long"),
+                                errdetail("A cube cannot have more than %d dimensions.",
+                                                          CUBE_MAX_DIM)));
 
        dur = ARRPTR(ur);
 
@@ -267,6 +280,13 @@ cube_subset(PG_FUNCTION_ARGS)
        dx = (int32 *) ARR_DATA_PTR(idx);
 
        dim = ARRNELEMS(idx);
+       if (dim > CUBE_MAX_DIM)
+               ereport(ERROR,
+                               (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+                                errmsg("array is too long"),
+                                errdetail("A cube cannot have more than %d dimensions.",
+                                                          CUBE_MAX_DIM)));
+
        size = offsetof(NDBOX, x[0]) +sizeof(double) * 2 * dim;
        result = (NDBOX *) palloc0(size);
        SET_VARSIZE(result, size);
@@ -1452,6 +1472,13 @@ cube_c_f8(PG_FUNCTION_ARGS)
        int                     size;
        int                     i;
 
+       if (c->dim + 1 > CUBE_MAX_DIM)
+               ereport(ERROR,
+                               (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+                                errmsg("can't extend cube"),
+                                errdetail("A cube cannot have more than %d dimensions.",
+                                                          CUBE_MAX_DIM)));
+
        size = offsetof(NDBOX, x[0]) +sizeof(double) * (c->dim + 1) *2;
        result = (NDBOX *) palloc0(size);
        SET_VARSIZE(result, size);
@@ -1479,6 +1506,13 @@ cube_c_f8_f8(PG_FUNCTION_ARGS)
        int                     size;
        int                     i;
 
+       if (c->dim + 1 > CUBE_MAX_DIM)
+               ereport(ERROR,
+                               (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+                                errmsg("can't extend cube"),
+                                errdetail("A cube cannot have more than %d dimensions.",
+                                                          CUBE_MAX_DIM)));
+
        size = offsetof(NDBOX, x[0]) +sizeof(double) * (c->dim + 1) *2;
        result = (NDBOX *) palloc0(size);
        SET_VARSIZE(result, size);
index da16f048c80d44ecce58348f9978ab14bf7a964f..9e0d11b435e43e2089cb63b176ad2dd2fc483f34 100644 (file)
@@ -373,9 +373,21 @@ SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]);
 
 SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[4,0]);
 ERROR:  Index out of bounds
+-- test for limits: this should pass
+SELECT cube_subset(cube('(6,7,8),(6,7,8)'), array(SELECT 1 as a FROM generate_series(1,100)));
+                                                                                                                                                 cube_subset                                                                                                                                                  
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ (6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6)
+(1 row)
+
+-- and this should fail
+SELECT cube_subset(cube('(6,7,8),(6,7,8)'), array(SELECT 1 as a FROM generate_series(1,101)));
+ERROR:  array is too long
+DETAIL:  A cube cannot have more than 100 dimensions.
 --
 -- Testing limit of CUBE_MAX_DIM dimensions check in cube_in.
 --
+-- create too big cube from literal
 select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)'::cube;
 ERROR:  bad cube representation
 LINE 1: select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0...
@@ -386,6 +398,34 @@ ERROR:  bad cube representation
 LINE 1: select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0...
                ^
 DETAIL:  A cube cannot have more than 100 dimensions.
+-- from an array
+select cube(array(SELECT 0 as a FROM generate_series(1,101)));
+ERROR:  array is too long
+DETAIL:  A cube cannot have more than 100 dimensions.
+select cube(array(SELECT 0 as a FROM generate_series(1,101)),array(SELECT 0 as a FROM generate_series(1,101)));
+ERROR:  can't extend cube
+DETAIL:  A cube cannot have more than 100 dimensions.
+-- extend cube beyond limit
+-- this should work
+select cube(array(SELECT 0 as a FROM generate_series(1,100)));
+                                                                                                                                                     cube                                                                                                                                                     
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+(1 row)
+
+select cube(array(SELECT 0 as a FROM generate_series(1,100)),array(SELECT 0 as a FROM generate_series(1,100)));
+                                                                                                                                                     cube                                                                                                                                                     
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+(1 row)
+
+-- this should fail
+select cube(cube(array(SELECT 0 as a FROM generate_series(1,100))), 0);
+ERROR:  can't extend cube
+DETAIL:  A cube cannot have more than 100 dimensions.
+select cube(cube(array(SELECT 0 as a FROM generate_series(1,100)),array(SELECT 0 as a FROM generate_series(1,100))), 0, 0);
+ERROR:  can't extend cube
+DETAIL:  A cube cannot have more than 100 dimensions.
 --
 -- testing the  operators
 --
index 84eae09015926bb860a52b6a9d2cb11a363e5765..77797ee6269b0c6ac7cb2503747616800e9522a9 100644 (file)
@@ -96,13 +96,29 @@ SELECT cube(NULL::float[], '{3}'::float[]);
 SELECT cube('{0,1,2}'::float[]);
 SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]);
 SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[4,0]);
+-- test for limits: this should pass
+SELECT cube_subset(cube('(6,7,8),(6,7,8)'), array(SELECT 1 as a FROM generate_series(1,100)));
+-- and this should fail
+SELECT cube_subset(cube('(6,7,8),(6,7,8)'), array(SELECT 1 as a FROM generate_series(1,101)));
 
 --
 -- Testing limit of CUBE_MAX_DIM dimensions check in cube_in.
 --
-
+-- create too big cube from literal
 select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)'::cube;
 select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)'::cube;
+-- from an array
+select cube(array(SELECT 0 as a FROM generate_series(1,101)));
+select cube(array(SELECT 0 as a FROM generate_series(1,101)),array(SELECT 0 as a FROM generate_series(1,101)));
+
+-- extend cube beyond limit
+-- this should work
+select cube(array(SELECT 0 as a FROM generate_series(1,100)));
+select cube(array(SELECT 0 as a FROM generate_series(1,100)),array(SELECT 0 as a FROM generate_series(1,100)));
+-- this should fail
+select cube(cube(array(SELECT 0 as a FROM generate_series(1,100))), 0);
+select cube(cube(array(SELECT 0 as a FROM generate_series(1,100)),array(SELECT 0 as a FROM generate_series(1,100))), 0, 0);
+
 
 --
 -- testing the  operators