From d50babfc99f8bbc15e1eb24adb4279eb6fcbb9f6 Mon Sep 17 00:00:00 2001 From: andrey-golubev Date: Wed, 2 Oct 2019 20:54:11 +0300 Subject: [PATCH] G-API: fix perform substitution UB/crash --- .../gapi/src/compiler/passes/perform_substitution.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/modules/gapi/src/compiler/passes/perform_substitution.cpp b/modules/gapi/src/compiler/passes/perform_substitution.cpp index a1d9098102..d18cb21fcc 100644 --- a/modules/gapi/src/compiler/passes/perform_substitution.cpp +++ b/modules/gapi/src/compiler/passes/perform_substitution.cpp @@ -57,10 +57,19 @@ void performSubstitution(GModel::Graph& graph, const auto& patternDataNode = std::get<0>(it); const auto& substituteDataNode = std::get<1>(it); const auto& graphDataNode = patternToGraphMatch.outputDataNodes.at(patternDataNode); + // delete existing edges (otherwise we cannot redirect) - for (auto e : graphDataNode->inEdges()) { + auto existingEdges = graphDataNode->inEdges(); + // NB: we cannot iterate over node->inEdges() here directly because it gets modified when + // edges are erased. Erasing an edge supposes that src/dst nodes will remove + // (correspondingly) out/in edge (which is _our edge_). Now, this deleting means + // node->inEdges() will also get updated in the process: so, we'd iterate over a + // container which changes in this case. Using supplementary std::vector instead: + std::vector handles(existingEdges.begin(), existingEdges.end()); + for (const auto& e : handles) { graph.erase(e); } + GModel::redirectWriter(graph, substituteDataNode, graphDataNode); }