From 7335470b3a30b901da3f180f6bba89f28f4dbebe Mon Sep 17 00:00:00 2001 From: howsohazard <143410553+howsohazard@users.noreply.github.com> Date: Thu, 25 Jul 2024 13:20:02 -0400 Subject: [PATCH] 21035: Fixes potential crash when calling union, mix, or difference_entities opcodes (#197) --- src/Amalgam/entity/EntityManipulation.cpp | 7 +++---- .../evaluablenode/EvaluableNodeTreeManipulation.h | 2 ++ src/Amalgam/interpreter/InterpreterOpcodesCodeMixing.cpp | 9 +++------ .../interpreter/InterpreterOpcodesEntityAccess.cpp | 1 + 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/Amalgam/entity/EntityManipulation.cpp b/src/Amalgam/entity/EntityManipulation.cpp index ae0429eb..250f9ca6 100644 --- a/src/Amalgam/entity/EntityManipulation.cpp +++ b/src/Amalgam/entity/EntityManipulation.cpp @@ -357,13 +357,12 @@ EvaluableNodeReference EntityManipulation::DifferenceEntities(Interpreter *inter a_code = entity_from_a->second->GetRoot(enm); EvaluableNode *b_code = entity_to_create->GetRoot(enm); + EvaluableNode *entity_difference = EvaluableNodeTreeDifference::DifferenceTrees(enm, a_code, b_code); - //if either entity needs a cycle check, then everything will need to be checked for cycles later - if( (a_code != nullptr && a_code->GetNeedCycleCheck()) - || (b_code != nullptr && b_code->GetNeedCycleCheck()) ) + EvaluableNodeManager::UpdateFlagsForNodeTree(entity_difference); + if(entity_difference != nullptr && entity_difference->GetNeedCycleCheck()) cycle_free = false; - EvaluableNode *entity_difference = EvaluableNodeTreeDifference::DifferenceTrees(enm, a_code, b_code); call_lambda->AppendOrderedChildNode(entity_difference); EvaluableNode *call_assoc = enm->AllocNode(ENT_ASSOC); diff --git a/src/Amalgam/evaluablenode/EvaluableNodeTreeManipulation.h b/src/Amalgam/evaluablenode/EvaluableNodeTreeManipulation.h index 7a4cbaed..8a86eadc 100644 --- a/src/Amalgam/evaluablenode/EvaluableNodeTreeManipulation.h +++ b/src/Amalgam/evaluablenode/EvaluableNodeTreeManipulation.h @@ -501,10 +501,12 @@ class EvaluableNodeTreeManipulation //Returns a tree that consists of only nodes that are common across all of the trees specified, // where all returned values are newly allocated and modifiable + //Note that MergeTrees does not guarantee that EvaluableNodeFlags will be set appropriately static EvaluableNode *MergeTrees(NodesMergeMethod *mm, EvaluableNode *tree1, EvaluableNode *tree2); //Returns a tree that is a copy of tree but mutated based on mutation_rate // will create the new tree with interpreter's evaluableNodeManager and will use interpreter's RandomStream + //Note that MutateTree does not guarantee that EvaluableNodeFlags will be set appropriately static EvaluableNode *MutateTree(Interpreter *interpreter, EvaluableNodeManager *enm, EvaluableNode *tree, double mutation_rate, CompactHashMap *mutation_weights, CompactHashMap *evaluable_node_weights); //traverses tree and replaces any string that matches a key of to_replace with the value in to_replace diff --git a/src/Amalgam/interpreter/InterpreterOpcodesCodeMixing.cpp b/src/Amalgam/interpreter/InterpreterOpcodesCodeMixing.cpp index 98241585..60a1b57f 100644 --- a/src/Amalgam/interpreter/InterpreterOpcodesCodeMixing.cpp +++ b/src/Amalgam/interpreter/InterpreterOpcodesCodeMixing.cpp @@ -160,8 +160,7 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_INTERSECT(EvaluableNode *e EvaluableNode *result = EvaluableNodeTreeManipulation::IntersectTrees(evaluableNodeManager, n1, n2); - if(n1.GetNeedCycleCheck() || n2.GetNeedCycleCheck()) - EvaluableNodeManager::UpdateFlagsForNodeTree(result); + EvaluableNodeManager::UpdateFlagsForNodeTree(result); return EvaluableNodeReference(result, true); } @@ -180,8 +179,7 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_UNION(EvaluableNode *en, b EvaluableNode *result = EvaluableNodeTreeManipulation::UnionTrees(evaluableNodeManager, n1, n2); - if(n1.GetNeedCycleCheck() || n2.GetNeedCycleCheck()) - EvaluableNodeManager::UpdateFlagsForNodeTree(result); + EvaluableNodeManager::UpdateFlagsForNodeTree(result); return EvaluableNodeReference(result, true); } @@ -255,8 +253,7 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_MIX(EvaluableNode *en, boo EvaluableNode *result = EvaluableNodeTreeManipulation::MixTrees(randomStream.CreateOtherStreamViaRand(), evaluableNodeManager, n1, n2, blend1, blend2, similar_mix_chance); - if(n1.GetNeedCycleCheck() || n2.GetNeedCycleCheck()) - EvaluableNodeManager::UpdateFlagsForNodeTree(result); + EvaluableNodeManager::UpdateFlagsForNodeTree(result); return EvaluableNodeReference(result, true); } diff --git a/src/Amalgam/interpreter/InterpreterOpcodesEntityAccess.cpp b/src/Amalgam/interpreter/InterpreterOpcodesEntityAccess.cpp index ff799a4c..8ac1fbf9 100644 --- a/src/Amalgam/interpreter/InterpreterOpcodesEntityAccess.cpp +++ b/src/Amalgam/interpreter/InterpreterOpcodesEntityAccess.cpp @@ -146,6 +146,7 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_CONTAINED_ENTITIES_and_COM //if not a valid query, return nullptr if(conditionsBuffer.size() == 0) { + evaluableNodeManager->FreeNodeTreeIfPossible(entity_id_path); evaluableNodeManager->FreeNodeTreeIfPossible(query_params); return EvaluableNodeReference::Null(); }