From 5fed7b24aed50a50e2e922de2bcc51458a067210 Mon Sep 17 00:00:00 2001 From: Alexander Korotkov Date: Thu, 30 Aug 2018 14:18:53 +0300 Subject: [PATCH] Enforce cube dimension limit in all cube construction functions 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 | 34 +++++++++++++++++++++++++++++ contrib/cube/expected/cube.out | 40 ++++++++++++++++++++++++++++++++++ contrib/cube/sql/cube.sql | 20 ++++++++++++++++- 3 files changed, 93 insertions(+), 1 deletion(-) diff --git a/contrib/cube/cube.c b/contrib/cube/cube.c index d835fe1f87..8074caadb7 100644 --- a/contrib/cube/cube.c +++ b/contrib/cube/cube.c @@ -152,6 +152,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), @@ -209,6 +216,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); @@ -243,6 +256,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 = IS_POINT(c) ? POINT_SIZE(dim) : CUBE_SIZE(dim); result = (NDBOX *) palloc0(size); SET_VARSIZE(result, size); @@ -1752,6 +1772,13 @@ cube_c_f8(PG_FUNCTION_ARGS) int size; int i; + if (DIM(cube) + 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))); + if (IS_POINT(cube)) { size = POINT_SIZE((DIM(cube) + 1)); @@ -1793,6 +1820,13 @@ cube_c_f8_f8(PG_FUNCTION_ARGS) int size; int i; + if (DIM(cube) + 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))); + if (IS_POINT(cube) && (x1 == x2)) { size = POINT_SIZE((DIM(cube) + 1)); diff --git a/contrib/cube/expected/cube.out b/contrib/cube/expected/cube.out index 67ca1990ac..b5f278cfa3 100644 --- a/contrib/cube/expected/cube.out +++ b/contrib/cube/expected/cube.out @@ -381,6 +381,17 @@ SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[4,0]); ERROR: Index out of bounds SELECT cube_subset(cube('(6,7,8),(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. -- -- Test point processing -- @@ -453,6 +464,7 @@ SELECT cube(cube(1,2), 42, 24); -- cube_c_f8_f8 -- -- 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... @@ -463,6 +475,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 -- diff --git a/contrib/cube/sql/cube.sql b/contrib/cube/sql/cube.sql index 57805ad996..31d1f03c50 100644 --- a/contrib/cube/sql/cube.sql +++ b/contrib/cube/sql/cube.sql @@ -98,6 +98,12 @@ SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]); SELECT cube_subset(cube('(1,3,5),(1,3,5)'), ARRAY[3,2,1,1]); SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[4,0]); SELECT cube_subset(cube('(6,7,8),(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))); + + -- -- Test point processing @@ -117,9 +123,21 @@ SELECT cube(cube(1,2), 42, 24); -- cube_c_f8_f8 -- -- 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 -- 2.40.0