Fix crash on call dictGet() with bad arguments.

This commit is contained in:
Vitaly Baranov 2021-07-02 14:20:41 +03:00
parent 523155a020
commit 8b4fabe60c
4 changed files with 33 additions and 20 deletions

View File

@ -11,6 +11,26 @@
namespace DB namespace DB
{ {
namespace
{
void replaceArgumentWithTableIdentifierIfNotAlias(ASTFunction & func, size_t argument_pos, const Aliases & aliases)
{
if (!func.arguments || (func.arguments->children.size() <= argument_pos))
return;
auto arg = func.arguments->children[argument_pos];
auto identifier = arg->as<ASTIdentifier>();
if (!identifier)
return;
if (aliases.contains(identifier->name()))
return;
auto table_identifier = identifier->createTable();
if (!table_identifier)
return;
func.arguments->children[argument_pos] = table_identifier;
}
}
bool MarkTableIdentifiersMatcher::needChildVisit(ASTPtr & node, const ASTPtr & child) bool MarkTableIdentifiersMatcher::needChildVisit(ASTPtr & node, const ASTPtr & child)
{ {
if (child->as<ASTSelectQuery>()) if (child->as<ASTSelectQuery>())
@ -23,37 +43,22 @@ bool MarkTableIdentifiersMatcher::needChildVisit(ASTPtr & node, const ASTPtr & c
void MarkTableIdentifiersMatcher::visit(ASTPtr & ast, Data & data) void MarkTableIdentifiersMatcher::visit(ASTPtr & ast, Data & data)
{ {
if (auto * node_func = ast->as<ASTFunction>()) if (auto * node_func = ast->as<ASTFunction>())
visit(*node_func, ast, data); visit(*node_func, data);
} }
void MarkTableIdentifiersMatcher::visit(const ASTFunction & func, ASTPtr & ptr, Data & data) void MarkTableIdentifiersMatcher::visit(ASTFunction & func, const Data & data)
{ {
/// `IN t` can be specified, where t is a table, which is equivalent to `IN (SELECT * FROM t)`. /// `IN t` can be specified, where t is a table, which is equivalent to `IN (SELECT * FROM t)`.
if (checkFunctionIsInOrGlobalInOperator(func)) if (checkFunctionIsInOrGlobalInOperator(func))
{ {
auto ast = func.arguments->children.at(1); replaceArgumentWithTableIdentifierIfNotAlias(func, 1, data.aliases);
auto opt_name = tryGetIdentifierName(ast);
if (opt_name && !data.aliases.count(*opt_name) && ast->as<ASTIdentifier>())
{
ptr->as<ASTFunction>()->arguments->children[1] = ast->as<ASTIdentifier>()->createTable();
assert(ptr->as<ASTFunction>()->arguments->children[1]);
}
} }
// First argument of joinGet can be a table name, perhaps with a database. // First argument of joinGet can be a table name, perhaps with a database.
// First argument of dictGet can be a dictionary name, perhaps with a database. // First argument of dictGet can be a dictionary name, perhaps with a database.
else if (functionIsJoinGet(func.name) || functionIsDictGet(func.name)) else if (functionIsJoinGet(func.name) || functionIsDictGet(func.name))
{ {
if (!func.arguments || func.arguments->children.empty()) replaceArgumentWithTableIdentifierIfNotAlias(func, 0, data.aliases);
return;
auto ast = func.arguments->children.at(0);
auto opt_name = tryGetIdentifierName(ast);
if (opt_name && !data.aliases.count(*opt_name) && ast->as<ASTIdentifier>())
{
ptr->as<ASTFunction>()->arguments->children[0] = ast->as<ASTIdentifier>()->createTable();
assert(ptr->as<ASTFunction>()->arguments->children[0]);
}
} }
} }

View File

@ -24,7 +24,7 @@ public:
static void visit(ASTPtr & ast, Data & data); static void visit(ASTPtr & ast, Data & data);
private: private:
static void visit(const ASTFunction & func, ASTPtr &, Data &); static void visit(ASTFunction & func, const Data & data);
}; };
using MarkTableIdentifiersVisitor = MarkTableIdentifiersMatcher::Visitor; using MarkTableIdentifiersVisitor = MarkTableIdentifiersMatcher::Visitor;

View File

@ -0,0 +1,7 @@
SELECT dictGet(t.nest.a, concat(currentDatabase(), '.dict.dict'), 's', number) FROM numbers(5); -- { serverError 47 }
SELECT dictGetFloat64(t.b.s, 'database_for_dict.dict1', dictGetFloat64('Ta\0', toUInt64('databas\0_for_dict.dict1databas\0_for_dict.dict1', dictGetFloat64('', '', toUInt64(1048577), toDate(NULL)), NULL), toDate(dictGetFloat64(257, 'database_for_dict.dict1database_for_dict.dict1', '', toUInt64(NULL), 2, toDate(NULL)), '2019-05-2\0')), NULL, toUInt64(dictGetFloat64('', '', toUInt64(-9223372036854775808), toDate(NULL)), NULL)); -- { serverError 47 }
SELECT NULL AND (2147483648 AND NULL) AND -2147483647, toUUID(((1048576 AND NULL) AND (2147483647 AND 257 AND NULL AND -2147483649) AND NULL) IN (test_01103.t1_distr.id), '00000000-e1fe-11e\0-bb8f\0853d60c00749'), stringToH3('89184926cc3ffff89184926cc3ffff89184926cc3ffff89184926cc3ffff89184926cc3ffff89184926cc3ffff89184926cc3ffff89184926cc3ffff'); -- { serverError 47 }
SELECT 'still alive';