Invocation: chase down insidious use-after-free problem
Just wanted to use a helper function to build a source-data node. However, the resulting node had a corrupted Node-ID spec. Investigation with the debugger showed that the ID was still valid while in construction and shows up corrupted after returning from the helper function. As it turned out, the reason is related to the de-duplication of ProcID data. While the de-duplicated strings themselves are ''not'' affected, the corruption happened by an intermediate instance of ProcID, which was inadvertently created and bound by-value to the builder-λ. The created Port then picks up a reference to this temporary, leading to the use-after-free of the string_view obejcts. Obviously, `ProcID` must not be instantiated other than through the static front-end `ProcID::describe`. Due to the private constructor, I can not make this object non-copyable (because then the hash-set would not be allowed to emplace it). But making it at least move-only will provoke a compiler error whenever binding to a lambda capture by value, which hopefully helps to pinpoint this insidious problem in the future...
This commit is contained in:
parent
5121bce156
commit
ccb10f3c65
6 changed files with 57 additions and 5 deletions
|
|
@ -667,7 +667,7 @@ namespace engine {
|
|||
return NodeBuilder ( static_cast<NodeBuilder<POL,DAT>&&> (*this) // slice away PortBulder subclass data
|
||||
, SizMark<sizeof(TurnoutWeaving)>{}
|
||||
,// prepare a builder-λ to construct the actual Turnout-object
|
||||
[procID = ProcID::describe(_Par::symbol_,portSpec,flags)
|
||||
[&procID = ProcID::describe(_Par::symbol_,portSpec,flags)
|
||||
,builder = move(blockBuilder_)
|
||||
,postProc = move(postProcessor_)
|
||||
,delegate = delegatePort_
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@
|
|||
#include "lib/error.hpp"
|
||||
#include "lib/hash-standard.hpp"
|
||||
#include "lib/several.hpp"
|
||||
#include "lib/nocopy.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include <string>
|
||||
|
|
@ -114,8 +115,12 @@ namespace engine {
|
|||
* @note must be essentially immutable; should ensure that implementation
|
||||
* never changes anything constituent for the \ref hash_value(),
|
||||
* due to de-duplication into a hashtable (see proc-node.cpp).
|
||||
* @warning be sure always to take a reference to the instance emplaced
|
||||
* into the `procRegistry` (see proc-node.cpp); inadvertently taking
|
||||
* a reference to some transient ProcID value leads to insidious errors!
|
||||
*/
|
||||
class ProcID
|
||||
: util::MoveOnly // ◁—— you must not create instances, use ProcID::describe()
|
||||
{
|
||||
StrView nodeName_;
|
||||
StrView portQual_;
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ namespace engine {
|
|||
"Node:%s Spec:%s"}
|
||||
% nodeSymb % portSpec
|
||||
};
|
||||
auto res = procRegistry.insert (ProcID{nodeSymb, portSpec.substr(0,p), portSpec.substr(p), extAttrib});
|
||||
auto res = procRegistry.emplace (ProcID{nodeSymb, portSpec.substr(0,p), portSpec.substr(p), extAttrib});
|
||||
ProcID& entry{unConst (*res.first)};
|
||||
if (res.second)
|
||||
{// new record placed into the registry
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ namespace engine {
|
|||
,types = move(outTypes.build())
|
||||
,prototype = move(prototype_)
|
||||
,resultIdx = resultSlot
|
||||
,procID = ProcID::describe (nodeSymb_,portSpec_)
|
||||
,&procID = ProcID::describe (nodeSymb_,portSpec_)
|
||||
]
|
||||
(PortDataBuilder& portData) mutable -> void
|
||||
{
|
||||
|
|
|
|||
|
|
@ -338,12 +338,16 @@ namespace test {
|
|||
makeSrcNode (ont::FraNo frameNr, ont::Flavr flavour)
|
||||
{
|
||||
auto spec = testRand().setupGenerator();
|
||||
SHOW_EXPR(spec.nodeID())
|
||||
return prepareNode(spec.nodeID())
|
||||
// ProcNode n{prepareNode(spec.nodeID())
|
||||
.preparePort()
|
||||
.invoke(spec.procID(), spec.makeFun())
|
||||
.setParam(frameNr,flavour)
|
||||
.completePort()
|
||||
.build();
|
||||
//SHOW_EXPR(watch(n).getNodeName() );
|
||||
// return move(n);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -386,6 +390,9 @@ namespace test {
|
|||
|
||||
// Build a node using this processing-functor...
|
||||
ProcNode nSrc = makeSrcNode (frameNr,flavour);
|
||||
SHOW_EXPR(watch(nSrc).getNodeName() );
|
||||
ProcID& px = ProcID::describe("Test:generate","(TestFrame)");
|
||||
SHOW_EXPR(px.genNodeName())
|
||||
ProcNode nFilt{prepareNode(spec.nodeID())
|
||||
.preparePort()
|
||||
.invoke(spec.procID(), procFun)
|
||||
|
|
|
|||
|
|
@ -105236,9 +105236,34 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1739116716548" ID="ID_348689410" MODIFIED="1739116790424" TEXT="brauche Test-Nodes">
|
||||
<arrowlink COLOR="#6e409a" DESTINATION="ID_525505656" ENDARROW="Default" ENDINCLINATION="-260;17;" ID="Arrow_ID_1565815419" STARTARROW="None" STARTINCLINATION="-71;-3;"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1739152096185" ID="ID_419285469" MODIFIED="1739152380070" TEXT="Problem mit korrumpierten Node-IDs">
|
||||
<arrowlink COLOR="#e00e57" DESTINATION="ID_93765980" ENDARROW="Default" ENDINCLINATION="-837;47;" ID="Arrow_ID_1352551175" STARTARROW="None" STARTINCLINATION="845;59;"/>
|
||||
<icon BUILTIN="broken-line"/>
|
||||
<node CREATED="1739152384977" ID="ID_815114496" MODIFIED="1739152402019" TEXT="wollte mir in einer Hilfsfunktion einer Source-Node generieren lassen"/>
|
||||
<node BACKGROUND_COLOR="#cfa193" COLOR="#690f14" CREATED="1739152403271" ID="ID_467549326" MODIFIED="1739152534007" TEXT="deren Node-IDs zeigen auf fregegebenen Speicher">
|
||||
<icon BUILTIN="clanbomber"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1739116294867" ID="ID_495521485" MODIFIED="1739116669840" TEXT="Node-Setup im NodeDevel_test dokumentieren">
|
||||
<arrowlink COLOR="#2c80c0" DESTINATION="ID_596205632" ENDARROW="Default" ENDINCLINATION="139;11;" ID="Arrow_ID_1998396288" STARTARROW="None" STARTINCLINATION="-765;-533;"/>
|
||||
<node COLOR="#ed2143" CREATED="1739152494531" HGAP="107" ID="ID_1336671386" MODIFIED="1739152700887" TEXT="�� Problem im Builder-λ" VSHIFT="-16">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Puh...
|
||||
</p>
|
||||
<p>
|
||||
...endlos mit dem Debugger beobachtet, sieht immer alles völlig sauber aus; konnte schließlich belegen daß es <i>nicht die de-duplzierten Strings selber </i>sind ⟹ das hat mich dann auf die richtige Fährte gebracht: es muß einer der dazwischen liegenden String-Views sein, der in transientem Speicher liegt — und tatsächlich: in den Builder-λ erzeugen wir eine Proc-ID <b>per Value</b>, binden sie dann aber per Referenz <b>in den neuen Port</b>....
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<font NAME="SansSerif" SIZE="10"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1739116294867" ID="ID_495521485" MODIFIED="1739137027196" TEXT="Node-Setup im NodeDevel_test dokumentieren">
|
||||
<arrowlink COLOR="#2c80c0" DESTINATION="ID_596205632" ENDARROW="Default" ENDINCLINATION="1567;83;" ID="Arrow_ID_1998396288" STARTARROW="None" STARTINCLINATION="-765;-533;"/>
|
||||
<icon BUILTIN="pencil"/>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -105821,6 +105846,21 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1730598512266" ID="ID_939010483" MODIFIED="1738695919297" TEXT="muß komplett von der Weaving-Pattern-Impl entkoppelt werden">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e5a988" COLOR="#890f62" CREATED="1739150638564" ID="ID_93765980" MODIFIED="1739152380070" TEXT="heimtückische Falle: transiente ProcID per Value">
|
||||
<linktarget COLOR="#e00e57" DESTINATION="ID_93765980" ENDARROW="Default" ENDINCLINATION="-837;47;" ID="Arrow_ID_1352551175" SOURCE="ID_419285469" STARTARROW="None" STARTINCLINATION="845;59;"/>
|
||||
<icon BUILTIN="clanbomber"/>
|
||||
<node CREATED="1739150662506" ID="ID_255473907" MODIFIED="1739150685582" TEXT="man muß immer auf die Instanz in der Registry referenzieren">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node CREATED="1739150687286" ID="ID_498143021" MODIFIED="1739150721902" TEXT="wenn man versehentlich irgendwo eine ProcID transient per Value konstruiert..."/>
|
||||
<node CREATED="1739150706579" ID="ID_53217299" MODIFIED="1739150728747" TEXT="kann es passieren, stattdessen auf diese zu referenzieren"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1739152148122" ID="ID_1081974707" MODIFIED="1739152172268" TEXT="besonders gefährlich: λ-capture">
|
||||
<icon BUILTIN="clanbomber"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#d1d2b3" COLOR="#435e98" CREATED="1739152175454" ID="ID_266108270" MODIFIED="1739152202663" TEXT="habe jetzt ProcID move-only gemacht">
|
||||
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1730598527660" ID="ID_114450698" MODIFIED="1730598535314" TEXT="Initialisierung per Konstruktor">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue