[med-svn] [Git][med-team/dcmtk][master] 2 commits: Revert "CVE-2026-10528-partial.patch: new: fix needed by orthanc."
Étienne Mollier (@emollier)
gitlab at salsa.debian.org
Thu Jun 4 21:15:12 BST 2026
Étienne Mollier pushed to branch master at Debian Med / dcmtk
Commits:
b760963c by Étienne Mollier at 2026-06-04T22:10:06+02:00
Revert "CVE-2026-10528-partial.patch: new: fix needed by orthanc."
The change is causing an ABI breakage that is going to require a
transition. It is more appropriate to wait for the 3.7.1 release and
coordinate the transition on a sane basis. In the meantime the change
is undone.
This reverts commit 5d6c0649ddf534d574f7c64245f13a9924400245.
- - - - -
213f23d8 by Étienne Mollier at 2026-06-04T22:14:10+02:00
d/changelog: ready for upload to unstable.
- - - - -
3 changed files:
- debian/changelog
- − debian/patches/CVE-2026-10528-partial.patch
- debian/patches/series
Changes:
=====================================
debian/changelog
=====================================
@@ -1,3 +1,14 @@
+dcmtk (3.7.0+really3.7.0-4) unstable; urgency=medium
+
+ * Team upload.
+ * Revert "CVE-2026-10528-partial.patch: new: fix needed by orthanc."
+ The change is causing an ABI breakage that is going to require a
+ transition. It is probably more appropriate to wait for the 3.7.1
+ release and coordinate the transition on a sane basis. In the
+ meantime the change is undone.
+
+ -- Étienne Mollier <emollier at debian.org> Thu, 04 Jun 2026 22:13:25 +0200
+
dcmtk (3.7.0+really3.7.0-3) unstable; urgency=medium
* Team upload.
=====================================
debian/patches/CVE-2026-10528-partial.patch deleted
=====================================
@@ -1,1358 +0,0 @@
-Description: Add sequence nesting depth limit for parsing
- Track sequence nesting depth on DcmInputStream during parsing. When the
- depth exceeds a configurable limit, parsing is aborted with
- EC_NestingDepthLimitExceeded. This prevents stack overflow from
- excessively nested DICOM sequences.
- .
- The default limit is controlled by the compile-time macro
- DCMTK_MAX_SEQUENCE_NESTING (default: 64). It can be overridden per parse
- operation via the runtime API:
- .
- - DcmInputStream::setMaxNestingDepth() for direct stream access
- - DcmItem::setMaxNestingDepth() (inherited by DcmDataset) for loadFile()
- and read()
- - DcmFileFormat::setMaxNestingDepth() for loadFile() and read(),
- forwarded to the contained dataset
- - DcmSCP::setMaxNestingDepth() and DcmSCU::setMaxNestingDepth() for
- datasets received over the network via receiveDIMSEDataset()
- .
- The runtime setter uses Sint32 semantics:
- 0 = compile-time default, -1 = unlimited, >0 = limit
- .
- Note: the specific EC_NestingDepthLimitExceeded error code is not yet
- surfaced through the DIMSE layer; DIMSE_receiveDataSetInMemory() maps
- all parse errors to DIMSE_RECEIVEFAILED.
- .
- Thanks to the IN-CYPHER OSS Security Team for the report, detailed
- analysis and proof of concept.
- .
- This closes DCMTK Bug #1191.
-Author: Michael Onken <onken at open-connections.de>
-Applied-Upstream: 885ff0f10372bd589b5f44cea974f28a3964cb0f
-Last-Update: 2026-04-11
-Bug: https://support.dcmtk.org/redmine/issues/1191
-Bug-Debian: https://bugs.debian.org/1138713
-Reviewed-By: Étienne Mollier <emollier at debian.org>
-
---- dcmtk.orig/config/docs/macros.txt
-+++ dcmtk/config/docs/macros.txt
-@@ -109,6 +109,21 @@
- dcmtk::log4cplus::threadCleanup() should be called by the user code in
- order to clean-up oflog's thread local storage.
-
-+DCMTK_MAX_SEQUENCE_NESTING
-+ Affected: dcmdata
-+ Type of modification: Compile-time tunable
-+ Explanation: Defines the default maximum permitted sequence nesting depth
-+ during DICOM parsing. Deeply nested sequences can cause a stack overflow
-+ by exhausting the call stack through unbounded recursion. When this macro
-+ is not defined, the default limit of 64 nested sequence levels is used.
-+ Real-world DICOM data rarely exceeds 5-10 nesting levels. The limit can
-+ be changed at runtime per parse operation via
-+ DcmInputStream::setMaxNestingDepth(), DcmItem::setMaxNestingDepth(), or
-+ DcmFileFormat::setMaxNestingDepth(). Setting the runtime value to -1
-+ disables the check entirely.
-+ Minimum value: 1. Values less than 1 cause a compile-time error.
-+ Maximum value: 2147483647 (aligned to 32-bit signed integer runtime API).
-+
- DCMTK_MERGE_STDERR_TO_STDOUT
- Affected: dcmdata
- Type of modification: Activates feature
---- dcmtk.orig/dcmdata/include/dcmtk/dcmdata/dcerror.h
-+++ dcmtk/dcmdata/include/dcmtk/dcmdata/dcerror.h
-@@ -1,6 +1,6 @@
- /*
- *
-- * Copyright (C) 1994-2025, OFFIS e.V.
-+ * Copyright (C) 1994-2026, OFFIS e.V.
- * All rights reserved. See COPYRIGHT file for details.
- *
- * This software and supporting documentation were developed by
-@@ -200,6 +200,8 @@
- extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_UnsupportedURIType;
- /// Execution of command line failed
- extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_CommandLineFailed;
-+/// Maximum sequence nesting depth exceeded (stack overflow protection)
-+extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_NestingDepthLimitExceeded;
-
- ///@}
-
---- dcmtk.orig/dcmdata/include/dcmtk/dcmdata/dcfilefo.h
-+++ dcmtk/dcmdata/include/dcmtk/dcmdata/dcfilefo.h
-@@ -514,6 +514,35 @@
-
- /// implementation version name to write in the meta-header
- OFString ImplementationVersionName;
-+
-+ /// maximum sequence nesting depth for parsing
-+ /// (0 = compile-time default DCMTK_MAX_SEQUENCE_NESTING, -1 = unlimited)
-+ Sint32 MaxNestingDepth;
-+
-+ public:
-+
-+ /** set the maximum permitted sequence nesting depth for parsing.
-+ * Applied to the input stream in loadFile() and read(), and also
-+ * forwarded to the contained dataset.
-+ * - Value 0 (default): apply the compile-time default
-+ * (DCMTK_MAX_SEQUENCE_NESTING, default is 64)
-+ * - Value -1: disable the check (allow unlimited nesting)
-+ * - Value > 0: use this value as the maximum permitted nesting depth
-+ * @param maxDepth maximum nesting depth setting
-+ */
-+ void setMaxNestingDepth(Sint32 maxDepth)
-+ {
-+ MaxNestingDepth = maxDepth;
-+ DcmDataset* dset = getDataset();
-+ if (dset)
-+ dset->setMaxNestingDepth(maxDepth);
-+ }
-+
-+ /** return the maximum permitted sequence nesting depth for parsing.
-+ * @return maximum nesting depth setting
-+ * (0 = compile-time default DCMTK_MAX_SEQUENCE_NESTING, -1 = unlimited)
-+ */
-+ Sint32 getMaxNestingDepth() const { return MaxNestingDepth; }
- };
-
-
---- dcmtk.orig/dcmdata/include/dcmtk/dcmdata/dcistrma.h
-+++ dcmtk/dcmdata/include/dcmtk/dcmdata/dcistrma.h
-@@ -1,6 +1,6 @@
- /*
- *
-- * Copyright (C) 1994-2018, OFFIS e.V.
-+ * Copyright (C) 1994-2026, OFFIS e.V.
- * All rights reserved. See COPYRIGHT file for details.
- *
- * This software and supporting documentation were developed by
-@@ -224,6 +224,40 @@
- */
- virtual DcmInputStreamFactory *newFactory() const = 0;
-
-+ /** returns the current sequence nesting depth.
-+ * This counter is used to prevent stack overflow from deeply nested
-+ * DICOM sequences in malicious input files.
-+ * @return current nesting depth
-+ */
-+ Uint32 nestingDepth() const;
-+
-+ /** increments the sequence nesting depth counter.
-+ * @return the new nesting depth after incrementing
-+ */
-+ Uint32 incrementNestingDepth();
-+
-+ /** decrements the sequence nesting depth counter.
-+ * Does nothing if the counter is already zero.
-+ */
-+ void decrementNestingDepth();
-+
-+ /** returns the maximum permitted sequence nesting depth for this stream.
-+ * A value of 0 means the compile-time default (DCMTK_MAX_SEQUENCE_NESTING) applies.
-+ * A value of -1 means the check is disabled (unlimited nesting).
-+ * @return maximum nesting depth setting
-+ */
-+ Sint32 maxNestingDepth() const;
-+
-+ /** sets the maximum permitted sequence nesting depth for this stream.
-+ * Must be called before parsing begins.
-+ * - Value 0 (default): apply the compile-time default
-+ * (DCMTK_MAX_SEQUENCE_NESTING, default is 64)
-+ * - Value -1: disable the check (allow unlimited nesting)
-+ * - Value > 0: use this value as the maximum permitted nesting depth
-+ * @param maxDepth maximum nesting depth setting
-+ */
-+ void setMaxNestingDepth(Sint32 maxDepth);
-+
- /** marks the current stream position for a later putback operation,
- * overwriting a possibly existing prior putback mark.
- * The DcmObject read methods rely on the possibility to putback
-@@ -272,6 +306,12 @@
-
- /// putback marker
- offile_off_t mark_;
-+
-+ /// current sequence nesting depth (for stack overflow protection)
-+ Uint32 nestingDepth_;
-+
-+ /// maximum permitted sequence nesting depth (0 = default 64, -1 = unlimited)
-+ Sint32 maxNestingDepth_;
- };
-
-
---- dcmtk.orig/dcmdata/include/dcmtk/dcmdata/dcitem.h
-+++ dcmtk/dcmdata/include/dcmtk/dcmdata/dcitem.h
-@@ -1,6 +1,6 @@
- /*
- *
-- * Copyright (C) 1994-2025, OFFIS e.V.
-+ * Copyright (C) 1994-2026, OFFIS e.V.
- * All rights reserved. See COPYRIGHT file for details.
- *
- * This software and supporting documentation were developed by
-@@ -1573,6 +1573,29 @@
-
- /// cache for private creator tags and identifiers
- DcmPrivateTagCache privateCreatorCache;
-+
-+ /// maximum sequence nesting depth for parsing
-+ /// (0 = compile-time default DCMTK_MAX_SEQUENCE_NESTING, -1 = unlimited)
-+ Sint32 maxNestingDepth;
-+
-+ public:
-+
-+ /** set the maximum permitted sequence nesting depth for parsing.
-+ * This limit is applied to the input stream before parsing in
-+ * loadFile() and read().
-+ * - Value 0 (default): apply the compile-time default
-+ * (DCMTK_MAX_SEQUENCE_NESTING, default is 64)
-+ * - Value -1: disable the check (allow unlimited nesting)
-+ * - Value > 0: use this value as the maximum permitted nesting depth
-+ * @param maxDepth maximum nesting depth setting
-+ */
-+ void setMaxNestingDepth(Sint32 maxDepth) { maxNestingDepth = maxDepth; }
-+
-+ /** return the maximum permitted sequence nesting depth for parsing.
-+ * @return maximum nesting depth setting
-+ * (0 = compile-time default DCMTK_MAX_SEQUENCE_NESTING, -1 = unlimited)
-+ */
-+ Sint32 getMaxNestingDepth() const { return maxNestingDepth; }
- };
-
- /** Checks whether left hand side item is smaller than right hand side
---- dcmtk.orig/dcmdata/include/dcmtk/dcmdata/dcobject.h
-+++ dcmtk/dcmdata/include/dcmtk/dcmdata/dcobject.h
-@@ -1,6 +1,6 @@
- /*
- *
-- * Copyright (C) 1994-2024, OFFIS e.V.
-+ * Copyright (C) 1994-2026, OFFIS e.V.
- * All rights reserved. See COPYRIGHT file for details.
- *
- * This software and supporting documentation were developed by
-@@ -50,6 +50,18 @@
-
- // Undefined Length Identifier now defined in dctypes.h
-
-+// Default maximum sequence nesting depth (can be overridden at compile time).
-+// Must be in the range [1, 2147483647].
-+#ifndef DCMTK_MAX_SEQUENCE_NESTING
-+#define DCMTK_MAX_SEQUENCE_NESTING 64
-+#endif
-+#if DCMTK_MAX_SEQUENCE_NESTING < 1
-+#error "DCMTK_MAX_SEQUENCE_NESTING must be >= 1"
-+#endif
-+#if DCMTK_MAX_SEQUENCE_NESTING > 2147483647
-+#error "DCMTK_MAX_SEQUENCE_NESTING must be <= 2147483647"
-+#endif
-+
- // Maximum number of read bytes for a Value Element
- const Uint32 DCM_MaxReadLength = 4096;
-
---- dcmtk.orig/dcmdata/libsrc/dcdatset.cc
-+++ dcmtk/dcmdata/libsrc/dcdatset.cc
-@@ -647,6 +647,9 @@
- {
- /* use stdin stream */
- DcmStdinStream inStream;
-+ /* apply configured nesting depth limit */
-+ if (getMaxNestingDepth() > 0)
-+ inStream.setMaxNestingDepth(getMaxNestingDepth());
-
- /* clear this object */
- l_error = clear();
-@@ -670,6 +673,9 @@
- } else {
- /* open file for input */
- DcmInputFileStream fileStream(fileName);
-+ /* apply configured nesting depth limit */
-+ if (getMaxNestingDepth() > 0)
-+ fileStream.setMaxNestingDepth(getMaxNestingDepth());
-
- /* check stream status */
- l_error = fileStream.status();
---- dcmtk.orig/dcmdata/libsrc/dcerror.cc
-+++ dcmtk/dcmdata/libsrc/dcerror.cc
-@@ -91,6 +91,7 @@
- makeOFConditionConst(EC_BulkDataURINotSupported, OFM_dcmdata, 66, OF_error, "BulkDataURI not yet supported" );
- makeOFConditionConst(EC_UnsupportedURIType, OFM_dcmdata, 67, OF_error, "Unsupported URI type" );
- makeOFConditionConst(EC_CommandLineFailed, OFM_dcmdata, 68, OF_error, "Execution of command line failed" );
-+makeOFConditionConst(EC_NestingDepthLimitExceeded, OFM_dcmdata, 69, OF_error, "Maximum sequence nesting depth exceeded" );
-
- const unsigned short EC_CODE_CannotSelectCharacterSet = 35;
- const unsigned short EC_CODE_CannotConvertCharacterSet = 36;
---- dcmtk.orig/dcmdata/libsrc/dcfilefo.cc
-+++ dcmtk/dcmdata/libsrc/dcfilefo.cc
-@@ -54,7 +54,8 @@
- : DcmSequenceOfItems(DCM_InternalUseTag),
- FileReadMode(ERM_autoDetect),
- ImplementationClassUID(OFFIS_IMPLEMENTATION_CLASS_UID),
-- ImplementationVersionName(OFFIS_DTK_IMPLEMENTATION_VERSION_NAME)
-+ ImplementationVersionName(OFFIS_DTK_IMPLEMENTATION_VERSION_NAME),
-+ MaxNestingDepth(0)
- {
- DcmMetaInfo *MetaInfo = new DcmMetaInfo();
- DcmSequenceOfItems::itemList->insert(MetaInfo);
-@@ -71,7 +72,8 @@
- : DcmSequenceOfItems(DCM_InternalUseTag),
- FileReadMode(ERM_autoDetect),
- ImplementationClassUID(OFFIS_IMPLEMENTATION_CLASS_UID),
-- ImplementationVersionName(OFFIS_DTK_IMPLEMENTATION_VERSION_NAME)
-+ ImplementationVersionName(OFFIS_DTK_IMPLEMENTATION_VERSION_NAME),
-+ MaxNestingDepth(0)
- {
- DcmMetaInfo *MetaInfo = new DcmMetaInfo();
- DcmSequenceOfItems::itemList->insert(MetaInfo);
-@@ -99,7 +101,8 @@
- : DcmSequenceOfItems(old),
- FileReadMode(old.FileReadMode),
- ImplementationClassUID(old.ImplementationClassUID),
-- ImplementationVersionName(old.ImplementationVersionName)
-+ ImplementationVersionName(old.ImplementationVersionName),
-+ MaxNestingDepth(old.MaxNestingDepth)
- {
- }
-
-@@ -128,6 +131,7 @@
- FileReadMode = obj.FileReadMode;
- ImplementationClassUID = obj.ImplementationClassUID;
- ImplementationVersionName = obj.ImplementationVersionName;
-+ MaxNestingDepth = obj.MaxNestingDepth;
- }
-
- return *this;
-@@ -942,6 +946,9 @@
- {
- /* use stdin stream */
- DcmStdinStream inStream;
-+ /* apply configured nesting depth limit */
-+ if (MaxNestingDepth != 0)
-+ inStream.setMaxNestingDepth(MaxNestingDepth);
-
- /* clear this object */
- l_error = clear();
-@@ -972,6 +979,9 @@
- } else {
- /* open file for output */
- DcmInputFileStream fileStream(fileName);
-+ /* apply configured nesting depth limit */
-+ if (MaxNestingDepth > 0)
-+ fileStream.setMaxNestingDepth(MaxNestingDepth);
-
- /* check stream status */
- l_error = fileStream.status();
---- dcmtk.orig/dcmdata/libsrc/dcistrma.cc
-+++ dcmtk/dcmdata/libsrc/dcistrma.cc
-@@ -1,6 +1,6 @@
- /*
- *
-- * Copyright (C) 1994-2010, OFFIS e.V.
-+ * Copyright (C) 1994-2026, OFFIS e.V.
- * All rights reserved. See COPYRIGHT file for details.
- *
- * This software and supporting documentation were developed by
-@@ -29,6 +29,8 @@
- , compressionFilter_(NULL)
- , tell_(0)
- , mark_(0)
-+, nestingDepth_(0)
-+, maxNestingDepth_(0)
- {
- }
-
-@@ -94,6 +96,32 @@
- return current_;
- }
-
-+Uint32 DcmInputStream::nestingDepth() const
-+{
-+ return nestingDepth_;
-+}
-+
-+Uint32 DcmInputStream::incrementNestingDepth()
-+{
-+ return ++nestingDepth_;
-+}
-+
-+void DcmInputStream::decrementNestingDepth()
-+{
-+ if (nestingDepth_ > 0)
-+ --nestingDepth_;
-+}
-+
-+Sint32 DcmInputStream::maxNestingDepth() const
-+{
-+ return maxNestingDepth_;
-+}
-+
-+void DcmInputStream::setMaxNestingDepth(Sint32 maxDepth)
-+{
-+ maxNestingDepth_ = maxDepth;
-+}
-+
- OFCondition DcmInputStream::installCompressionFilter(E_StreamCompression filterType)
- {
- OFCondition result = EC_Normal;
---- dcmtk.orig/dcmdata/libsrc/dcitem.cc
-+++ dcmtk/dcmdata/libsrc/dcitem.cc
-@@ -83,7 +83,8 @@
- elementList(NULL),
- lastElementComplete(OFTrue),
- fStartPosition(0),
-- privateCreatorCache()
-+ privateCreatorCache(),
-+ maxNestingDepth(0)
- {
- elementList = new DcmList;
- }
-@@ -95,7 +96,8 @@
- elementList(NULL),
- lastElementComplete(OFTrue),
- fStartPosition(0),
-- privateCreatorCache()
-+ privateCreatorCache(),
-+ maxNestingDepth(0)
- {
- elementList = new DcmList;
- }
-@@ -106,7 +108,8 @@
- elementList(new DcmList),
- lastElementComplete(old.lastElementComplete),
- fStartPosition(old.fStartPosition),
-- privateCreatorCache()
-+ privateCreatorCache(),
-+ maxNestingDepth(old.maxNestingDepth)
- {
- if (!old.elementList->empty())
- {
-@@ -136,6 +139,7 @@
- // copy DcmItem's member variables
- lastElementComplete = obj.lastElementComplete;
- fStartPosition = obj.fStartPosition;
-+ maxNestingDepth = obj.maxNestingDepth;
- if (!obj.elementList->empty())
- {
- elementList->seek(ELP_first);
-@@ -1394,6 +1398,10 @@
- return errorFlag;
- }
-
-+ /* apply configured nesting depth limit to the input stream (0 = use default, skip override) */
-+ if (getMaxNestingDepth() != 0)
-+ inStream.setMaxNestingDepth(getMaxNestingDepth());
-+
- /* figure out if the stream reported an error */
- errorFlag = inStream.status();
- /* if the stream reported an error or if it is the end of the */
---- dcmtk.orig/dcmdata/libsrc/dcsequen.cc
-+++ dcmtk/dcmdata/libsrc/dcsequen.cc
-@@ -1,6 +1,6 @@
- /*
- *
-- * Copyright (C) 1994-2023, OFFIS e.V.
-+ * Copyright (C) 1994-2026, OFFIS e.V.
- * All rights reserved. See COPYRIGHT file for details.
- *
- * This software and supporting documentation were developed by
-@@ -704,6 +704,23 @@
- errorFlag = EC_IllegalCall;
- else
- {
-+ const Uint32 depth = inStream.incrementNestingDepth();
-+ const Sint32 maxDepthSetting = inStream.maxNestingDepth();
-+ /* -1 = unlimited; 0 = use built-in default (DCMTK_MAX_SEQUENCE_NESTING); > 0 = custom limit */
-+ const Uint32 effectiveMax = (maxDepthSetting == 0) ? DCMTK_MAX_SEQUENCE_NESTING
-+ : (maxDepthSetting < 0) ? 0 /* unlimited */
-+ : OFstatic_cast(Uint32, maxDepthSetting);
-+ if (effectiveMax > 0 && depth > effectiveMax)
-+ {
-+ DCMDATA_ERROR("DcmSequenceOfItems: Maximum nesting depth (" << effectiveMax
-+ << ") exceeded while parsing sequence " << getTagName() << " " << getTag());
-+ inStream.decrementNestingDepth();
-+ errorFlag = EC_NestingDepthLimitExceeded;
-+ // dump information if required
-+ DCMDATA_TRACE("DcmSequenceOfItems::read() returns error = " << errorFlag.text());
-+ return errorFlag;
-+ }
-+
- errorFlag = inStream.status();
-
- if (errorFlag.good() && inStream.eos())
-@@ -773,6 +790,7 @@
- errorFlag = EC_Normal;
- if (errorFlag.good())
- setTransferState(ERW_ready); // sequence is complete
-+ inStream.decrementNestingDepth();
- }
- // dump information if required
- DCMDATA_TRACE("DcmSequenceOfItems::read() returns error = " << errorFlag.text());
---- dcmtk.orig/dcmdata/tests/CMakeLists.txt
-+++ dcmtk/dcmdata/tests/CMakeLists.txt
-@@ -11,6 +11,7 @@
- ti2dbmp.cc
- titem.cc
- tmatch.cc
-+ tnesting.cc
- tnewdcme.cc
- tparent.cc
- tparser.cc
---- dcmtk.orig/dcmdata/tests/Makefile.dep
-+++ dcmtk/dcmdata/tests/Makefile.dep
-@@ -712,6 +712,73 @@
- ../include/dcmtk/dcmdata/dcvr.h \
- ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
- ../include/dcmtk/dcmdata/dcmatch.h
-+tnesting.o: tnesting.cc ../../config/include/dcmtk/config/osconfig.h \
-+ ../../ofstd/include/dcmtk/ofstd/oftest.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
-+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofexbl.h \
-+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
-+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofconsol.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
-+ ../../ofstd/include/dcmtk/ofstd/offile.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
-+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
-+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
-+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
-+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
-+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofexit.h \
-+ ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \
-+ ../../oflog/include/dcmtk/oflog/oflog.h \
-+ ../../oflog/include/dcmtk/oflog/logger.h \
-+ ../../oflog/include/dcmtk/oflog/config.h \
-+ ../../oflog/include/dcmtk/oflog/config/defines.h \
-+ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
-+ ../../oflog/include/dcmtk/oflog/loglevel.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofvector.h \
-+ ../../oflog/include/dcmtk/oflog/tstring.h \
-+ ../../oflog/include/dcmtk/oflog/tchar.h \
-+ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
-+ ../../oflog/include/dcmtk/oflog/appender.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofmem.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofutil.h \
-+ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
-+ ../../oflog/include/dcmtk/oflog/layout.h \
-+ ../../oflog/include/dcmtk/oflog/streams.h \
-+ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
-+ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
-+ ../../oflog/include/dcmtk/oflog/spi/filter.h \
-+ ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
-+ ../../oflog/include/dcmtk/oflog/spi/logfact.h \
-+ ../../oflog/include/dcmtk/oflog/logmacro.h \
-+ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
-+ ../../oflog/include/dcmtk/oflog/tracelog.h \
-+ ../../ofstd/include/dcmtk/ofstd/oftempf.h \
-+ ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcitem.h \
-+ ../include/dcmtk/dcmdata/dctypes.h ../include/dcmtk/dcmdata/dcobject.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
-+ ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \
-+ ../include/dcmtk/dcmdata/dcvr.h \
-+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
-+ ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dctagkey.h \
-+ ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
-+ ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dclist.h \
-+ ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcfilefo.h \
-+ ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcelem.h \
-+ ../include/dcmtk/dcmdata/dcistrmb.h ../include/dcmtk/dcmdata/dcistrma.h \
-+ ../include/dcmtk/dcmdata/dcostrmb.h ../include/dcmtk/dcmdata/dcostrma.h \
-+ ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcwcache.h \
-+ ../include/dcmtk/dcmdata/dcfcache.h
- tnewdcme.o: tnewdcme.cc ../../config/include/dcmtk/config/osconfig.h \
- ../../ofstd/include/dcmtk/ofstd/oftest.h \
- ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
---- dcmtk.orig/dcmdata/tests/Makefile.in
-+++ dcmtk/dcmdata/tests/Makefile.in
-@@ -25,7 +25,7 @@
-
- objs = tests.o tpread.o ti2dbmp.o tchval.o tpath.o tvrdatim.o telemlen.o tparser.o \
- tdict.o tvrds.o tvrfd.o tvrui.o tvrol.o tvrov.o tvrsv.o tvruv.o tstrval.o \
-- tspchrs.o tvrpn.o tparent.o tfilter.o tvrcomp.o tmatch.o tnewdcme.o \
-+ tspchrs.o tvrpn.o tparent.o tfilter.o tvrcomp.o tmatch.o tnesting.o tnewdcme.o \
- tgenuid.o tsequen.o titem.o ttag.o txfer.o tbytestr.o tfrmsiz.o
-
- progs = tests
---- dcmtk.orig/dcmdata/tests/tests.cc
-+++ dcmtk/dcmdata/tests/tests.cc
-@@ -1,6 +1,6 @@
- /*
- *
-- * Copyright (C) 2011-2025 OFFIS e.V.
-+ * Copyright (C) 2011-2026 OFFIS e.V.
- * All rights reserved. See COPYRIGHT file for details.
- *
- * This software and supporting documentation were developed by
-@@ -127,5 +127,12 @@
- OFTEST_REGISTER(dcmdata_xferLookup_4);
- OFTEST_REGISTER(dcmdata_putOFStringAtPos);
- OFTEST_REGISTER(dcmdata_uncompressedFrameSize);
-+OFTEST_REGISTER(dcmdata_nestingDepthLimit_exceeded);
-+OFTEST_REGISTER(dcmdata_nestingDepthLimit_atLimit);
-+OFTEST_REGISTER(dcmdata_nestingDepthLimit_wellBelow);
-+OFTEST_REGISTER(dcmdata_nestingDepthLimit_customLimit);
-+OFTEST_REGISTER(dcmdata_nestingDepthLimit_disabled);
-+OFTEST_REGISTER(dcmdata_nestingDepthLimit_datasetAPI);
-+OFTEST_REGISTER(dcmdata_nestingDepthLimit_fileFormatAPI);
-
- OFTEST_MAIN("dcmdata")
---- /dev/null
-+++ dcmtk/dcmdata/tests/tnesting.cc
-@@ -0,0 +1,266 @@
-+/*
-+ *
-+ * Copyright (C) 2026, OFFIS e.V.
-+ * All rights reserved. See COPYRIGHT file for details.
-+ *
-+ * This software and supporting documentation were developed by
-+ *
-+ * OFFIS e.V.
-+ * R&D Division Health
-+ * Escherweg 2
-+ * D-26121 Oldenburg, Germany
-+ *
-+ *
-+ * Module: dcmdata
-+ *
-+ * Author: Michael Onken
-+ *
-+ * Purpose: test program for sequence nesting depth limit
-+ *
-+ */
-+
-+
-+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
-+
-+#include "dcmtk/ofstd/oftest.h"
-+#include "dcmtk/ofstd/oftempf.h"
-+#include "dcmtk/dcmdata/dcdatset.h"
-+#include "dcmtk/dcmdata/dcfilefo.h"
-+#include "dcmtk/dcmdata/dcsequen.h"
-+#include "dcmtk/dcmdata/dcistrmb.h"
-+#include "dcmtk/dcmdata/dcostrmb.h"
-+#include "dcmtk/dcmdata/dcerror.h"
-+#include "dcmtk/dcmdata/dcdeftag.h"
-+#include "dcmtk/dcmdata/dcwcache.h"
-+
-+
-+/** Helper: build a DcmDataset containing a chain of nested sequences to the
-+ * specified depth using the high-level dcmdata API. Each nesting level
-+ * consists of a DcmSequenceOfItems with one DcmItem, and the innermost
-+ * item is empty.
-+ * @param depth the number of nested sequence levels to generate
-+ * @param dset output dataset (cleared before use)
-+ */
-+static void buildNestedDataset(Uint32 depth, DcmDataset& dset)
-+{
-+ dset.clear();
-+ /* start with the dataset as the outermost item */
-+ DcmItem* currentItem = &dset;
-+ for (Uint32 i = 0; i < depth; ++i)
-+ {
-+ DcmSequenceOfItems* seq = new DcmSequenceOfItems(DCM_ReferencedSeriesSequence);
-+ currentItem->insert(seq);
-+ DcmItem* item = new DcmItem();
-+ seq->insert(item);
-+ currentItem = item;
-+ }
-+}
-+
-+
-+/** Helper: serialize a dataset to a byte buffer and parse it back using a
-+ * fresh DcmInputStream, with an optional custom nesting depth limit.
-+ * @param srcDset the dataset to serialize
-+ * @param dstDset output dataset to receive the parsed result
-+ * @param maxNestingDepth nesting depth setting passed to setMaxNestingDepth():
-+ * 0 (default) = compile-time default (DCMTK_MAX_SEQUENCE_NESTING), -1 = unlimited, > 0 = custom limit
-+ * @return the OFCondition returned by DcmDataset::read()
-+ */
-+static OFCondition serializeAndParse(DcmDataset& srcDset, DcmDataset& dstDset,
-+ Sint32 maxNestingDepth = 0)
-+{
-+ /* write the dataset to a memory buffer */
-+ const size_t bufLen = 1024 * 1024;
-+ Uint8* buf = new Uint8[bufLen];
-+
-+ DcmOutputBufferStream outStream(buf, bufLen);
-+ srcDset.transferInit();
-+ DcmWriteCache wcache;
-+ OFCondition cond = srcDset.write(outStream, EXS_LittleEndianExplicit, EET_UndefinedLength, &wcache);
-+ srcDset.transferEnd();
-+ if (cond.bad())
-+ {
-+ delete[] buf;
-+ return cond;
-+ }
-+ offile_off_t bytesWritten = 0;
-+ void* writtenBuf = NULL;
-+ outStream.flushBuffer(writtenBuf, bytesWritten);
-+
-+ /* parse it back with nesting depth limit */
-+ DcmInputBufferStream inStream;
-+ inStream.setBuffer(buf, bytesWritten);
-+ inStream.setEos();
-+ inStream.setMaxNestingDepth(maxNestingDepth);
-+
-+ dstDset.clear();
-+ dstDset.transferInit();
-+ cond = dstDset.read(inStream, EXS_LittleEndianExplicit);
-+ dstDset.transferEnd();
-+
-+ delete[] buf;
-+ return cond;
-+}
-+
-+
-+OFTEST(dcmdata_nestingDepthLimit_exceeded)
-+{
-+ /* One level beyond the default limit (DCMTK_MAX_SEQUENCE_NESTING) must be rejected. */
-+ DcmDataset srcDset, dstDset;
-+ buildNestedDataset(DCMTK_MAX_SEQUENCE_NESTING + 1, srcDset);
-+
-+ OFCondition cond = serializeAndParse(srcDset, dstDset);
-+ if (cond != EC_NestingDepthLimitExceeded)
-+ {
-+ OFCHECK_FAIL("Expected EC_NestingDepthLimitExceeded for " << (DCMTK_MAX_SEQUENCE_NESTING + 1)
-+ << " levels of nesting, but got: " << cond.text());
-+ }
-+}
-+
-+
-+OFTEST(dcmdata_nestingDepthLimit_atLimit)
-+{
-+ /* Exactly DCMTK_MAX_SEQUENCE_NESTING levels must still pass. */
-+ DcmDataset srcDset, dstDset;
-+ buildNestedDataset(DCMTK_MAX_SEQUENCE_NESTING, srcDset);
-+
-+ OFCondition cond = serializeAndParse(srcDset, dstDset);
-+ if (cond.bad())
-+ {
-+ OFCHECK_FAIL("Parsing " << DCMTK_MAX_SEQUENCE_NESTING
-+ << " levels of nesting should succeed, but got: " << cond.text());
-+ }
-+}
-+
-+
-+OFTEST(dcmdata_nestingDepthLimit_wellBelow)
-+{
-+ /* 5 levels of nesting (typical real-world depth) must parse fine. */
-+ DcmDataset srcDset, dstDset;
-+ buildNestedDataset(5, srcDset);
-+
-+ OFCondition cond = serializeAndParse(srcDset, dstDset);
-+ if (cond.bad())
-+ {
-+ OFCHECK_FAIL("Parsing 5 levels of nesting should succeed, but got: " << cond.text());
-+ }
-+}
-+
-+
-+OFTEST(dcmdata_nestingDepthLimit_customLimit)
-+{
-+ /* Test setMaxNestingDepth(): set the limit to 10.
-+ * 10 levels must succeed, 11 levels must fail. */
-+ DcmDataset srcDset, dstDset;
-+ OFCondition cond;
-+
-+ buildNestedDataset(10, srcDset);
-+ cond = serializeAndParse(srcDset, dstDset, 10);
-+ if (cond.bad())
-+ {
-+ OFCHECK_FAIL("Parsing 10 levels with maxNestingDepth=10 should succeed, but got: " << cond.text());
-+ }
-+
-+ buildNestedDataset(11, srcDset);
-+ cond = serializeAndParse(srcDset, dstDset, 10);
-+ if (cond != EC_NestingDepthLimitExceeded)
-+ {
-+ OFCHECK_FAIL("Expected EC_NestingDepthLimitExceeded for 11 levels with maxNestingDepth=10, but got: " << cond.text());
-+ }
-+}
-+
-+
-+OFTEST(dcmdata_nestingDepthLimit_disabled)
-+{
-+ /* Test that setMaxNestingDepth(-1) disables the limit entirely.
-+ * Even 200 levels of nesting must succeed. */
-+ DcmDataset srcDset, dstDset;
-+ buildNestedDataset(200, srcDset);
-+
-+ OFCondition cond = serializeAndParse(srcDset, dstDset, -1);
-+ if (cond.bad())
-+ {
-+ OFCHECK_FAIL("Parsing 200 levels with maxNestingDepth=-1 (unlimited) should succeed, but got: " << cond.text());
-+ }
-+}
-+
-+
-+/** Helper: create a temporary file path.
-+ * @param tmpFile receives the temporary file path
-+ * @return EC_Normal if successful
-+ */
-+static OFCondition makeTempFile(OFString& tmpFile)
-+{
-+ return OFTempFile::createFile(tmpFile, NULL /* fd_out */, O_RDWR,
-+ "" /* dir */, "" /* prefix */, ".dcm" /* postfix */);
-+}
-+
-+
-+OFTEST(dcmdata_nestingDepthLimit_datasetAPI)
-+{
-+ /* Test DcmDataset::setMaxNestingDepth() with loadFile(). */
-+ DcmDataset srcDset;
-+ OFString tmpFile;
-+ OFCondition cond;
-+
-+ /* save as raw dataset (no meta header) */
-+ buildNestedDataset(11, srcDset);
-+ cond = makeTempFile(tmpFile);
-+ OFCHECK(cond.good());
-+ cond = srcDset.saveFile(tmpFile, EXS_LittleEndianExplicit);
-+ OFCHECK(cond.good());
-+
-+ /* default limit (DCMTK_MAX_SEQUENCE_NESTING): 11 levels should succeed */
-+ DcmDataset dset1;
-+ cond = dset1.loadFile(tmpFile, EXS_LittleEndianExplicit);
-+ if (cond.bad())
-+ {
-+ OFCHECK_FAIL("DcmDataset::loadFile() with 11 levels should succeed with default limit, but got: " << cond.text());
-+ }
-+
-+ /* custom limit 10: 11 levels should fail */
-+ DcmDataset dset2;
-+ dset2.setMaxNestingDepth(10);
-+ cond = dset2.loadFile(tmpFile, EXS_LittleEndianExplicit);
-+ if (cond != EC_NestingDepthLimitExceeded)
-+ {
-+ OFCHECK_FAIL("DcmDataset::loadFile() with 11 levels and maxNestingDepth=10 should fail, but got: " << cond.text());
-+ }
-+
-+ OFStandard::deleteFile(tmpFile);
-+}
-+
-+
-+OFTEST(dcmdata_nestingDepthLimit_fileFormatAPI)
-+{
-+ /* Test DcmFileFormat::setMaxNestingDepth() with loadFile(). */
-+ DcmDataset srcDset;
-+ OFString tmpFile;
-+ OFCondition cond;
-+
-+ /* save as DcmFileFormat (with meta header) */
-+ buildNestedDataset(11, srcDset);
-+ cond = makeTempFile(tmpFile);
-+ OFCHECK(cond.good());
-+ DcmFileFormat srcFF(&srcDset);
-+ cond = srcFF.saveFile(tmpFile, EXS_LittleEndianExplicit);
-+ OFCHECK(cond.good());
-+
-+ /* default limit (DCMTK_MAX_SEQUENCE_NESTING): 11 levels should succeed */
-+ DcmFileFormat ff1;
-+ cond = ff1.loadFile(tmpFile);
-+ if (cond.bad())
-+ {
-+ OFCHECK_FAIL("DcmFileFormat::loadFile() with 11 levels should succeed with default limit, but got: " << cond.text());
-+ }
-+
-+ /* custom limit 10: 11 levels should fail */
-+ DcmFileFormat ff2;
-+ ff2.setMaxNestingDepth(10);
-+ cond = ff2.loadFile(tmpFile);
-+ if (cond != EC_NestingDepthLimitExceeded)
-+ {
-+ OFCHECK_FAIL("DcmFileFormat::loadFile() with 11 levels and maxNestingDepth=10 should fail, but got: " << cond.text());
-+ }
-+
-+ OFStandard::deleteFile(tmpFile);
-+}
---- dcmtk.orig/dcmnet/include/dcmtk/dcmnet/scp.h
-+++ dcmtk/dcmnet/include/dcmtk/dcmnet/scp.h
-@@ -360,6 +360,17 @@
- */
- void setAlwaysAcceptDefaultRole(const OFBool enabled);
-
-+ /** Set the maximum permitted sequence nesting depth for parsing
-+ * datasets received over the network. This limit is applied to
-+ * each dataset received via receiveDIMSEDataset().
-+ * - Value 0 (default): apply the compile-time default
-+ * (DCMTK_MAX_SEQUENCE_NESTING)
-+ * - Value -1: disable the check (allow unlimited nesting)
-+ * - Value > 0: use this value as the maximum nesting depth
-+ * @param maxDepth maximum nesting depth setting
-+ */
-+ void setMaxNestingDepth(const Sint32 maxDepth);
-+
- /* Get methods for SCP settings */
-
- /** Returns TCP/IP port number SCP listens for new connection requests
-@@ -434,6 +445,14 @@
- */
- OFBool getProgressNotificationMode() const;
-
-+ /** Return the maximum permitted sequence nesting depth for
-+ * parsing datasets received over the network.
-+ * @return maximum nesting depth setting
-+ * (0 = compile-time default DCMTK_MAX_SEQUENCE_NESTING,
-+ * -1 = unlimited)
-+ */
-+ Sint32 getMaxNestingDepth() const;
-+
- /** Get access to the configuration of the SCP. Note that the functionality
- * on the configuration object is shadowed by other API functions of DcmSCP.
- * The existing functions are provided in order to not break users of this
-@@ -1157,6 +1176,11 @@
- /// it, e.g. in the context of the DcmSCPPool class.
- DcmSharedSCPConfig m_cfg;
-
-+ /// Maximum sequence nesting depth for parsing received datasets
-+ /// (0 = compile-time default DCMTK_MAX_SEQUENCE_NESTING,
-+ /// -1 = unlimited)
-+ Sint32 m_maxNestingDepth;
-+
- /** Drops association and clears internal structures to free memory
- */
- void dropAndDestroyAssociation();
---- dcmtk.orig/dcmnet/include/dcmtk/dcmnet/scu.h
-+++ dcmtk/dcmnet/include/dcmtk/dcmnet/scu.h
-@@ -739,6 +739,17 @@
- */
- void setProgressNotificationMode(const OFBool mode);
-
-+ /** Set the maximum permitted sequence nesting depth for parsing
-+ * datasets received over the network. This limit is applied to
-+ * each dataset received via receiveDIMSEDataset().
-+ * - Value 0 (default): apply the compile-time default
-+ * (DCMTK_MAX_SEQUENCE_NESTING)
-+ * - Value -1: disable the check (allow unlimited nesting)
-+ * - Value > 0: use this value as the maximum nesting depth
-+ * @param maxDepth maximum nesting depth setting
-+ */
-+ void setMaxNestingDepth(const Sint32 maxDepth);
-+
- /* Get methods */
-
- /** Get current connection status
-@@ -831,6 +842,14 @@
- */
- OFBool getProgressNotificationMode() const;
-
-+ /** Return the maximum permitted sequence nesting depth for
-+ * parsing datasets received over the network.
-+ * @return maximum nesting depth setting
-+ * (0 = compile-time default DCMTK_MAX_SEQUENCE_NESTING,
-+ * -1 = unlimited)
-+ */
-+ Sint32 getMaxNestingDepth() const;
-+
- /** Returns whether SCU is configured to create a TLS connection with the SCP
- * @return OFTrue if TLS mode has been enabled, OFFalse otherwise
- */
-@@ -1136,6 +1155,11 @@
- /// Progress notification mode (default: enabled)
- OFBool m_progressNotificationMode;
-
-+ /// Maximum sequence nesting depth for parsing received datasets
-+ /// (0 = compile-time default DCMTK_MAX_SEQUENCE_NESTING,
-+ /// -1 = unlimited)
-+ Sint32 m_maxNestingDepth;
-+
- /// Flag indicating whether secure mode has been enabled (default: disabled)
- OFBool m_secureConnectionEnabled;
-
---- dcmtk.orig/dcmnet/libsrc/dimse.cc
-+++ dcmtk/dcmnet/libsrc/dimse.cc
-@@ -1,6 +1,6 @@
- /*
- *
-- * Copyright (C) 1994-2025, OFFIS e.V.
-+ * Copyright (C) 1994-2026, OFFIS e.V.
- * All rights reserved. See COPYRIGHT file for details.
- *
- * This software and supporting documentation were partly developed by
-@@ -1536,7 +1536,8 @@
- dset = *dataObject;
- }
-
-- /* check if there is still no DcmDataset object which can be used to store the data set. */
-+ /* check if there is still no DcmDataset object (i.e. if allocation fails) */
-+ /* which can be used to store the data set. */
- if (dset == NULL)
- {
- /* if this is the case, just go ahead an receive data, but do not store it anywhere */
---- dcmtk.orig/dcmnet/libsrc/scp.cc
-+++ dcmtk/dcmnet/libsrc/scp.cc
-@@ -32,6 +32,7 @@
- : m_network(NULL)
- , m_assoc(NULL)
- , m_cfg()
-+, m_maxNestingDepth(0)
- {
- OFStandard::initializeNetwork();
- }
-@@ -1590,6 +1591,19 @@
- if (m_assoc == NULL)
- return DIMSE_ILLEGALASSOCIATION;
-
-+ /* if a custom nesting depth limit is configured, pre-allocate
-+ * the dataset and apply the setting before parsing starts.
-+ * DIMSE_receiveDataSetInMemory() will use this dataset instead
-+ * of creating a new one internally. */
-+ OFBool weAllocated = OFFalse;
-+ if (dataObject != NULL && *dataObject == NULL
-+ && m_maxNestingDepth != 0)
-+ {
-+ *dataObject = new DcmDataset();
-+ (*dataObject)->setMaxNestingDepth(m_maxNestingDepth);
-+ weAllocated = OFTrue;
-+ }
-+
- OFCondition cond;
- /* call the corresponding DIMSE function to receive the dataset */
- if (m_cfg->getProgressNotificationMode())
-@@ -1619,6 +1633,14 @@
- }
- else
- {
-+ /* if we pre-allocated the dataset, clean up on error since
-+ * DIMSE_receiveDataSetInMemory() won't delete a dataset
-+ * that was passed in by the caller */
-+ if (weAllocated && dataObject != NULL)
-+ {
-+ delete *dataObject;
-+ *dataObject = NULL;
-+ }
- OFString tempStr;
- DCMNET_ERROR("Unable to receive dataset on presentation context "
- << OFstatic_cast(unsigned int, *presID) << ": " << DimseCondition::dump(tempStr, cond));
-@@ -1910,6 +1932,13 @@
-
- // ----------------------------------------------------------------------------
-
-+void DcmSCP::setMaxNestingDepth(const Sint32 maxDepth)
-+{
-+ m_maxNestingDepth = maxDepth;
-+}
-+
-+// ----------------------------------------------------------------------------
-+
- /* Get methods for SCP settings and current association information */
-
- OFBool DcmSCP::getRefuseAssociation() const
-@@ -2002,6 +2031,13 @@
- }
-
- // ----------------------------------------------------------------------------
-+
-+Sint32 DcmSCP::getMaxNestingDepth() const
-+{
-+ return m_maxNestingDepth;
-+}
-+
-+// ----------------------------------------------------------------------------
-
- OFBool DcmSCP::isConnected() const
- {
---- dcmtk.orig/dcmnet/libsrc/scu.cc
-+++ dcmtk/dcmnet/libsrc/scu.cc
-@@ -56,6 +56,7 @@
- , m_verbosePCMode(OFFalse)
- , m_datasetConversionMode(OFFalse)
- , m_progressNotificationMode(OFTrue)
-+ , m_maxNestingDepth(0)
- , m_secureConnectionEnabled(OFFalse)
- , m_protocolVersion(ASC_AF_Default)
- {
-@@ -2500,6 +2501,19 @@
- if (!isConnected())
- return DIMSE_ILLEGALASSOCIATION;
-
-+ /* if a custom nesting depth limit is configured, pre-allocate
-+ * the dataset and apply the setting before parsing starts.
-+ * DIMSE_receiveDataSetInMemory() will use this dataset instead
-+ * of creating a new one internally. */
-+ OFBool weAllocated = OFFalse;
-+ if (dataObject != NULL && *dataObject == NULL
-+ && m_maxNestingDepth != 0)
-+ {
-+ *dataObject = new DcmDataset();
-+ (*dataObject)->setMaxNestingDepth(m_maxNestingDepth);
-+ weAllocated = OFTrue;
-+ }
-+
- OFCondition cond;
- /* call the corresponding DIMSE function to receive the dataset */
- if (m_progressNotificationMode)
-@@ -2519,6 +2533,14 @@
- }
- else
- {
-+ /* if we pre-allocated the dataset, clean up on error since
-+ * DIMSE_receiveDataSetInMemory() won't delete a dataset
-+ * that was passed in by the caller */
-+ if (weAllocated && dataObject != NULL)
-+ {
-+ delete *dataObject;
-+ *dataObject = NULL;
-+ }
- OFString tempStr;
- DCMNET_ERROR("Unable to receive dataset on presentation context "
- << OFstatic_cast(unsigned int, *presID) << ": " << DimseCondition::dump(tempStr, cond));
-@@ -2607,6 +2629,11 @@
- m_progressNotificationMode = mode;
- }
-
-+void DcmSCU::setMaxNestingDepth(const Sint32 maxDepth)
-+{
-+ m_maxNestingDepth = maxDepth;
-+}
-+
- void DcmSCU::setProtocolVersion(T_ASC_ProtocolFamily protocolVersion)
- {
- m_protocolVersion = protocolVersion;
-@@ -2694,6 +2721,11 @@
- return m_progressNotificationMode;
- }
-
-+Sint32 DcmSCU::getMaxNestingDepth() const
-+{
-+ return m_maxNestingDepth;
-+}
-+
- OFCondition DcmSCU::getDatasetInfo(DcmDataset* dataset,
- OFString& sopClassUID,
- OFString& sopInstanceUID,
---- dcmtk.orig/dcmnet/tests/tests.cc
-+++ dcmtk/dcmnet/tests/tests.cc
-@@ -51,6 +51,11 @@
- OFTEST_REGISTER(dcmnet_scu_sendNSETRequest_succeeds_and_modifies_instance_when_scp_has_instance);
- OFTEST_REGISTER(dcmnet_scu_sendNSETRequest_succeeds_and_sets_responsestatuscode_from_scp_when_scp_sets_error_status);
-
-+OFTEST_REGISTER(dcmnet_scp_maxNestingDepth_getset);
-+OFTEST_REGISTER(dcmnet_scu_maxNestingDepth_getset);
-+OFTEST_REGISTER(dcmnet_scp_maxNestingDepth_rejects_deep);
-+OFTEST_REGISTER(dcmnet_scp_maxNestingDepth_accepts_shallow);
-+
- #endif // WITH_THREADS
-
- OFTEST_MAIN("dcmnet")
---- dcmtk.orig/dcmnet/tests/tscuscp.cc
-+++ dcmtk/dcmnet/tests/tscuscp.cc
-@@ -1113,4 +1113,209 @@
- }
-
-
-+// Test that setMaxNestingDepth/getMaxNestingDepth work on DcmSCP
-+OFTEST(dcmnet_scp_maxNestingDepth_getset)
-+{
-+ DcmSCP scp;
-+ // Default must be 0 (use compile-time default)
-+ OFCHECK_EQUAL(scp.getMaxNestingDepth(), 0);
-+ scp.setMaxNestingDepth(10);
-+ OFCHECK_EQUAL(scp.getMaxNestingDepth(), 10);
-+ scp.setMaxNestingDepth(-1);
-+ OFCHECK_EQUAL(scp.getMaxNestingDepth(), -1);
-+ scp.setMaxNestingDepth(0);
-+ OFCHECK_EQUAL(scp.getMaxNestingDepth(), 0);
-+}
-+
-+
-+// Test that setMaxNestingDepth/getMaxNestingDepth work on DcmSCU
-+OFTEST(dcmnet_scu_maxNestingDepth_getset)
-+{
-+ DcmSCU scu;
-+ // Default must be 0 (use compile-time default)
-+ OFCHECK_EQUAL(scu.getMaxNestingDepth(), 0);
-+ scu.setMaxNestingDepth(5);
-+ OFCHECK_EQUAL(scu.getMaxNestingDepth(), 5);
-+ scu.setMaxNestingDepth(-1);
-+ OFCHECK_EQUAL(scu.getMaxNestingDepth(), -1);
-+ scu.setMaxNestingDepth(0);
-+ OFCHECK_EQUAL(scu.getMaxNestingDepth(), 0);
-+}
-+
-+
-+/** Helper: build a DcmDataset with nested sequences to a given depth.
-+ * @param depth number of nesting levels
-+ * @param dset output dataset (cleared before use)
-+ */
-+static void buildNestedDataset(Uint32 depth, DcmDataset& dset)
-+{
-+ dset.clear();
-+ DcmItem* currentItem = &dset;
-+ for (Uint32 i = 0; i < depth; ++i)
-+ {
-+ DcmSequenceOfItems* sq =
-+ new DcmSequenceOfItems(DCM_ReferencedSeriesSequence);
-+ currentItem->insert(sq);
-+ DcmItem* item = new DcmItem();
-+ sq->insert(item);
-+ currentItem = item;
-+ }
-+}
-+
-+
-+/** SCP that applies a nesting depth limit and records whether
-+ * receiving the dataset succeeded or failed.
-+ */
-+struct NestingTestSCP : TestSCP
-+{
-+ NestingTestSCP(Sint32 maxNesting)
-+ : TestSCP()
-+ , m_receiveResult(EC_NotYetImplemented)
-+ {
-+ setMaxNestingDepth(maxNesting);
-+ DcmSCPConfig& config = getConfig();
-+ config.setAETitle("NESTING_SCP");
-+ config.setConnectionBlockingMode(DUL_NOBLOCK);
-+ config.setConnectionTimeout(10);
-+ config.setHostLookupEnabled(OFFalse);
-+ config.setPort(0);
-+ OFList<OFString> xfers;
-+ xfers.push_back(UID_LittleEndianImplicitTransferSyntax);
-+ OFCHECK(config.addPresentationContext(
-+ UID_ModalityPerformedProcedureStepSOPClass, xfers).good());
-+ OFCHECK(openListenPort().good());
-+ m_portNum = config.getPort();
-+ }
-+
-+ OFCondition handleIncomingCommand(
-+ T_DIMSE_Message* incomingMsg,
-+ const DcmPresentationContextInfo& presInfo)
-+ {
-+ if (incomingMsg->CommandField == DIMSE_N_CREATE_RQ)
-+ {
-+ T_DIMSE_N_CreateRQ& req = incomingMsg->msg.NCreateRQ;
-+ if (req.DataSetType != DIMSE_DATASET_NULL)
-+ {
-+ DcmDataset* dataset = OFnullptr;
-+ T_ASC_PresentationContextID presIDdset;
-+ m_receiveResult =
-+ receiveDIMSEDataset(&presIDdset, &dataset);
-+ /* send a response regardless of receive outcome */
-+ T_DIMSE_Message rsp;
-+ memset(&rsp, 0, sizeof(rsp));
-+ rsp.CommandField = DIMSE_N_CREATE_RSP;
-+ T_DIMSE_N_CreateRSP& createRsp = rsp.msg.NCreateRSP;
-+ createRsp.MessageIDBeingRespondedTo = req.MessageID;
-+ createRsp.DimseStatus = m_receiveResult.good()
-+ ? STATUS_N_Success
-+ : STATUS_N_ProcessingFailure;
-+ createRsp.DataSetType = DIMSE_DATASET_NULL;
-+ OFStandard::strlcpy(
-+ createRsp.AffectedSOPClassUID,
-+ req.AffectedSOPClassUID,
-+ sizeof(createRsp.AffectedSOPClassUID));
-+ createRsp.opts = O_NCREATE_AFFECTEDSOPCLASSUID;
-+ sendDIMSEMessage(
-+ presInfo.presentationContextID, &rsp, NULL);
-+ delete dataset;
-+ }
-+ return EC_Normal;
-+ }
-+ return DcmSCP::handleIncomingCommand(incomingMsg, presInfo);
-+ }
-+
-+ /// Result of receiveDIMSEDataset() for the last request
-+ OFCondition m_receiveResult;
-+ /// Port the SCP is listening on
-+ Uint16 m_portNum;
-+};
-+
-+
-+// Test that SCP's nesting depth limit rejects deeply nested data
-+// received over the network
-+OFTEST_FLAGS(dcmnet_scp_maxNestingDepth_rejects_deep, EF_Slow)
-+{
-+ NestingTestSCP scp(3);
-+ scp.m_set_stop_after_assoc = OFTrue;
-+ scp.start();
-+ OFStandard::forceSleep(1);
-+
-+ // SCU sends a dataset with 4 levels of nesting (exceeds limit 3)
-+ DcmSCU scu;
-+ scu.setAETitle("NESTING_SCU");
-+ scu.setPeerAETitle("NESTING_SCP");
-+ scu.setPeerHostName("localhost");
-+ scu.setPeerPort(scp.m_portNum);
-+ OFList<OFString> xfers;
-+ xfers.push_back(UID_LittleEndianImplicitTransferSyntax);
-+ OFCHECK(scu.addPresentationContext(
-+ UID_ModalityPerformedProcedureStepSOPClass, xfers).good());
-+ OFCHECK(scu.initNetwork().good());
-+ OFCHECK(scu.negotiateAssociation().good());
-+
-+ DcmDataset reqDataset;
-+ buildNestedDataset(4, reqDataset);
-+ T_ASC_PresentationContextID presID = scu.findPresentationContextID(
-+ UID_ModalityPerformedProcedureStepSOPClass,
-+ UID_LittleEndianImplicitTransferSyntax);
-+ OFCHECK(presID != 0);
-+ Uint16 rspStatus = 0;
-+ DcmDataset* rspDataset = NULL;
-+ scu.sendNCREATERequest(presID, "1.2.3.4.5",
-+ &reqDataset, rspDataset, rspStatus);
-+ delete rspDataset;
-+ if (scu.isConnected())
-+ scu.releaseAssociation();
-+ OFStandard::forceSleep(2);
-+ scp.join();
-+
-+ // Verify SCP saw the nesting depth error
-+ OFCHECK(scp.m_receiveResult == DIMSE_RECEIVEFAILED);
-+}
-+
-+
-+// Test that SCP's nesting depth limit accepts data within the limit
-+OFTEST_FLAGS(dcmnet_scp_maxNestingDepth_accepts_shallow, EF_Slow)
-+{
-+ NestingTestSCP scp(3);
-+ scp.m_set_stop_after_assoc = OFTrue;
-+ scp.start();
-+ OFStandard::forceSleep(1);
-+
-+ // SCU sends a dataset with 3 levels of nesting (at the limit)
-+ DcmSCU scu;
-+ scu.setAETitle("NESTING_SCU");
-+ scu.setPeerAETitle("NESTING_SCP");
-+ scu.setPeerHostName("localhost");
-+ scu.setPeerPort(scp.m_portNum);
-+ OFList<OFString> xfers;
-+ xfers.push_back(UID_LittleEndianImplicitTransferSyntax);
-+ OFCHECK(scu.addPresentationContext(
-+ UID_ModalityPerformedProcedureStepSOPClass, xfers).good());
-+ OFCHECK(scu.initNetwork().good());
-+ OFCHECK(scu.negotiateAssociation().good());
-+
-+ DcmDataset reqDataset;
-+ buildNestedDataset(3, reqDataset);
-+ T_ASC_PresentationContextID presID = scu.findPresentationContextID(
-+ UID_ModalityPerformedProcedureStepSOPClass,
-+ UID_LittleEndianImplicitTransferSyntax);
-+ OFCHECK(presID != 0);
-+ Uint16 rspStatus = 0;
-+ DcmDataset* rspDataset = NULL;
-+ OFCondition result = scu.sendNCREATERequest(presID, "1.2.3.4.5",
-+ &reqDataset, rspDataset, rspStatus);
-+ OFCHECK_MSG(result.good(), result.text());
-+ OFCHECK(rspStatus == STATUS_N_Success);
-+ delete rspDataset;
-+ if (scu.isConnected())
-+ OFCHECK(scu.releaseAssociation().good());
-+ OFStandard::forceSleep(2);
-+ scp.join();
-+
-+ // Verify SCP successfully received the dataset
-+ OFCHECK(scp.m_receiveResult.good());
-+}
-+
-+
- #endif // WITH_THREADS
=====================================
debian/patches/series
=====================================
@@ -5,4 +5,3 @@ remove_version.patch
skip-bigendian-roundtrip-failure.patch
hurd.patch
CVE-2026-5663.patch
-CVE-2026-10528-partial.patch
View it on GitLab: https://salsa.debian.org/med-team/dcmtk/-/compare/7ab71d3e98014bb2d9b4897e9bc61604285d2613...213f23d808e97458c73dd6689b35d3466c4cc556
--
View it on GitLab: https://salsa.debian.org/med-team/dcmtk/-/compare/7ab71d3e98014bb2d9b4897e9bc61604285d2613...213f23d808e97458c73dd6689b35d3466c4cc556
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20260604/1e8140b1/attachment-0001.htm>
More information about the debian-med-commit
mailing list