* fix(bpmn): refuse documents with duplicate element ids before recursion
A subProcess nested inside another subProcess with the same id made
EnsureCapabilitiesSatisfied, BpmnWorkBinder.BindScope and the interchange
library's own BpmnXmlWriter recurse without terminating, overflowing the
stack and killing the process (.NET cannot catch StackOverflowException).
Refuse such a document up front, coded bpmn.import.duplicate-element-id
(422), on POST bpmn/import and PUT bpmn/definitions/{id}/document, listing
the duplicated ids.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(bpmn): include process ids in the duplicate-id check
EnsureElementIdsUnique only pooled element ids, never a process
definition's own ProcessId. A top-level process's id is never one of
its own elements, so a subprocess reusing its parent's id (or two
top-level processes sharing an id) went undetected and still
overflowed the stack in EnsureCapabilitiesSatisfied, BpmnWorkBinder
and BpmnXmlWriter the same way a repeated element id does. Add every
top-level process's own id to the pool; a nested process definition's
own id needs no equivalent addition since it is always exactly the
element id that opens it, already counted once via its owner's
elements.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
48 lines
2.2 KiB
XML
48 lines
2.2 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"
|
|
xmlns:vw="https://bpmn.valenceworks.io/schema/bpmn"
|
|
id="Definitions_nested-subprocess-duplicate-id"
|
|
targetNamespace="http://bpmn.io/schema/bpmn">
|
|
<bpmn:process id="nested-subprocess-duplicate-id" name="Nested Subprocess Duplicate Id" isExecutable="true">
|
|
<bpmn:startEvent id="Start_1">
|
|
<bpmn:outgoing>Flow_1</bpmn:outgoing>
|
|
</bpmn:startEvent>
|
|
|
|
<!-- The outer subprocess and the subprocess nested directly inside it share the same id ("Outer"), which is
|
|
invalid BPMN (ids must be unique within a document) and, before elsa-core#8074's fix, overflowed the stack
|
|
of any code that finds a scope's nested processes by matching this id back out of the flat binding list. -->
|
|
<bpmn:subProcess id="Outer" name="Outer">
|
|
<bpmn:incoming>Flow_1</bpmn:incoming>
|
|
<bpmn:outgoing>Flow_2</bpmn:outgoing>
|
|
<bpmn:startEvent id="Outer_Start">
|
|
<bpmn:outgoing>Outer_Flow_1</bpmn:outgoing>
|
|
</bpmn:startEvent>
|
|
|
|
<bpmn:subProcess id="Outer" name="Inner reusing its parent's id">
|
|
<bpmn:incoming>Outer_Flow_1</bpmn:incoming>
|
|
<bpmn:outgoing>Outer_Flow_2</bpmn:outgoing>
|
|
<bpmn:startEvent id="Inner_Start">
|
|
<bpmn:outgoing>Inner_Flow_1</bpmn:outgoing>
|
|
</bpmn:startEvent>
|
|
<bpmn:endEvent id="Inner_End">
|
|
<bpmn:incoming>Inner_Flow_1</bpmn:incoming>
|
|
</bpmn:endEvent>
|
|
<bpmn:sequenceFlow id="Inner_Flow_1" sourceRef="Inner_Start" targetRef="Inner_End" />
|
|
</bpmn:subProcess>
|
|
|
|
<bpmn:endEvent id="Outer_End">
|
|
<bpmn:incoming>Outer_Flow_2</bpmn:incoming>
|
|
</bpmn:endEvent>
|
|
<bpmn:sequenceFlow id="Outer_Flow_1" sourceRef="Outer_Start" targetRef="Outer" />
|
|
<bpmn:sequenceFlow id="Outer_Flow_2" sourceRef="Outer" targetRef="Outer_End" />
|
|
</bpmn:subProcess>
|
|
|
|
<bpmn:endEvent id="End_1">
|
|
<bpmn:incoming>Flow_2</bpmn:incoming>
|
|
</bpmn:endEvent>
|
|
|
|
<bpmn:sequenceFlow id="Flow_1" sourceRef="Start_1" targetRef="Outer" />
|
|
<bpmn:sequenceFlow id="Flow_2" sourceRef="Outer" targetRef="End_1" />
|
|
</bpmn:process>
|
|
</bpmn:definitions>
|