From f9f73d2d62801022ecc198b72d366d96dd58523a Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Thu, 5 Jun 2014 15:00:57 +0200 Subject: [PATCH] Fix potential infinite loop in CDB_QueryStatements This fix was already present at one point in cartodb/lib/sql (where the code was copied from) but in a different branch than the one the code was initially copied from. The fix depends on plpython language which becomes a new dependency. --- NEWS | 5 ++++ README.md | 3 +- cartodb.control.in | 2 +- expected/test_setup.out | 1 + scripts-available/CDB_QueryStatements.sql | 17 +++++------ sql/test_setup.sql | 1 + test/CDB_QueryStatementsTest.sql | 35 +++++++++++++++++++++++ test/CDB_QueryStatementsTest_expect | 10 +++++++ 8 files changed, 64 insertions(+), 10 deletions(-) diff --git a/NEWS b/NEWS index 5ac9b9b..c4f469a 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ 0.2.0dev - 2014-MM-DD ------------------ +Important changes: + + - This release adds dependency on "plpythonu" extension + Bug fixes: - Fix recursive trigger on create table (#32) @@ -8,6 +12,7 @@ Bug fixes: - Fully qualify call to cdb_disable_ddl_hooks from cdb_enable_ddl_hooks - Fully qualify call to CDB_UserDataSize from quota trigger - Fix potential infinite loop in CDB_CartodbfyTable + - Fix potential infinite loop in CDB_QueryStatements Enhancements: diff --git a/README.md b/README.md index 5431fce..698f16e 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ See https://github.com/CartoDB/cartodb/wiki/CartoDB-PostgreSQL-extension Dependencies ------------ - * PostgreSQL 9.3+ + * PostgreSQL 9.3+ (with plpythonu extension) + * [PostGIS extension](http://postgis.net) * [Schema triggers extension] (https://bitbucket.org/malloclabs/pg_schema_triggers) (or [fork](https://github.com/CartoDB/pg_schema_triggers)) diff --git a/cartodb.control.in b/cartodb.control.in index 36fc0ee..3d783c7 100644 --- a/cartodb.control.in +++ b/cartodb.control.in @@ -3,4 +3,4 @@ comment = 'Turn a database into a cartodb user database.' superuser = true relocatable = false schema = cartodb -requires = 'schema_triggers, postgis' +requires = 'schema_triggers, postgis, plpythonu' diff --git a/expected/test_setup.out b/expected/test_setup.out index 1f4bf2a..c05769f 100644 --- a/expected/test_setup.out +++ b/expected/test_setup.out @@ -1,5 +1,6 @@ CREATE EXTENSION postgis; CREATE EXTENSION schema_triggers; +CREATE EXTENSION plpythonu; CREATE EXTENSION cartodb; CREATE FUNCTION public.cdb_invalidate_varnish(table_name text) RETURNS void AS $$ diff --git a/scripts-available/CDB_QueryStatements.sql b/scripts-available/CDB_QueryStatements.sql index 9c8309a..bb4d10c 100644 --- a/scripts-available/CDB_QueryStatements.sql +++ b/scripts-available/CDB_QueryStatements.sql @@ -1,13 +1,14 @@ -- Return an array of statements found in the given query text -- --- Curtesy of Hubert Lubaczewski (depesz) +-- Regexp curtesy of Hubert Lubaczewski (depesz) +-- Implemented in plpython for performance reasons -- CREATE OR REPLACE FUNCTION CDB_QueryStatements(query text) RETURNS SETOF TEXT AS $$ - SELECT stmt FROM ( - SELECT btrim(q[1], E' \n\t\r;') as stmt FROM ( - SELECT regexp_matches( $1, $REG$((?:[^'"$;]+|"[^"]*"|'(?:[^']*|'')*'|(\$[^$]*\$).*?\2)+)$REG$, 'g' ) as q - ) i - ) j - WHERE stmt <> ''; -$$ language sql IMMUTABLE STRICT; + import re + pat = re.compile( r'''((?:[^'"$;]+|"[^"]*"|'[^']*'|(\$[^$]*\$).*?\2)+)''', re.DOTALL ) + for match in pat.findall(query): + cleaned = match[0].strip() + if ( cleaned ): + yield cleaned +$$ language 'plpythonu' IMMUTABLE STRICT; diff --git a/sql/test_setup.sql b/sql/test_setup.sql index 1f4bf2a..c05769f 100644 --- a/sql/test_setup.sql +++ b/sql/test_setup.sql @@ -1,5 +1,6 @@ CREATE EXTENSION postgis; CREATE EXTENSION schema_triggers; +CREATE EXTENSION plpythonu; CREATE EXTENSION cartodb; CREATE FUNCTION public.cdb_invalidate_varnish(table_name text) RETURNS void AS $$ diff --git a/test/CDB_QueryStatementsTest.sql b/test/CDB_QueryStatementsTest.sql index c1c5424..7e8873c 100644 --- a/test/CDB_QueryStatementsTest.sql +++ b/test/CDB_QueryStatementsTest.sql @@ -26,3 +26,38 @@ INSER INTO "my''""t" values ('''','""'';;'); SELECT $qu;oted$ hi $qu;oted$; $the_param$) as statement ) SELECT '5', row_number() over (), statement FROM q; + +WITH q AS ( SELECT CDB_QueryStatements($the_param$ +SELECT +1 ; SELECT +2 +$the_param$) as statement ) +SELECT '6', row_number() over (), statement FROM q; + +-- This is an insane input, illegal sql +-- we are really only testing that it does not +-- take forever to process.. +-- The actual result is not correct, so if the function +-- ever gets fixed check if it's better +WITH q AS ( SELECT CDB_QueryStatements($the_param$ + + + + + + + + + /a + $b$ + $c$d + ; +$the_param$) as statement ) +SELECT '7', row_number() over (), statement FROM q; + + +WITH q AS ( SELECT CDB_QueryStatements($the_param$ +SELECT $quoted$ hi +$quoted$; +$the_param$) as statement ) +SELECT '8', row_number() over (), statement FROM q; diff --git a/test/CDB_QueryStatementsTest_expect b/test/CDB_QueryStatementsTest_expect index 9ed8fb1..7334d4b 100644 --- a/test/CDB_QueryStatementsTest_expect +++ b/test/CDB_QueryStatementsTest_expect @@ -7,3 +7,13 @@ 4|4|SELECT 5 5|1|INSER INTO "my''""t" values ('''','""'';;') 5|2|SELECT $qu;oted$ hi $qu;oted$ +6|1|SELECT +1 +6|2|SELECT +2 +7|1|/a +7|2|b +7|3|c +7|4|d +8|1|SELECT $quoted$ hi +$quoted$