mirror of https://gitee.com/bigwinds/arangodb
disallow subqueries in AQL traversal PRUNE conditions (#10231)
* disallow subqueries in AQL traversal PRUNE conditions * added derived file
This commit is contained in:
parent
7eb53e0645
commit
7fd3b3c390
|
@ -1,6 +1,11 @@
|
||||||
v3.5.2 (XXXX-XX-XX)
|
v3.5.2 (XXXX-XX-XX)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
* Disallow the usage of subqueries inside AQL traversal PRUNE conditions.
|
||||||
|
Using subqueries inside PRUNE conditions causes undefined behavior,
|
||||||
|
so such queries will now be aborted early on with a parse error
|
||||||
|
instead of running into undefined behavior.
|
||||||
|
|
||||||
* Fixed available flag for hotbackup.
|
* Fixed available flag for hotbackup.
|
||||||
|
|
||||||
* Fixed list with id for partially available hotbackups.
|
* Fixed list with id for partially available hotbackups.
|
||||||
|
|
|
@ -748,6 +748,23 @@ AstNode* Ast::createNodeReference(Variable const* variable) {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief create an AST subquery reference node
|
||||||
|
AstNode* Ast::createNodeSubqueryReference(std::string const& variableName) {
|
||||||
|
AstNode* node = createNode(NODE_TYPE_REFERENCE);
|
||||||
|
node->setFlag(AstNodeFlagType::FLAG_SUBQUERY_REFERENCE);
|
||||||
|
|
||||||
|
auto variable = _scopes.getVariable(variableName);
|
||||||
|
|
||||||
|
if (variable == nullptr) {
|
||||||
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
||||||
|
"variable not found in reference AstNode");
|
||||||
|
}
|
||||||
|
|
||||||
|
node->setData(variable);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief create an AST variable access
|
/// @brief create an AST variable access
|
||||||
AstNode* Ast::createNodeAccess(Variable const* variable,
|
AstNode* Ast::createNodeAccess(Variable const* variable,
|
||||||
std::vector<basics::AttributeName> const& field) {
|
std::vector<basics::AttributeName> const& field) {
|
||||||
|
|
|
@ -248,6 +248,9 @@ class Ast {
|
||||||
/// @brief create an AST reference node
|
/// @brief create an AST reference node
|
||||||
AstNode* createNodeReference(Variable const* variable);
|
AstNode* createNodeReference(Variable const* variable);
|
||||||
|
|
||||||
|
/// @brief create an AST subquery reference node
|
||||||
|
AstNode* createNodeSubqueryReference(std::string const& variableName);
|
||||||
|
|
||||||
/// @brief create an AST parameter node for a value literal
|
/// @brief create an AST parameter node for a value literal
|
||||||
AstNode* createNodeParameter(char const* name, size_t length);
|
AstNode* createNodeParameter(char const* name, size_t length);
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,7 @@ enum AstNodeFlagType : AstNodeFlagsType {
|
||||||
FLAG_BIND_PARAMETER = 0x0020000, // node was created from a bind parameter
|
FLAG_BIND_PARAMETER = 0x0020000, // node was created from a bind parameter
|
||||||
FLAG_FINALIZED = 0x0040000, // node has been finalized and should not be modified; only
|
FLAG_FINALIZED = 0x0040000, // node has been finalized and should not be modified; only
|
||||||
// set and checked in maintainer mode
|
// set and checked in maintainer mode
|
||||||
|
FLAG_SUBQUERY_REFERENCE = 0x0080000, // node references a subquery
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief enumeration of AST node value types
|
/// @brief enumeration of AST node value types
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -568,7 +568,6 @@ prune_and_options:
|
||||||
node->addMember($2);
|
node->addMember($2);
|
||||||
// Options
|
// Options
|
||||||
node->addMember($4);
|
node->addMember($4);
|
||||||
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -710,6 +709,15 @@ for_statement:
|
||||||
} prune_and_options {
|
} prune_and_options {
|
||||||
auto graphInfoNode = static_cast<AstNode*>(parser->popStack());
|
auto graphInfoNode = static_cast<AstNode*>(parser->popStack());
|
||||||
auto variablesNode = static_cast<AstNode*>(parser->popStack());
|
auto variablesNode = static_cast<AstNode*>(parser->popStack());
|
||||||
|
|
||||||
|
auto prune = graphInfoNode->getMember(3);
|
||||||
|
if (prune != nullptr) {
|
||||||
|
Ast::traverseReadOnly(prune, [&](AstNode const* node) {
|
||||||
|
if (node->type == NODE_TYPE_REFERENCE && node->hasFlag(AstNodeFlagType::FLAG_SUBQUERY_REFERENCE)) {
|
||||||
|
parser->registerParseError(TRI_ERROR_QUERY_PARSE, "prune condition must not use a subquery", yylloc.first_line, yylloc.first_column);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
auto node = parser->ast()->createNodeTraversal(variablesNode, graphInfoNode);
|
auto node = parser->ast()->createNodeTraversal(variablesNode, graphInfoNode);
|
||||||
parser->ast()->addOperation(node);
|
parser->ast()->addOperation(node);
|
||||||
}
|
}
|
||||||
|
@ -1487,7 +1495,7 @@ expression_or_query:
|
||||||
auto subQuery = parser->ast()->createNodeLet(variableName.c_str(), variableName.size(), node, false);
|
auto subQuery = parser->ast()->createNodeLet(variableName.c_str(), variableName.size(), node, false);
|
||||||
parser->ast()->addOperation(subQuery);
|
parser->ast()->addOperation(subQuery);
|
||||||
|
|
||||||
$$ = parser->ast()->createNodeReference(variableName);
|
$$ = parser->ast()->createNodeSubqueryReference(variableName);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -2253,6 +2253,20 @@ function complexFilteringSuite() {
|
||||||
|
|
||||||
tearDownAll: cleanup,
|
tearDownAll: cleanup,
|
||||||
|
|
||||||
|
testPruneWithSubquery: function () {
|
||||||
|
let query = `FOR v,e,p IN 1..100 OUTBOUND @start @ecol PRUNE 2 <= LENGTH(FOR w IN p.vertices FILTER w._id == v._id RETURN 1) RETURN p`;
|
||||||
|
try {
|
||||||
|
let bindVars = {
|
||||||
|
'@eCol': en,
|
||||||
|
'start': vertex.Tri1
|
||||||
|
};
|
||||||
|
db._query(query, bindVars);
|
||||||
|
fail();
|
||||||
|
} catch (err) {
|
||||||
|
assertEqual(err.errorNum, errors.ERROR_QUERY_PARSE.code);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
testVertexEarlyPruneHighDepth: function () {
|
testVertexEarlyPruneHighDepth: function () {
|
||||||
var query = `WITH ${vn}
|
var query = `WITH ${vn}
|
||||||
FOR v, e, p IN 100 OUTBOUND @start @@eCol
|
FOR v, e, p IN 100 OUTBOUND @start @@eCol
|
||||||
|
|
Loading…
Reference in New Issue