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)
|
||||
-------------------
|
||||
|
||||
* 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 list with id for partially available hotbackups.
|
||||
|
|
|
@ -748,6 +748,23 @@ AstNode* Ast::createNodeReference(Variable const* variable) {
|
|||
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
|
||||
AstNode* Ast::createNodeAccess(Variable const* variable,
|
||||
std::vector<basics::AttributeName> const& field) {
|
||||
|
|
|
@ -248,6 +248,9 @@ class Ast {
|
|||
/// @brief create an AST reference node
|
||||
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
|
||||
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_FINALIZED = 0x0040000, // node has been finalized and should not be modified; only
|
||||
// set and checked in maintainer mode
|
||||
FLAG_SUBQUERY_REFERENCE = 0x0080000, // node references a subquery
|
||||
};
|
||||
|
||||
/// @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);
|
||||
// Options
|
||||
node->addMember($4);
|
||||
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -710,6 +709,15 @@ for_statement:
|
|||
} prune_and_options {
|
||||
auto graphInfoNode = 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);
|
||||
parser->ast()->addOperation(node);
|
||||
}
|
||||
|
@ -1487,7 +1495,7 @@ expression_or_query:
|
|||
auto subQuery = parser->ast()->createNodeLet(variableName.c_str(), variableName.size(), node, false);
|
||||
parser->ast()->addOperation(subQuery);
|
||||
|
||||
$$ = parser->ast()->createNodeReference(variableName);
|
||||
$$ = parser->ast()->createNodeSubqueryReference(variableName);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
@ -2253,6 +2253,20 @@ function complexFilteringSuite() {
|
|||
|
||||
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 () {
|
||||
var query = `WITH ${vn}
|
||||
FOR v, e, p IN 100 OUTBOUND @start @@eCol
|
||||
|
|
Loading…
Reference in New Issue