Check inclusion inside user_files

This commit is contained in:
kssenii 2021-07-13 12:38:37 +00:00
parent 48ffd3b81d
commit f86817d57c
6 changed files with 80 additions and 63 deletions

View File

@ -40,6 +40,12 @@ DatabaseSQLite::DatabaseSQLite(
if (err)
throw Exception(ErrorCodes::PATH_ACCESS_DENIED, "SQLite database path '{}' is invalid. Error: {}", database_path_, err.message());
String user_files_path = fs::canonical(context_->getUserFilesPath());
if (!canonical_path.starts_with(user_files_path))
throw Exception(ErrorCodes::PATH_ACCESS_DENIED,
"SQLite database file path '{}' must be inside 'user_files' directory: {}",
database_path_, user_files_path);
sqlite3 * tmp_sqlite_db = nullptr;
int status = sqlite3_open(canonical_path.c_str(), &tmp_sqlite_db);

View File

@ -161,11 +161,17 @@ void registerStorageSQLite(StorageFactory & factory)
const auto table_name = engine_args[1]->as<ASTLiteral &>().value.safeGet<String>();
std::error_code err;
auto canonical_path = fs::canonical(database_path, err);
String canonical_path = fs::canonical(database_path, err);
/// The path existance is also checked here.
if (err)
throw Exception(ErrorCodes::PATH_ACCESS_DENIED, "SQLite database path '{}' is invalid. Error: {}", database_path, err.message());
String user_files_path = fs::canonical(args.getContext()->getUserFilesPath());
if (!canonical_path.starts_with(user_files_path))
throw Exception(ErrorCodes::PATH_ACCESS_DENIED,
"SQLite database file path '{}' must be inside 'user_files' directory: {}",
database_path, user_files_path);
sqlite3 * tmp_sqlite_db = nullptr;
int status = sqlite3_open(canonical_path.c_str(), &tmp_sqlite_db);
if (status != SQLITE_OK)

View File

@ -9,6 +9,8 @@
#include "registerTableFunctions.h"
#include <Interpreters/evaluateConstantExpression.h>
#include <Interpreters/Context.h>
#include <Parsers/ASTFunction.h>
#include <Parsers/ASTLiteral.h>
@ -83,12 +85,16 @@ void TableFunctionSQLite::parseArguments(const ASTPtr & ast_function, ContextPtr
if (err)
throw Exception(ErrorCodes::PATH_ACCESS_DENIED, "SQLite database path '{}' is invalid. Error: {}", database_path, err.message());
String user_files_path = fs::canonical(context->getUserFilesPath());
if (!canonical_path.starts_with(user_files_path))
throw Exception(ErrorCodes::PATH_ACCESS_DENIED, "SQLite database file path '{}' must be inside 'user_files' directory", database_path);
sqlite3 * tmp_sqlite_db = nullptr;
int status = sqlite3_open(canonical_path.c_str(), &tmp_sqlite_db);
if (status != SQLITE_OK)
throw Exception(ErrorCodes::SQLITE_ENGINE_ERROR,
"Failed to open sqlite database. Status: {}. Message: {}",
status, sqlite3_errstr(status));
throw Exception(ErrorCodes::PATH_ACCESS_DENIED,
"SQLite database file path '{}' must be inside 'user_files' directory: {}",
database_path, user_files_path);
sqlite_db = std::shared_ptr<sqlite3>(tmp_sqlite_db, sqlite3_close);
}

View File

@ -3,14 +3,16 @@ show database tables:
table1
table2
table3
table4
table5
show creare table:
CREATE TABLE SQLite.table1\n(\n `col1` Nullable(String),\n `col2` Nullable(Int16)\n)\nENGINE = SQLite
CREATE TABLE SQLite.table2\n(\n `col1` Nullable(Int32),\n `col2` Nullable(String)\n)\nENGINE = SQLite
describe table:
col1 Nullable(String)
col2 Nullable(Int16)
col1 Nullable(Int32)
col2 Nullable(String)
describe table:
CREATE TABLE SQLite.table1\n(\n `col1` Nullable(String),\n `col2` Nullable(Int16)\n)\nENGINE = SQLite
CREATE TABLE SQLite.table2\n(\n `col1` Nullable(Int32),\n `col2` Nullable(String)\n)\nENGINE = SQLite
select *:
line1 1
line2 2
@ -18,28 +20,19 @@ line3 3
1 text1
2 text2
3 text3
test NULLs:
\N 1
not a null 2
\N 3
4
detach
line1 1
line2 2
line3 3
1 text1
2 text2
3 text3
test types
CREATE TABLE SQLite.table4\n(\n `a` Nullable(Int32),\n `b` Nullable(Int32),\n `c` Nullable(Int8),\n `d` Nullable(Int16),\n `e` Nullable(Int32),\n `bigint` Nullable(String),\n `int2` Nullable(String),\n `int8` Nullable(String)\n)\nENGINE = SQLite
CREATE TABLE SQLite.table5\n(\n `a` Nullable(String),\n `b` Nullable(String),\n `c` Nullable(Float64),\n `d` Nullable(Float64),\n `e` Nullable(Float64),\n `f` Nullable(Float32)\n)\nENGINE = SQLite
create table engine with table3
CREATE TABLE default.sqlite_table3\n(\n `col1` String,\n `col2` Int32\n)\nENGINE = SQLite
1
not a null 2
3
4
test types
CREATE TABLE SQLite.table4\n(\n `a` Nullable(Int32),\n `b` Nullable(Int32),\n `c` Nullable(Int8),\n `d` Nullable(Int16),\n `e` Nullable(Int32),\n `bigint` Nullable(String),\n `int2` Nullable(String),\n `int8` Nullable(String)\n)\nENGINE = SQLite
CREATE TABLE SQLite.table5\n(\n `a` Nullable(String),\n `b` Nullable(String),\n `c` Nullable(Float64),\n `d` Nullable(Float64),\n `e` Nullable(Float64),\n `f` Nullable(Float32)\n)\nENGINE = SQLite
line6 6
7
test table function
line1 1
line2 2
line3 3
line4 4

View File

@ -4,71 +4,77 @@ CUR_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
# shellcheck source=../shell_config.sh
. "$CUR_DIR"/../shell_config.sh
DATA_FILE1=$CUR_DIR/data_sqlite/db1
DATA_FILE2=$CUR_DIR/db2
# See 01658_read_file_to_string_column.sh
user_files_path=$(clickhouse-client --query "select _path,_file from file('nonexist.txt', 'CSV', 'val1 char')" 2>&1 | grep Exception | awk '{gsub("/nonexist.txt","",$9); print $9}')
mkdir -p ${user_files_path}/
DB_PATH=${user_files_path}/db1
sqlite3 ${DB_PATH} 'DROP TABLE IF EXISTS table1'
sqlite3 ${DB_PATH} 'DROP TABLE IF EXISTS table2'
sqlite3 ${DB_PATH} 'DROP TABLE IF EXISTS table3'
sqlite3 ${DB_PATH} 'DROP TABLE IF EXISTS table4'
sqlite3 ${DB_PATH} 'DROP TABLE IF EXISTS table5'
sqlite3 ${DB_PATH} 'CREATE TABLE table1 (col1 text, col2 smallint);'
sqlite3 ${DB_PATH} 'CREATE TABLE table2 (col1 int, col2 text);'
sqlite3 ${DB_PATH} "INSERT INTO table1 VALUES ('line1', 1), ('line2', 2), ('line3', 3)"
sqlite3 ${DB_PATH} "INSERT INTO table2 VALUES (1, 'text1'), (2, 'text2'), (3, 'text3')"
sqlite3 ${DB_PATH} 'CREATE TABLE table3 (col1 text, col2 int);'
sqlite3 ${DB_PATH} 'INSERT INTO table3 VALUES (NULL, 1)'
sqlite3 ${DB_PATH} "INSERT INTO table3 VALUES ('not a null', 2)"
sqlite3 ${DB_PATH} 'INSERT INTO table3 VALUES (NULL, 3)'
sqlite3 ${DB_PATH} "INSERT INTO table3 VALUES ('', 4)"
sqlite3 ${DB_PATH} 'CREATE TABLE table4 (a int, b integer, c tinyint, d smallint, e mediumint, bigint, int2, int8)'
sqlite3 ${DB_PATH} 'CREATE TABLE table5 (a character(20), b varchar(10), c real, d double, e double precision, f float)'
${CLICKHOUSE_CLIENT} --query='DROP DATABASE IF EXISTS sqlite_database'
${CLICKHOUSE_CLIENT} --query="select 'create database engine'";
${CLICKHOUSE_CLIENT} --query="CREATE DATABASE sqlite_database ENGINE = SQLite('${DATA_FILE1}')"
${CLICKHOUSE_CLIENT} --query="CREATE DATABASE sqlite_database ENGINE = SQLite('${DB_PATH}')"
${CLICKHOUSE_CLIENT} --query="select 'show database tables:'";
${CLICKHOUSE_CLIENT} --query='SHOW TABLES FROM sqlite_database;'
${CLICKHOUSE_CLIENT} --query="select 'show creare table:'";
${CLICKHOUSE_CLIENT} --query='SHOW CREATE TABLE sqlite_database.table1;' | sed -r 's/(.*SQLite)(.*)/\1/'
${CLICKHOUSE_CLIENT} --query='SHOW CREATE TABLE sqlite_database.table2;' | sed -r 's/(.*SQLite)(.*)/\1/'
${CLICKHOUSE_CLIENT} --query="select 'describe table:'";
${CLICKHOUSE_CLIENT} --query='DESCRIBE TABLE sqlite_database.table1;'
${CLICKHOUSE_CLIENT} --query='DESCRIBE TABLE sqlite_database.table2;'
${CLICKHOUSE_CLIENT} --query="select 'describe table:'";
${CLICKHOUSE_CLIENT} --query='SHOW CREATE TABLE sqlite_database.table1;' | sed -r 's/(.*SQLite)(.*)/\1/'
${CLICKHOUSE_CLIENT} --query='SHOW CREATE TABLE sqlite_database.table2;' | sed -r 's/(.*SQLite)(.*)/\1/'
${CLICKHOUSE_CLIENT} --query="select 'select *:'";
${CLICKHOUSE_CLIENT} --query='SELECT * FROM sqlite_database.table1 ORDER BY col2'
${CLICKHOUSE_CLIENT} --query='SELECT * FROM sqlite_database.table2 ORDER BY col1;'
sqlite3 $CUR_DIR/db2 'DROP TABLE IF EXISTS table3'
sqlite3 $CUR_DIR/db2 'CREATE TABLE table3 (col1 text, col2 int)'
sqlite3 $CUR_DIR/db2 'INSERT INTO table3 VALUES (NULL, 1)'
sqlite3 $CUR_DIR/db2 "INSERT INTO table3 VALUES ('not a null', 2)"
sqlite3 $CUR_DIR/db2 'INSERT INTO table3 VALUES (NULL, 3)'
sqlite3 $CUR_DIR/db2 "INSERT INTO table3 VALUES ('', 4)"
${CLICKHOUSE_CLIENT} --query="select 'test types'";
${CLICKHOUSE_CLIENT} --query='SHOW CREATE TABLE sqlite_database.table4;' | sed -r 's/(.*SQLite)(.*)/\1/'
${CLICKHOUSE_CLIENT} --query='SHOW CREATE TABLE sqlite_database.table5;' | sed -r 's/(.*SQLite)(.*)/\1/'
${CLICKHOUSE_CLIENT} --query='DROP DATABASE IF EXISTS sqlite_database_2'
${CLICKHOUSE_CLIENT} --query="CREATE DATABASE sqlite_database_2 ENGINE = SQLite('${DATA_FILE2}')"
# Do not run these, bacuase requires permissions in ci for write access to the directory of the created file and chmod does not help.
# ${CLICKHOUSE_CLIENT} --query="INSERT INTO sqlite_database_2.table3 VALUES (NULL, 3);"
# ${CLICKHOUSE_CLIENT} --query="INSERT INTO sqlite_database_2.table3 VALUES (NULL, 4);"
# ${CLICKHOUSE_CLIENT} --query="INSERT INTO sqlite_database_2.table3 VALUES ('line5', 5);"
${CLICKHOUSE_CLIENT} --query="select 'test NULLs:'";
${CLICKHOUSE_CLIENT} --query='SELECT * FROM sqlite_database_2.table3 ORDER BY col2;'
${CLICKHOUSE_CLIENT} --query='DROP DATABASE IF EXISTS sqlite_database'
${CLICKHOUSE_CLIENT} --query="select 'detach'";
${CLICKHOUSE_CLIENT} --query='DETACH DATABASE sqlite_database;'
${CLICKHOUSE_CLIENT} --query='ATTACH DATABASE sqlite_database;'
${CLICKHOUSE_CLIENT} --query='SELECT * FROM sqlite_database.table1 ORDER BY col2'
${CLICKHOUSE_CLIENT} --query='SELECT * FROM sqlite_database.table2 ORDER BY col1;'
${CLICKHOUSE_CLIENT} --query='DROP DATABASE IF EXISTS sqlite_database;'
${CLICKHOUSE_CLIENT} --query="select 'create table engine with table3'";
${CLICKHOUSE_CLIENT} --query='DROP TABLE IF EXISTS sqlite_table3'
${CLICKHOUSE_CLIENT} --query="CREATE TABLE sqlite_table3 (col1 String, col2 Int32) ENGINE = SQLite('${DATA_FILE2}', 'table3')"
${CLICKHOUSE_CLIENT} --query="CREATE TABLE sqlite_table3 (col1 String, col2 Int32) ENGINE = SQLite('${DB_PATH}', 'table3')"
${CLICKHOUSE_CLIENT} --query='SHOW CREATE TABLE sqlite_table3;' | sed -r 's/(.*SQLite)(.*)/\1/'
# Do not run these, bacuase requires permissions in ci for write access to the directory of the created file and chmod does not help.
# ${CLICKHOUSE_CLIENT} --query="INSERT INTO sqlite_table3 VALUES ('line6', 6);"
# ${CLICKHOUSE_CLIENT} --query="INSERT INTO sqlite_table3 VALUES (NULL, 7);"
${CLICKHOUSE_CLIENT} --query="INSERT INTO sqlite_table3 VALUES ('line6', 6);"
${CLICKHOUSE_CLIENT} --query="INSERT INTO sqlite_table3 VALUES (NULL, 7);"
${CLICKHOUSE_CLIENT} --query='SELECT * FROM sqlite_table3 ORDER BY col2'
sqlite3 $CUR_DIR/db2 'DROP TABLE IF EXISTS table4'
sqlite3 $CUR_DIR/db2 'CREATE TABLE table4 (a int, b integer, c tinyint, d smallint, e mediumint, bigint, int2, int8)'
${CLICKHOUSE_CLIENT} --query="select 'test types'";
${CLICKHOUSE_CLIENT} --query='SHOW CREATE TABLE sqlite_database_2.table4;' | sed -r 's/(.*SQLite)(.*)/\1/'
sqlite3 $CUR_DIR/db2 'CREATE TABLE table5 (a character(20), b varchar(10), c real, d double, e double precision, f float)'
${CLICKHOUSE_CLIENT} --query='SHOW CREATE TABLE sqlite_database_2.table5;' | sed -r 's/(.*SQLite)(.*)/\1/'
${CLICKHOUSE_CLIENT} --query="select 'test table function'";
${CLICKHOUSE_CLIENT} --query="SELECT * FROM sqlite('${DATA_FILE1}', 'table1') ORDER BY col2"
${CLICKHOUSE_CLIENT} --query="INSERT INTO TABLE FUNCTION sqlite('${DB_PATH}', 'table1') SELECT 'line4', 4"
${CLICKHOUSE_CLIENT} --query="SELECT * FROM sqlite('${DB_PATH}', 'table1') ORDER BY col2"
rm ${DATA_FILE2}
rm -r ${DB_PATH}