From 38c12f21e9ac68c250f44fe3206da2ffc6dc94b4 Mon Sep 17 00:00:00 2001 From: Pranav C Date: Tue, 9 May 2023 00:13:44 +0530 Subject: [PATCH] feat: sanitise DataType Signed-off-by: Pranav C --- .../src/db/sql-client/lib/KnexClient.ts | 8 ++++++++ .../db/sql-client/lib/mssql/MssqlClient.ts | 20 +++++++++++++++---- .../db/sql-client/lib/mysql/MysqlClient.ts | 6 +++--- .../src/db/sql-client/lib/pg/PgClient.ts | 20 +++++++++++++++---- .../lib/snowflake/SnowflakeClient.ts | 20 +++++++++++++++---- .../db/sql-client/lib/sqlite/SqliteClient.ts | 20 +++++++++++++++---- 6 files changed, 75 insertions(+), 19 deletions(-) diff --git a/packages/nocodb/src/db/sql-client/lib/KnexClient.ts b/packages/nocodb/src/db/sql-client/lib/KnexClient.ts index 9e412ee4c7..e701b15288 100644 --- a/packages/nocodb/src/db/sql-client/lib/KnexClient.ts +++ b/packages/nocodb/src/db/sql-client/lib/KnexClient.ts @@ -2967,6 +2967,14 @@ class KnexClient extends SqlClient { return str.replace(/\\[?]/g, '?'); } + sanitiseDataType(dt: string) { + // allow only alphanumeric and space + // eg: varchar, int, bigint, text, character varying, etc + if (/^[\w ]+$/.test(dt)) return dt; + + throw new Error(`Invalid data type: ${dt}`); + } + // todo: add support to complex default values with functions and expressions sanitiseDefaultValue(value: string | number | boolean) { if (value === null || value === undefined) return undefined; diff --git a/packages/nocodb/src/db/sql-client/lib/mssql/MssqlClient.ts b/packages/nocodb/src/db/sql-client/lib/mssql/MssqlClient.ts index 7a90360179..9df83f88f2 100644 --- a/packages/nocodb/src/db/sql-client/lib/mssql/MssqlClient.ts +++ b/packages/nocodb/src/db/sql-client/lib/mssql/MssqlClient.ts @@ -2586,7 +2586,11 @@ class MssqlClient extends KnexClient { if (change === 0) { query = existingQuery ? ',' : ''; - query += this.genQuery(`?? ${n.dt}`, [n.cn], shouldSanitize); + query += this.genQuery( + `?? ${this.sanitiseDataType(n.dt)}`, + [n.cn], + shouldSanitize, + ); query += scaleAndPrecision; query += n.rqd ? ' NOT NULL' : ' NULL'; query += n.ai ? ' IDENTITY(1,1)' : ' '; @@ -2601,7 +2605,11 @@ class MssqlClient extends KnexClient { n.default_constraint_name = `DF_${t}_${n.cn}`; } } else if (change === 1) { - query += this.genQuery(` ADD ?? ${n.dt}`, [n.cn], shouldSanitize); + query += this.genQuery( + ` ADD ?? ${this.sanitiseDataType(n.dt)}`, + [n.cn], + shouldSanitize, + ); query += scaleAndPrecision; query += n.rqd ? ' NOT NULL' : ' NULL'; query += n.ai ? ' IDENTITY(1,1)' : ' '; @@ -2639,7 +2647,9 @@ class MssqlClient extends KnexClient { n.rqd !== o.rqd ) { query += this.genQuery( - `\nALTER TABLE ?? ALTER COLUMN ?? ${n.dt}${scaleAndPrecision}`, + `\nALTER TABLE ?? ALTER COLUMN ?? ${this.sanitiseDataType( + n.dt, + )}${scaleAndPrecision}`, [this.getTnPath(t), n.cn], shouldSanitize, ); @@ -2655,7 +2665,9 @@ class MssqlClient extends KnexClient { ); if (n.cdf) { query += this.genQuery( - `\nALTER TABLE ?? ADD CONSTRAINT ?? DEFAULT ${n.cdf} FOR ??;`, + `\nALTER TABLE ?? ADD CONSTRAINT ?? DEFAULT ${this.sanitiseDefaultValue( + n.cdf, + )} FOR ??;`, [this.getTnPath(t), `DF_${n.tn}_${n.cn}`, n.cn], shouldSanitize, ); diff --git a/packages/nocodb/src/db/sql-client/lib/mysql/MysqlClient.ts b/packages/nocodb/src/db/sql-client/lib/mysql/MysqlClient.ts index 36b97ddaf6..2208e3c9d9 100644 --- a/packages/nocodb/src/db/sql-client/lib/mysql/MysqlClient.ts +++ b/packages/nocodb/src/db/sql-client/lib/mysql/MysqlClient.ts @@ -2463,18 +2463,18 @@ class MysqlClient extends KnexClient { query += this.genQuery( ` CHANGE - COLUMN ?? ?? ${n.dt}`, + COLUMN ?? ?? ${this.sanitiseDataType(n.dt)}`, [o.cn, n.cn], ); } else if (change === 1) { query += this.genQuery( ` ADD - COLUMN ?? ${n.dt}`, + COLUMN ?? ${this.sanitiseDataType(n.dt)}`, [n.cn], ); } else { - query += this.genQuery(` ?? ${n.dt}`, [n.cn]); + query += this.genQuery(` ?? ${this.sanitiseDataType(n.dt)}`, [n.cn]); } if (!n.dt.endsWith('text')) { query += n.dtxp && n.dtxp !== ' ' ? `(${n.dtxp}` : ''; diff --git a/packages/nocodb/src/db/sql-client/lib/pg/PgClient.ts b/packages/nocodb/src/db/sql-client/lib/pg/PgClient.ts index 7553435f65..06db320e25 100644 --- a/packages/nocodb/src/db/sql-client/lib/pg/PgClient.ts +++ b/packages/nocodb/src/db/sql-client/lib/pg/PgClient.ts @@ -2699,12 +2699,20 @@ class PGClient extends KnexClient { query += this.genQuery(` ?? serial`, [n.cn], shouldSanitize); } } else { - query += this.genQuery(` ?? ${n.dt}`, [n.cn], shouldSanitize); + query += this.genQuery( + ` ?? ${this.sanitiseDataType(n.dt)}`, + [n.cn], + shouldSanitize, + ); query += n.rqd ? ' NOT NULL' : ' NULL'; query += defaultValue ? ` DEFAULT ${defaultValue}` : ''; } } else if (change === 1) { - query += this.genQuery(` ADD ?? ${n.dt}`, [n.cn], shouldSanitize); + query += this.genQuery( + ` ADD ?? ${this.sanitiseDataType(n.dt)}`, + [n.cn], + shouldSanitize, + ); query += n.rqd ? ' NOT NULL' : ' NULL'; query += defaultValue ? ` DEFAULT ${defaultValue}` : ''; query = this.genQuery(`ALTER TABLE ?? ${query};`, [t], shouldSanitize); @@ -2719,7 +2727,9 @@ class PGClient extends KnexClient { if (n.dt !== o.dt) { query += this.genQuery( - `\nALTER TABLE ?? ALTER COLUMN ?? TYPE ${n.dt} USING ??::${n.dt};\n`, + `\nALTER TABLE ?? ALTER COLUMN ?? TYPE ${this.sanitiseDataType( + n.dt, + )} USING ??::${this.sanitiseDataType(n.dt)};\n`, [t, n.cn, n.cn], shouldSanitize, ); @@ -2740,7 +2750,9 @@ class PGClient extends KnexClient { [t, n.cn], shouldSanitize, ); - query += n.cdf ? ` SET DEFAULT ${n.cdf};\n` : ` DROP DEFAULT;\n`; + query += n.cdf + ? ` SET DEFAULT ${this.sanitiseDefaultValue(n.cdf)};\n` + : ` DROP DEFAULT;\n`; } } return query; diff --git a/packages/nocodb/src/db/sql-client/lib/snowflake/SnowflakeClient.ts b/packages/nocodb/src/db/sql-client/lib/snowflake/SnowflakeClient.ts index a976723543..167b7954c8 100644 --- a/packages/nocodb/src/db/sql-client/lib/snowflake/SnowflakeClient.ts +++ b/packages/nocodb/src/db/sql-client/lib/snowflake/SnowflakeClient.ts @@ -2486,13 +2486,21 @@ class SnowflakeClient extends KnexClient { shouldSanitize, ); } else { - query += this.genQuery(` ?? ${n.dt}`, [n.cn], shouldSanitize); + query += this.genQuery( + ` ?? ${this.sanitiseDataType(n.dt)}`, + [n.cn], + shouldSanitize, + ); query += n.dtxp && n.dt !== 'text' ? `(${n.dtxp})` : ''; query += n.rqd ? ' NOT NULL' : ' NULL'; query += defaultValue ? ` DEFAULT ${defaultValue}` : ''; } } else if (change === 1) { - query += this.genQuery(` ADD ?? ${n.dt}`, [n.cn], shouldSanitize); + query += this.genQuery( + ` ADD ?? ${this.sanitiseDataType(n.dt)}`, + [n.cn], + shouldSanitize, + ); query += n.dtxp && n.dt !== 'text' ? `(${n.dtxp})` : ''; query += n.rqd ? ' NOT NULL' : ' NULL'; query += defaultValue ? ` DEFAULT ${defaultValue}` : ''; @@ -2512,7 +2520,9 @@ class SnowflakeClient extends KnexClient { if (n.dt !== o.dt) { query += this.genQuery( - `\nALTER TABLE ?? ALTER COLUMN ?? SET DATA TYPE ${n.dt}`, + `\nALTER TABLE ?? ALTER COLUMN ?? SET DATA TYPE ${this.sanitiseDataType( + n.dt, + )}`, [this.getTnPath(t), n.cn], shouldSanitize, ); @@ -2534,7 +2544,9 @@ class SnowflakeClient extends KnexClient { [this.getTnPath(t), n.cn], shouldSanitize, ); - query += n.cdf ? ` SET DEFAULT ${this.sanitiseDefaultValue(n.cdf)};\n` : ` DROP DEFAULT;\n`; + query += n.cdf + ? ` SET DEFAULT ${this.sanitiseDefaultValue(n.cdf)};\n` + : ` DROP DEFAULT;\n`; } } return query; diff --git a/packages/nocodb/src/db/sql-client/lib/sqlite/SqliteClient.ts b/packages/nocodb/src/db/sql-client/lib/sqlite/SqliteClient.ts index f4abc46c66..07e2e5ff72 100644 --- a/packages/nocodb/src/db/sql-client/lib/sqlite/SqliteClient.ts +++ b/packages/nocodb/src/db/sql-client/lib/sqlite/SqliteClient.ts @@ -2013,7 +2013,7 @@ class SqliteClient extends KnexClient { let addNewColumnQuery = ''; addNewColumnQuery += this.genQuery( - ` ADD ?? ${n.dt}`, + ` ADD ?? ${this.sanitiseDataType(n.dt)}`, [n.cn], shouldSanitize, ); @@ -2045,15 +2045,27 @@ class SqliteClient extends KnexClient { query = `${backupOldColumnQuery}${addNewColumnQuery}${updateNewColumnQuery}${dropOldColumnQuery}`; } else if (change === 0) { query = existingQuery ? ',' : ''; - query += this.genQuery(`?? ${n.dt}`, [n.cn], shouldSanitize); + query += this.genQuery( + `?? ${this.sanitiseDataType(n.dt)}`, + [n.cn], + shouldSanitize, + ); query += n.dtxp && n.dt !== 'text' ? `(${n.dtxp})` : ''; query += n.cdf ? ` DEFAULT ${this.sanitiseDefaultValue(n.cdf)}` : ' '; query += n.rqd ? ` NOT NULL` : ' '; } else if (change === 1) { shouldSanitize = true; - query += this.genQuery(` ADD ?? ${n.dt}`, [n.cn], shouldSanitize); + query += this.genQuery( + ` ADD ?? ${this.sanitiseDataType(n.dt)}`, + [n.cn], + shouldSanitize, + ); query += n.dtxp && n.dt !== 'text' ? `(${n.dtxp})` : ''; - query += n.cdf ? ` DEFAULT ${this.sanitiseDefaultValue(n.cdf)}` : !n.rqd ? ' ' : ` DEFAULT ''`; + query += n.cdf + ? ` DEFAULT ${this.sanitiseDefaultValue(n.cdf)}` + : !n.rqd + ? ' ' + : ` DEFAULT ''`; query += n.rqd ? ` NOT NULL` : ' '; query = this.genQuery(`ALTER TABLE ?? ${query};`, [t], shouldSanitize); } else {