mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 08:32:02 +00:00
Fix crash on call dictGet() with bad arguments.
This commit is contained in:
parent
523155a020
commit
8b4fabe60c
@ -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]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
still alive
|
@ -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';
|
Loading…
Reference in New Issue
Block a user