elsa-core/test/integration/Elsa.Bpmn.Interchange.IntegrationTests/Assets/two-process-duplicate-id.bpmn
Sipke Schoorstra 933d1739bd
fix(bpmn): refuse documents with duplicate element ids before recursion (#8080)
* 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>
2026-09-12 11:26:07 -07:00

28 lines
1.3 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"
id="Definitions_two-process-duplicate-id"
targetNamespace="http://bpmn.io/schema/bpmn">
<!-- Two top-level processes declaring the same id ("shared"), which is invalid BPMN (ids must be unique within a
document): a top-level process's own id was never added to the pool checked for uniqueness (only its
elements were), so two processes sharing an id went undetected as long as their own elements did not repeat
any id. -->
<bpmn:process id="shared" name="First Process" isExecutable="true">
<bpmn:startEvent id="Start_1">
<bpmn:outgoing>Flow_1</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:endEvent id="End_1">
<bpmn:incoming>Flow_1</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_1" sourceRef="Start_1" targetRef="End_1" />
</bpmn:process>
<bpmn:process id="shared" name="Second Process" isExecutable="true">
<bpmn:startEvent id="Start_2">
<bpmn:outgoing>Flow_2</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:endEvent id="End_2">
<bpmn:incoming>Flow_2</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_2" sourceRef="Start_2" targetRef="End_2" />
</bpmn:process>
</bpmn:definitions>