8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 22:03:03 +01:00

Backport fix for CORE-5719 - FB >= 3 crashes when restoring backup made by FB 2.5.

This commit is contained in:
Adriano dos Santos Fernandes 2018-01-29 12:16:31 -02:00
parent 12da171484
commit a496ff57f2

View File

@ -11440,7 +11440,7 @@ ValueExprNode* UdfCallNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
dsc desc = node->dsqlFunction->udf_arguments[pos];
// UNICODE_FSS_HACK
if ((pos < node->dsqlFunction->udf_fld_system_arguments.getCount()) &&
if ((pos < node->dsqlFunction->udf_fld_system_arguments.getCount()) &&
node->dsqlFunction->udf_fld_system_arguments[pos])
{
DataTypeUtilBase::adjustSysFieldLength(&desc);
@ -11489,37 +11489,74 @@ DmlNode* ValueIfNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
MissingBoolNode* missing = node->condition->as<MissingBoolNode>();
if (missing)
{
StmtExprNode* missingCond = missing->arg->as<StmtExprNode>();
if (!missingCond)
StmtExprNode* stmtExpr = missing->arg->as<StmtExprNode>();
if (!stmtExpr)
return node;
CompoundStmtNode* stmt = missingCond->stmt->as<CompoundStmtNode>();
DeclareVariableNode* declStmt = NULL;
bool firstAssign = true;
AssignmentNode* assignStmt;
Array<USHORT> nullVariables;
if (stmt)
do
{
if (stmt->statements.getCount() != 2 ||
!(declStmt = stmt->statements[0]->as<DeclareVariableNode>()) ||
!(assignStmt = stmt->statements[1]->as<AssignmentNode>()))
CompoundStmtNode* stmt = stmtExpr->stmt->as<CompoundStmtNode>();
VariableNode* var = NULL;
if (stmt)
{
DeclareVariableNode* declStmt;
if (stmt->statements.getCount() != 2 ||
!(declStmt = stmt->statements[0]->as<DeclareVariableNode>()) ||
!(assignStmt = stmt->statements[1]->as<AssignmentNode>()) ||
!(var = assignStmt->asgnTo->as<VariableNode>()) ||
var->varId != declStmt->varId)
{
return node;
}
}
else if (!(assignStmt = stmtExpr->stmt->as<AssignmentNode>()) ||
!(var = assignStmt->asgnTo->as<VariableNode>()))
{
return node;
}
}
else if (!(assignStmt = missingCond->stmt->as<AssignmentNode>()))
return node;
VariableNode* var = node->falseValue->as<VariableNode>();
VariableNode* var2 = assignStmt->asgnTo->as<VariableNode>();
nullVariables.add(var->varId);
if (!var || !var2 || var->varId != var2->varId || (declStmt && declStmt->varId != var->varId))
return node;
if (firstAssign)
{
firstAssign = false;
VariableNode* var2 = node->falseValue->as<VariableNode>();
if (!var2 || var->varId != var2->varId)
return node;
}
stmtExpr = assignStmt->asgnFrom->as<StmtExprNode>();
} while (stmtExpr);
CoalesceNode* coalesceNode = FB_NEW_POOL(pool) CoalesceNode(pool);
coalesceNode->args = FB_NEW_POOL(pool) ValueListNode(pool, 2);
coalesceNode->args->items[0] = assignStmt->asgnFrom;
coalesceNode->args->items[1] = node->trueValue;
// Variables known to be NULL may be removed from the coalesce. This is not only an optimization!
// If not removed, error will happen as they correspondents declare nodes were removed.
if (CoalesceNode* subCoalesceNode = node->trueValue->as<CoalesceNode>())
{
NestValueArray& childItems = subCoalesceNode->args->items;
for (int i = childItems.getCount() - 1; i >= 0; --i)
{
if (VariableNode* childVar = childItems[i]->as<VariableNode>())
{
if (nullVariables.exist(childVar->varId))
childItems.remove(i);
}
}
}
return coalesceNode;
}