1
0
Fork 0

disallow subqueries in AQL traversal PRUNE conditions (#10231)

* disallow subqueries in AQL traversal PRUNE conditions

* added derived file
This commit is contained in:
Jan 2019-10-16 15:36:33 +02:00 committed by KVS85
parent 7eb53e0645
commit 7fd3b3c390
7 changed files with 651 additions and 595 deletions

View File

@ -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.

View File

@ -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) {

View File

@ -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);

View File

@ -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

View File

@ -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);
}
;

View File

@ -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