Skip to content

Commit

Permalink
21047: Fixes crashes with self-referential nodes used in certain opco…
Browse files Browse the repository at this point in the history
…des. Also reclaims memory from intersect/union/mix operations. (#198)
  • Loading branch information
howsohazard authored Jul 25, 2024
1 parent 7335470 commit 280efff
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 25 deletions.
31 changes: 14 additions & 17 deletions src/Amalgam/evaluablenode/EvaluableNodeManagement.h
Original file line number Diff line number Diff line change
Expand Up @@ -394,27 +394,24 @@ class EvaluableNodeManager
//if candidate is not unique, then it allocates and returns a new node
inline EvaluableNodeReference ReuseOrAllocNode(EvaluableNodeReference candidate, EvaluableNodeType type)
{
if(candidate.unique && candidate != nullptr)
//if not cyclic, can attempt to free all child nodes
//if cyclic, don't try, in case a child node points back to candidate
if(candidate.unique && candidate != nullptr && !candidate->GetNeedCycleCheck())
{
//if not cyclic, can attempt to free all child nodes
//if cyclic, don't try, in case a child node points back to candidate
if(!candidate->GetNeedCycleCheck())
if(candidate->IsAssociativeArray())
{
if(candidate->IsAssociativeArray())
for(auto &[_, e] : candidate->GetMappedChildNodesReference())
{
for(auto &[_, e] : candidate->GetMappedChildNodesReference())
{
if(e != nullptr)
FreeNodeTreeRecurse(e);
}
if(e != nullptr)
FreeNodeTreeRecurse(e);
}
else if(!candidate->IsImmediate())
}
else if(!candidate->IsImmediate())
{
for(auto &e : candidate->GetOrderedChildNodesReference())
{
for(auto &e : candidate->GetOrderedChildNodesReference())
{
if(e != nullptr)
FreeNodeTreeRecurse(e);
}
if(e != nullptr)
FreeNodeTreeRecurse(e);
}
}

Expand Down Expand Up @@ -625,7 +622,7 @@ class EvaluableNodeManager
//attempts to free the node reference
__forceinline void FreeNodeIfPossible(EvaluableNodeReference &enr)
{
if(enr.unique && !enr.IsImmediateValue())
if(enr.unique && !enr.IsImmediateValue() && !enr->GetNeedCycleCheck())
FreeNode(enr);
}

Expand Down
22 changes: 14 additions & 8 deletions src/Amalgam/interpreter/InterpreterOpcodesCodeMixing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,13 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_INTERSECT(EvaluableNode *e
auto node_stack = CreateInterpreterNodeStackStateSaver(n1);

auto n2 = InterpretNodeForImmediateUse(ocn[1]);
node_stack.PushEvaluableNode(n2);

EvaluableNode *result = EvaluableNodeTreeManipulation::IntersectTrees(evaluableNodeManager, n1, n2);

EvaluableNodeManager::UpdateFlagsForNodeTree(result);

evaluableNodeManager->FreeNodeTreeIfPossible(n1);
evaluableNodeManager->FreeNodeTreeIfPossible(n2);

return EvaluableNodeReference(result, true);
}

Expand All @@ -175,11 +177,13 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_UNION(EvaluableNode *en, b
auto node_stack = CreateInterpreterNodeStackStateSaver(n1);

auto n2 = InterpretNodeForImmediateUse(ocn[1]);
node_stack.PushEvaluableNode(n2);

EvaluableNode *result = EvaluableNodeTreeManipulation::UnionTrees(evaluableNodeManager, n1, n2);

EvaluableNodeManager::UpdateFlagsForNodeTree(result);

evaluableNodeManager->FreeNodeTreeIfPossible(n1);
evaluableNodeManager->FreeNodeTreeIfPossible(n2);

return EvaluableNodeReference(result, true);
}

Expand All @@ -197,8 +201,8 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_DIFFERENCE(EvaluableNode *
node_stack.PushEvaluableNode(n2);

EvaluableNode *result = EvaluableNodeTreeDifference::DifferenceTrees(evaluableNodeManager, n1, n2);

EvaluableNodeManager::UpdateFlagsForNodeTree(result);

return EvaluableNodeReference(result, (n1.unique && n2.unique));
}

Expand Down Expand Up @@ -248,12 +252,14 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_MIX(EvaluableNode *en, boo
auto node_stack = CreateInterpreterNodeStackStateSaver(n1);

auto n2 = InterpretNodeForImmediateUse(ocn[1]);
node_stack.PushEvaluableNode(n2);

EvaluableNode *result = EvaluableNodeTreeManipulation::MixTrees(randomStream.CreateOtherStreamViaRand(),
evaluableNodeManager, n1, n2, blend1, blend2, similar_mix_chance);

EvaluableNodeManager::UpdateFlagsForNodeTree(result);

evaluableNodeManager->FreeNodeTreeIfPossible(n1);
evaluableNodeManager->FreeNodeTreeIfPossible(n2);

return EvaluableNodeReference(result, true);
}

Expand Down Expand Up @@ -298,8 +304,8 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_MIX_LABELS(EvaluableNode *
node_stack.PushEvaluableNode(n2);

EvaluableNode *result = EvaluableNodeTreeManipulation::MixTreesByCommonLabels(this, evaluableNodeManager, n1, n2, randomStream, blend1, blend2);

EvaluableNodeManager::UpdateFlagsForNodeTree(result);

return EvaluableNodeReference(result, (n1.unique && n2.unique));
}

Expand Down

0 comments on commit 280efff

Please sign in to comment.