Hi SRMs,

Since the opening of the present request, a new issue cropped up
in dcmtk, also affecting bookworm.  For reference, the change is
the bookworm equivalent of the trixie-proposed-updates #1140693,
except the present upload never occurred, hence no version bump.
You will find below my revised form, including the new change.

> [ Reason ]
> dcmtk in bookworm is currently affected by several security
> issues, namely:
> 
>   * CVE-2022-4981,
>   * CVE-2025-2357, described in #1100724,
>   * CVE-2025-9732, described in #1113993,
>   * CVE-2025-14607, described in #1122926,
>   * CVE-2025-14841, described in #1123584,
>   * CVE-2026-5663, described in #1133001,
>   * CVE-2026-10194, described in #1139181.

  * CVE-2026-12805, described in #1140562.

> They are all sorted as low-priority security issues, hence not
> coordinating directly with the Security Team.  Yet having them
> fixed in the next oldstable release might be welcome.

I stand by the assessment.  CVE-2026-12805 is marked no-dsa.

> [ Impact ]
> If the update is not approved, then dcmtk will continue being
> affected by the above items.

I have nothing to change here.

> [ Tests ]
> I have ensured that the patches have caused no regressions in
> bookworm using tests like piuparts and the embedded autopkgtest.
> I have also ensured that the reverse dependencies were not being
> affected by a regression in their autopkgtest if I introduce the
> patched library.

I carried similar testing for this revision.

> [ Risks ]
> Changes brought to the code are not trivial to me, but I'm
> neither imaging specialist nor security specialist (or at least
> don't consider myself as such).  Mitigation of CVE-2025-9732
> required an amendment upstream (see upstream commit 3de96da6c),
> which materializes here as patches 0013-CVE-2025-9732.patch and
> 0014-CVE-2025-9732b.patch.  That being written, all the changes
> are part of the current dcmtk 3.7.0+really3.7.0-5 available in
> unstable and forky.
> 
> I have also been mindful to make sure that the changes minimize
> alterations to the ABI.  This time, mitigating CVE-2026-5663
> also required introducing missing definition of sanitizeAETitle
> from the dcmtk library, so had to implement it directly in
> dcmnet/apps/storescp.cc.  The function is inline.  Otherwise,
> apart perhaps from the introduction of two constant static
> variables for listing admissible characters in sanitized file
> names, there should not be any breakage.

The last minute patch consists in an effective single line in a
patch straight from upstream commit.

> [ Checklist ]
>   [*] *all* changes are documented in the d/changelog
>   [*] I reviewed all changes and I approve them
>   [*] attach debdiff against the package in (old)stable
>   [*] the issue is verified as fixed in unstable

  [*] attach updated debdiff

> [ Changes ]
> 0012-CVE-2022-4981.patch is sligtly annoying to read due to the
> corresponding upstream patch also having redone the indentation.
> If I understood correctly, the change will initialize the
> noOfPeers to 0, add an extra check on a SymbolicName pointer
> deep within the CNF_HETable structure, and make sure that the
> noOfPeers cannot drop below 0 when returning the function
> result.  This corresponds to upstream commit 957fb31.
> 
> 0013-CVE-2025-2357.patch is also annoying to read, this time
> because of the amount of white space at end of lines being
> trimmed in the corresponding upstream commit, along the
> mitigation.  The actual change occurs at:
> 
>       void JlsCodec<TRAITS,STRATEGY>::DoLine(SAMPLE*)
> 
> where the extra code consists in introducing a check on the
> range, which will throw a JlsException if values are incoherent.
> This corresponds to upstram commit 3239a7915.
> 
> 0014-CVE-2025-9732.patch imports upstream commit 7ad81d69b,
> initially fixing CVE-2025-9732.
> 
> 0015-CVE-2025-9732b.patch imports upstream commit 3de96da6c,
> which amends the previous patch with a fix needed for proper
> operation of the library.
> 
> 0016-CVE-2025-14607.patch imports upstream commit 4c0e5c100,
> fixing CVE-2025-14607 by ensuring zero termination beyond the
> end of the string, necessary under certain conditions.
> 
> 0017-CVE-2025-14841.patch imports upstream commit ffb1a4a37,
> fixing CVE-2025-14841 by applying proper checks to ensure the
> pointer causing potential crashes is not NULL, or proceed
> appropriately.
> 
> 0018-CVE-2026-5663.patch
> This is the same as for trixie, but I also had to introduce a
> static const char sanitized_aetitle_charset[] and a function
> inline void sanitizeAETitle(OFString& aetitle) because it was
> not implemented in dcmtk 3.6.7, but the corresponding upstream
> patch relied on them.
> 
> 0019-CVE-2026-10194.patch imports upstream commit 0f78a4ef6,
> fixing CVE-2026-10194 about a heap buffer overflow.

0020-CVE-2026-12805.patch fixes the buffer overflow referenced
under CVE-2026-12805 by properly checking for ftell(3) error
codes.

> [ Other info ]
> The main differences with the proposed dcmtk upgrade for trixie
> are the two extra CVE: CVE-2022-4981 and CVE-2025-2357.  There
> is also the need to define sanitizeAETitle function to fix
> CVE-2026-5663, which did not exist in dcmtk 3.6.7; I used an
> inline to avoid polluting the ABI.

I have not much to add regarding other information.  I just hope
the form is readable and not too confusing this way.

Have a nice day,  :)
-- 
  .''`.  Étienne Mollier <[email protected]>
 : :' :  pgp: 8f91 b227 c7d6 f2b1 948c  8236 793c f67e 8f0d 11da
 `. `'   sent from /dev/pts/2, please excuse my verbosity
   `-
diff -Nru dcmtk-3.6.7/debian/changelog dcmtk-3.6.7/debian/changelog
--- dcmtk-3.6.7/debian/changelog        2025-02-20 21:59:03.000000000 +0100
+++ dcmtk-3.6.7/debian/changelog        2026-06-24 21:16:40.000000000 +0200
@@ -1,3 +1,23 @@
+dcmtk (3.6.7-9~deb12u4) bookworm; urgency=medium
+
+  * Team upload.
+  * 0012-CVE-2022-4981.patch: new: fix CVE-2022-4981.
+  * 0013-CVE-2025-2357.patch: new: fix CVE-2025-2357. (Closes: #1100724)
+  * *CVE-2025-9732*.patch: new.
+    These two patches fix CVE-2025-9732. (Closes: #1113993)
+  * 0016-CVE-2025-14607.patch: new: fix CVE-2025-14607. (Closes: #1122926)
+  * 0017-CVE-2025-14841.patch: new: fix CVE-2025-14841. (Closes: #1123584)
+  * 0018-CVE-2026-5663.patch: new: fix CVE-2026-5663.
+    This patch required some rework from upstream due to little changes in
+    the logic and the coding style. (Closes: #1133001)
+  * 0019-CVE-2026-10194.patch: new: fix CVE-2026-10194. (Closes: #1139181)
+  * 0020-CVE-2026-12805.patch: new: fix CVE-2026-12805.
+    This patch fixes a risk of buffer overflow by ensuring negative error
+    codes in XMLNode::parseFile are properly handled, as well a NULL
+    values. (Closes: #1140562)
+
+ -- Étienne Mollier <[email protected]>  Wed, 24 Jun 2026 21:16:40 +0200
+
 dcmtk (3.6.7-9~deb12u3) bookworm; urgency=medium
 
   * Team upload.
diff -Nru dcmtk-3.6.7/debian/patches/0012-CVE-2022-4981.patch 
dcmtk-3.6.7/debian/patches/0012-CVE-2022-4981.patch
--- dcmtk-3.6.7/debian/patches/0012-CVE-2022-4981.patch 1970-01-01 
01:00:00.000000000 +0100
+++ dcmtk-3.6.7/debian/patches/0012-CVE-2022-4981.patch 2026-06-24 
21:12:59.000000000 +0200
@@ -0,0 +1,90 @@
+commit 957fb31e5d96f51ecf5cb3422c7dc2227f8e0423
+Author: Marco Eichelberg <[email protected]>
+Date:   Tue May 24 11:22:35 2022 +0200
+
+    Fixed dcmqrscp crash caused by malformed config file.
+    
+    Fixed various issues in the dcmqrscp configuration file parser
+    that could cause application crashes when reading a malformed configuration
+    file, due to insufficient checks of the input data.
+    
+    This closes DCMTK issue #1026.
+    
+    Thanks to Zahra Mirzamomen <[email protected]> and
+    Marcel Böhme <[email protected]> for the bug report and sample 
files.
+
+diff --git a/dcmqrdb/libsrc/dcmqrcnf.cc b/dcmqrdb/libsrc/dcmqrcnf.cc
+index 686c9df2a..36a295fa2 100644
+--- a/dcmqrdb/libsrc/dcmqrcnf.cc
++++ b/dcmqrdb/libsrc/dcmqrcnf.cc
+@@ -1,6 +1,6 @@
+ /*
+  *
+- *  Copyright (C) 1993-2021, OFFIS e.V.
++ *  Copyright (C) 1993-2022, OFFIS e.V.
+  *  All rights reserved.  See COPYRIGHT file for details.
+  *
+  *  This software and supporting documentation were developed by
+@@ -447,7 +447,7 @@ int DcmQueryRetrieveConfig::readHostTable(FILE *cnffp, int 
*lineno)
+ {
+    int  error = 0,        /* error flag */
+         end = 0,          /* end flag */
+-        noOfPeers;        /* number of peers for entry */
++        noOfPeers=0;      /* number of peers for entry */
+    char rcline[512],      /* line in configuration file */
+         mnemonic[512],    /* mnemonic in line */
+         value[512],       /* parameter value */
+@@ -676,26 +676,34 @@ DcmQueryRetrieveConfigPeer 
*DcmQueryRetrieveConfig::readPeerList(char **valuehan
+    while((helpvalue = parsevalues(valuehandle)) != NULL) {
+       found = 0;
+       if (strchr(helpvalue, ',') == NULL) {   /* symbolic name */
+-         if (!CNF_HETable.noOfHostEntries) {
+-            panic("No symbolic names defined");
+-            *peers = 0;
+-            free(helpvalue);
+-            return((DcmQueryRetrieveConfigPeer *) 0);
+-         }
+-         for(i = 0; i < CNF_HETable.noOfHostEntries; i++) {
+-            if (!strcmp(CNF_HETable.HostEntries[i].SymbolicName, helpvalue)) {
+-               found = 1;
+-               break;
+-            }
+-         }
+-         if (!found) {
+-            panic("Symbolic name \"%s\" not defined", helpvalue);
+-            *peers = 0;
+-            free(helpvalue);
+-            return((DcmQueryRetrieveConfigPeer *) 0);
+-         }
++        if (!CNF_HETable.noOfHostEntries) {
++           panic("No symbolic names defined");
++           *peers = 0;
++           free(helpvalue);
++           return((DcmQueryRetrieveConfigPeer *) 0);
++        }
++        for(i = 0; i < CNF_HETable.noOfHostEntries; i++) {
++           if ((CNF_HETable.HostEntries[i].SymbolicName != NULL) && (0 == 
strcmp(CNF_HETable.HostEntries[i].SymbolicName, helpvalue))) {
++              found = 1;
++              break;
++           }
++        }
++        if (!found) {
++           panic("Symbolic name \"%s\" not defined", helpvalue);
++           *peers = 0;
++           free(helpvalue);
++           return((DcmQueryRetrieveConfigPeer *) 0);
++        }
++
++        if (CNF_HETable.HostEntries[i].noOfPeers <= 0) {
++           panic("No peers for symbolic name \"%s\" defined", helpvalue);
++           *peers = 0;
++           free(helpvalue);
++           return((DcmQueryRetrieveConfigPeer *) 0);
++        }
++
++        noOfPeers += CNF_HETable.HostEntries[i].noOfPeers;
+ 
+-         noOfPeers += CNF_HETable.HostEntries[i].noOfPeers;
+         if ((helppeer = (DcmQueryRetrieveConfigPeer *)malloc(noOfPeers * 
sizeof(DcmQueryRetrieveConfigPeer))) == NULL)
+             panic("Memory allocation 5 (%d)", noOfPeers);
+         if (noOfPeers - CNF_HETable.HostEntries[i].noOfPeers) {
diff -Nru dcmtk-3.6.7/debian/patches/0013-CVE-2025-2357.patch 
dcmtk-3.6.7/debian/patches/0013-CVE-2025-2357.patch
--- dcmtk-3.6.7/debian/patches/0013-CVE-2025-2357.patch 1970-01-01 
01:00:00.000000000 +0100
+++ dcmtk-3.6.7/debian/patches/0013-CVE-2025-2357.patch 2026-06-24 
21:12:59.000000000 +0200
@@ -0,0 +1,510 @@
+commit 3239a791542e1ea433d23aaa9e0a05a532ffabff
+Author: Marco Eichelberg <[email protected]>
+Date:   Mon Mar 3 12:33:18 2025 +0100
+
+    Fixed segfault in JPEG-LS decoder.
+    
+    Fixed a bug in the JPEG-LS decoder that led to a segmentation fault if 
invalid
+    input data was processed, due to insufficient validation of input data.
+    
+    Thanks to Ding zhengzheng <[email protected]> for the report
+    and the sample file (PoC).
+    
+    This closes DCMTK issue #1155.
+
+diff --git a/dcmjpls/libcharls/scan.h b/dcmjpls/libcharls/scan.h
+index b4dea20d8..f13098104 100644
+--- a/dcmjpls/libcharls/scan.h
++++ b/dcmjpls/libcharls/scan.h
+@@ -1,6 +1,6 @@
+-// 
+-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying 
"License.txt" for licensed use. 
+-// 
++//
++// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying 
"License.txt" for licensed use.
++//
+ 
+ #ifndef CHARLS_SCAN
+ #define CHARLS_SCAN
+@@ -11,7 +11,7 @@
+ 
+ #include "lokuptbl.h"
+ 
+-// This file contains the code for handling a "scan". Usually an image is 
encoded as a single scan. 
++// This file contains the code for handling a "scan". Usually an image is 
encoded as a single scan.
+ 
+ #include DCMTK_DIAGNOSTIC_IGNORE_CONST_EXPRESSION_WARNING
+ 
+@@ -21,10 +21,10 @@ extern OFVector<signed char> rgquant10Ll;
+ extern OFVector<signed char> rgquant12Ll;
+ extern OFVector<signed char> rgquant16Ll;
+ //
+-// Apply 
++// Apply
+ //
+ inlinehint LONG ApplySign(LONG i, LONG sign)
+-{ return (sign ^ i) - sign; }                                                 
                
++{ return (sign ^ i) - sign; }
+ 
+ 
+ 
+@@ -58,20 +58,20 @@ inlinehint LONG GetPredictedValue(LONG Ra, LONG Rb, LONG 
Rc)
+ 
+ inlinehint LONG GetPredictedValue(LONG Ra, LONG Rb, LONG Rc)
+ {
+-      // sign trick reduces the number of if statements (branches) 
++      // sign trick reduces the number of if statements (branches)
+       LONG sgn = BitWiseSign(Rb - Ra);
+ 
+-      // is Ra between Rc and Rb? 
++      // is Ra between Rc and Rb?
+       if ((sgn ^ (Rc - Ra)) < 0)
+       {
+               return Rb;
+-      } 
++      }
+       else if ((sgn ^ (Rb - Rc)) < 0)
+       {
+               return Ra;
+       }
+ 
+-      // default case, valid if Rc element of [Ra,Rb] 
++      // default case, valid if Rc element of [Ra,Rb]
+       return Ra + Rb - Rc;
+ }
+ 
+@@ -110,7 +110,7 @@ public:
+ 
+ public:
+ 
+-        JlsCodec(const TRAITS& inTraits, const JlsParameters& info) : 
STRATEGY(info), 
++        JlsCodec(const TRAITS& inTraits, const JlsParameters& info) : 
STRATEGY(info),
+         traits(inTraits),
+                 _rect(),
+                 _width(0),
+@@ -120,13 +120,13 @@ public:
+                 _RUNindex(0),
+                 _pquant(0),
+                 _bCompare(0)
+-                
++
+         {
+                 if (Info().ilv == ILV_NONE)
+                 {
+                         Info().components = 1;
+                 }
+-        }     
++        }
+ 
+ 
+         void SetPresets(const JlsCustomParameters& presets)
+@@ -135,9 +135,9 @@ public:
+ 
+                 InitParams(presets.T1 != 0 ? presets.T1 : presetDefault.T1,
+                         presets.T2 != 0 ? presets.T2 : presetDefault.T2,
+-                        presets.T3 != 0 ? presets.T3 : presetDefault.T3, 
++                        presets.T3 != 0 ? presets.T3 : presetDefault.T3,
+                         presets.RESET != 0 ? presets.RESET : 
presetDefault.RESET);
+-        }     
++        }
+ 
+ 
+         bool IsInterleaved()
+@@ -155,13 +155,13 @@ public:
+ 
+         signed char QuantizeGratientOrg(LONG Di);
+         inlinehint LONG QuantizeGratient(LONG Di)
+-        { 
++        {
+                 ASSERT(QuantizeGratientOrg(Di) == *(_pquant + Di));
+-                return *(_pquant + Di); 
++                return *(_pquant + Di);
+         }
+ 
+         void InitQuantizationLUT();
+-      
++
+         LONG DecodeValue(LONG k, LONG limit, LONG qbpp);
+         inlinehint void EncodeMappedValue(LONG k, LONG mappedError, LONG 
limit);
+ 
+@@ -216,27 +216,27 @@ public:
+         {
+               LONG sign               = BitWiseSign(Qs);
+               JlsContext& ctx = _contexts[ApplySign(Qs, sign)];
+-              LONG k                  = ctx.GetGolomb();      
+-              LONG Px                 = traits.CorrectPrediction(pred + 
ApplySign(ctx.C, sign));    
++              LONG k                  = ctx.GetGolomb();
++              LONG Px                 = traits.CorrectPrediction(pred + 
ApplySign(ctx.C, sign));
+ 
+               LONG ErrVal;
+               const Code& code                = 
decodingTables[k].Get(STRATEGY::PeekByte());
+               if (code.GetLength() != 0)
+               {
+                       STRATEGY::Skip(code.GetLength());
+-                      ErrVal = code.GetValue(); 
++                      ErrVal = code.GetValue();
+                       ASSERT(ABS(ErrVal) < 65535);
+               }
+               else
+               {
+-                      ErrVal = UnMapErrVal(DecodeValue(k, traits.LIMIT, 
traits.qbpp)); 
++                      ErrVal = UnMapErrVal(DecodeValue(k, traits.LIMIT, 
traits.qbpp));
+                       if (ABS(ErrVal) > 65535)
+                               throw JlsException(InvalidCompressedData);
+-              }       
++              }
+               ErrVal = ErrVal ^ ((traits.NEAR == 0) ? 
ctx.GetErrorCorrection(k) : 0);
+-              ctx.UpdateVariables(ErrVal, traits.NEAR, traits.RESET); 
++              ctx.UpdateVariables(ErrVal, traits.NEAR, traits.RESET);
+               ErrVal = ApplySign(ErrVal, sign);
+-              return traits.ComputeReconstructedSample(Px, ErrVal); 
++              return traits.ComputeReconstructedSample(Px, ErrVal);
+         }
+ 
+ 
+@@ -245,7 +245,7 @@ public:
+               LONG sign               = BitWiseSign(Qs);
+               JlsContext& ctx = _contexts[ApplySign(Qs, sign)];
+               LONG k                  = ctx.GetGolomb();
+-              LONG Px                 = traits.CorrectPrediction(pred + 
ApplySign(ctx.C, sign));      
++              LONG Px                 = traits.CorrectPrediction(pred + 
ApplySign(ctx.C, sign));
+ 
+               LONG ErrVal             = traits.ComputeErrVal(ApplySign(x - 
Px, sign));
+ 
+@@ -270,16 +270,16 @@ public:
+       size_t  DecodeScan(void* rawData, const JlsRect& size, BYTE **buf, 
size_t *buf_size, size_t offset, bool bCompare);
+ 
+ protected:
+-      // codec parameters 
++      // codec parameters
+       TRAITS traits;
+       JlsRect _rect;
+       int _width;
+-      LONG T1;        
++      LONG T1;
+       LONG T2;
+-      LONG T3; 
++      LONG T3;
+ 
+       // compression context
+-      JlsContext _contexts[365];      
++      JlsContext _contexts[365];
+       CContextRunMode _contextRunmode[2];
+       LONG _RUNindex;
+       PIXEL* _previousLine; // previous line ptr
+@@ -309,7 +309,7 @@ CTable InitTable(LONG k)
+       CTable table;
+       short nerr;
+       for (nerr = 0; ; nerr++)
+-      {               
++      {
+               // Q is not used when k != 0
+               LONG merrval = GetMappedErrVal(nerr);//, k, -1);
+               OFPair<LONG, LONG> paircode = CreateEncodedValue(k, merrval);
+@@ -321,7 +321,7 @@ CTable InitTable(LONG k)
+       }
+ 
+       for (nerr = -1; ; nerr--)
+-      {               
++      {
+               // Q is not used when k != 0
+               LONG merrval = GetMappedErrVal(nerr);//, k, -1);
+               OFPair<LONG, LONG> paircode = CreateEncodedValue(k, merrval);
+@@ -364,7 +364,7 @@ inlinehint void 
JlsCodec<TRAITS,STRATEGY>::EncodeMappedValue(LONG k, LONG mapped
+               if (highbits + 1 > 31)
+               {
+                       STRATEGY::AppendToBitStream(0, highbits / 2);
+-                      highbits = highbits - highbits / 2;                     
                                                                                
++                      highbits = highbits - highbits / 2;
+               }
+               STRATEGY::AppendToBitStream(1, highbits + 1);
+               STRATEGY::AppendToBitStream((mappedError & ((1 << k) - 1)), k);
+@@ -374,11 +374,11 @@ inlinehint void 
JlsCodec<TRAITS,STRATEGY>::EncodeMappedValue(LONG k, LONG mapped
+       if (limit - traits.qbpp > 31)
+       {
+               STRATEGY::AppendToBitStream(0, 31);
+-              STRATEGY::AppendToBitStream(1, limit - traits.qbpp - 31);       
                
++              STRATEGY::AppendToBitStream(1, limit - traits.qbpp - 31);
+       }
+       else
+       {
+-              STRATEGY::AppendToBitStream(1, limit - traits.qbpp);            
        
++              STRATEGY::AppendToBitStream(1, limit - traits.qbpp);
+       }
+       STRATEGY::AppendToBitStream((mappedError - 1) & ((1 << traits.qbpp) - 
1), traits.qbpp);
+ }
+@@ -389,33 +389,33 @@ inlinehint void 
JlsCodec<TRAITS,STRATEGY>::EncodeMappedValue(LONG k, LONG mapped
+ template<class TRAITS, class STRATEGY>
+ void JlsCodec<TRAITS,STRATEGY>::InitQuantizationLUT()
+ {
+-      // for lossless mode with default parameters, we have precomputed te 
luts for bitcounts 8,10,12 and 16 
++      // for lossless mode with default parameters, we have precomputed te 
luts for bitcounts 8,10,12 and 16
+       if (traits.NEAR == 0 && traits.MAXVAL == (1 << traits.bpp) - 1)
+       {
+               JlsCustomParameters presets = ComputeDefault(traits.MAXVAL, 
traits.NEAR);
+               if (presets.T1 == T1 && presets.T2 == T2 && presets.T3 == T3)
+               {
+-                      if (traits.bpp == 8) 
++                      if (traits.bpp == 8)
+                       {
+-                              _pquant = &rgquant8Ll[rgquant8Ll.size() / 2 ]; 
++                              _pquant = &rgquant8Ll[rgquant8Ll.size() / 2 ];
+                               return;
+                       }
+-                      if (traits.bpp == 10) 
++                      if (traits.bpp == 10)
+                       {
+-                              _pquant = &rgquant10Ll[rgquant10Ll.size() / 2 
]; 
++                              _pquant = &rgquant10Ll[rgquant10Ll.size() / 2 ];
+                               return;
+-                      }                       
+-                      if (traits.bpp == 12) 
++                      }
++                      if (traits.bpp == 12)
+                       {
+-                              _pquant = &rgquant12Ll[rgquant12Ll.size() / 2 
]; 
++                              _pquant = &rgquant12Ll[rgquant12Ll.size() / 2 ];
+                               return;
+-                      }                       
+-                      if (traits.bpp == 16) 
++                      }
++                      if (traits.bpp == 16)
+                       {
+-                              _pquant = &rgquant16Ll[rgquant16Ll.size() / 2 
]; 
++                              _pquant = &rgquant16Ll[rgquant16Ll.size() / 2 ];
+                               return;
+-                      }                       
+-              }       
++                      }
++              }
+       }
+ 
+       LONG RANGE = 1 << traits.bpp;
+@@ -453,7 +453,7 @@ template<class TRAITS, class STRATEGY>
+ LONG JlsCodec<TRAITS,STRATEGY>::DecodeRIError(CContextRunMode& ctx)
+ {
+       LONG k = ctx.GetGolomb();
+-      LONG EMErrval = DecodeValue(k, traits.LIMIT - J[_RUNindex]-1, 
traits.qbpp);     
++      LONG EMErrval = DecodeValue(k, traits.LIMIT - J[_RUNindex]-1, 
traits.qbpp);
+       LONG Errval = ctx.ComputeErrVal(EMErrval + ctx._nRItype, k);
+       ctx.UpdateVariables(Errval, EMErrval);
+       return Errval;
+@@ -466,7 +466,7 @@ void 
JlsCodec<TRAITS,STRATEGY>::EncodeRIError(CContextRunMode& ctx, LONG Errval)
+ {
+       LONG k                  = ctx.GetGolomb();
+       bool map                = ctx.ComputeMap(Errval, k);
+-      LONG EMErrval   = 2 * ABS(Errval) - ctx._nRItype - map; 
++      LONG EMErrval   = 2 * ABS(Errval) - ctx._nRItype - map;
+ 
+       ASSERT(Errval == ctx.ComputeErrVal(EMErrval + ctx._nRItype, k));
+       EncodeMappedValue(k, EMErrval, traits.LIMIT-J[_RUNindex]-1);
+@@ -476,7 +476,7 @@ void 
JlsCodec<TRAITS,STRATEGY>::EncodeRIError(CContextRunMode& ctx, LONG Errval)
+ 
+ template<class TRAITS, class STRATEGY>
+ Triplet<OFTypename TRAITS::SAMPLE> 
JlsCodec<TRAITS,STRATEGY>::DecodeRIPixel(Triplet<SAMPLE> Ra, Triplet<SAMPLE> Rb)
+-{ 
++{
+       LONG Errval1 = DecodeRIError(_contextRunmode[0]);
+       LONG Errval2 = DecodeRIError(_contextRunmode[0]);
+       LONG Errval3 = DecodeRIError(_contextRunmode[0]);
+@@ -513,18 +513,18 @@ Triplet<OFTypename TRAITS::SAMPLE> 
JlsCodec<TRAITS,STRATEGY>::EncodeRIPixel(Trip
+ template<class TRAITS, class STRATEGY>
+ void JlsCodec<TRAITS,STRATEGY>::EncodeRunPixels(LONG runLength, bool 
endOfLine)
+ {
+-      while (runLength >= LONG(1 << J[_RUNindex])) 
++      while (runLength >= LONG(1 << J[_RUNindex]))
+       {
+               STRATEGY::AppendOnesToBitStream(1);
+               runLength = runLength - LONG(1 << J[_RUNindex]);
+               IncrementRunIndex();
+       }
+ 
+-      if (endOfLine) 
++      if (endOfLine)
+       {
+-              if (runLength != 0) 
++              if (runLength != 0)
+               {
+-                      STRATEGY::AppendOnesToBitStream(1);     
++                      STRATEGY::AppendOnesToBitStream(1);
+               }
+       }
+       else
+@@ -556,7 +556,7 @@ LONG JlsCodec<TRAITS,STRATEGY>::DecodeRunPixels(PIXEL Ra, 
PIXEL* startPos, LONG
+ 
+       if (index != cpixelMac)
+       {
+-              // incomplete run       
++              // incomplete run
+               index += (J[_RUNindex] > 0) ? STRATEGY::ReadValue(J[_RUNindex]) 
: 0;
+       }
+ 
+@@ -566,7 +566,7 @@ LONG JlsCodec<TRAITS,STRATEGY>::DecodeRunPixels(PIXEL Ra, 
PIXEL* startPos, LONG
+       for (LONG i = 0; i < index; ++i)
+       {
+               startPos[i] = Ra;
+-      }       
++      }
+ 
+       return index;
+ }
+@@ -582,7 +582,7 @@ LONG JlsCodec<TRAITS,STRATEGY>::DoRunMode(LONG index, 
EncoderStrategy*)
+ 
+       LONG runLength = 0;
+ 
+-      while (traits.IsNear(ptypeCurX[runLength],Ra)) 
++      while (traits.IsNear(ptypeCurX[runLength],Ra))
+       {
+               ptypeCurX[runLength] = Ra;
+               runLength++;
+@@ -629,14 +629,24 @@ void JlsCodec<TRAITS,STRATEGY>::DoLine(SAMPLE*)
+       LONG index = 0;
+       LONG Rb = _previousLine[index-1];
+       LONG Rd = _previousLine[index];
++    LONG RANGE_UPPER = 1 << traits.bpp;
++    LONG RANGE_LOWER = - RANGE_UPPER;
+ 
+       while(index < _width)
+-      {       
++      {
+               LONG Ra = _currentLine[index -1];
+               LONG Rc = Rb;
+               Rb = Rd;
+               Rd = _previousLine[index + 1];
+ 
++        // make sure that values are not out of range
++        if (  (Rd - Rb < RANGE_LOWER) || (Rd - Rb > RANGE_UPPER)
++           || (Rb - Rc < RANGE_LOWER) || (Rb - Rc > RANGE_UPPER)
++           || (Rc - Ra < RANGE_LOWER) || (Rc - Ra > RANGE_UPPER))
++        {
++            throw JlsException(InvalidCompressedData);
++        }
++
+               LONG Qs = ComputeContextID(QuantizeGratient(Rd - Rb), 
QuantizeGratient(Rb - Rc), QuantizeGratient(Rc - Ra));
+ 
+               if (Qs != 0)
+@@ -648,8 +658,8 @@ void JlsCodec<TRAITS,STRATEGY>::DoLine(SAMPLE*)
+               {
+                       index += DoRunMode(index, (STRATEGY*)(NULL));
+                       Rb = _previousLine[index-1];
+-                      Rd = _previousLine[index];      
+-              }                               
++                      Rd = _previousLine[index];
++              }
+       }
+ }
+ 
+@@ -661,7 +671,7 @@ void JlsCodec<TRAITS,STRATEGY>::DoLine(Triplet<SAMPLE>*)
+ {
+       LONG index = 0;
+       while(index < _width)
+-      {               
++      {
+               Triplet<SAMPLE> Ra = _currentLine[index -1];
+               Triplet<SAMPLE> Rc = _previousLine[index-1];
+               Triplet<SAMPLE> Rb = _previousLine[index];
+@@ -671,7 +681,7 @@ void JlsCodec<TRAITS,STRATEGY>::DoLine(Triplet<SAMPLE>*)
+               LONG Qs2 = ComputeContextID(QuantizeGratient(Rd.v2 - Rb.v2), 
QuantizeGratient(Rb.v2 - Rc.v2), QuantizeGratient(Rc.v2 - Ra.v2));
+               LONG Qs3 = ComputeContextID(QuantizeGratient(Rd.v3 - Rb.v3), 
QuantizeGratient(Rb.v3 - Rc.v3), QuantizeGratient(Rc.v3 - Ra.v3));
+ 
+-              
++
+               if (Qs1 == 0 && Qs2 == 0 && Qs3 == 0)
+               {
+                       index += DoRunMode(index, (STRATEGY*)(NULL));
+@@ -684,19 +694,19 @@ void JlsCodec<TRAITS,STRATEGY>::DoLine(Triplet<SAMPLE>*)
+                       Rx.v3 = DoRegular(Qs3, _currentLine[index].v3, 
GetPredictedValue(Ra.v3, Rb.v3, Rc.v3), (STRATEGY*)(NULL));
+                       _currentLine[index] = Rx;
+                       index++;
+-              }       
++              }
+       }
+ }
+ 
+ 
+-// DoScan: Encodes or decodes a scan. 
++// DoScan: Encodes or decodes a scan.
+ // In ILV_SAMPLE mode, multiple components are handled in DoLine
+ // In ILV_LINE mode, a call do DoLine is made for every component
+-// In ILV_NONE mode, DoScan is called for each component 
++// In ILV_NONE mode, DoScan is called for each component
+ 
+ template<class TRAITS, class STRATEGY>
+ void JlsCodec<TRAITS,STRATEGY>::DoScan(BYTE **ptr, size_t *size, size_t 
offset)
+-{             
++{
+       _width = Info().width;
+ 
+       STRATEGY::Init(ptr, size, offset);
+@@ -706,11 +716,11 @@ void JlsCodec<TRAITS,STRATEGY>::DoScan(BYTE **ptr, 
size_t *size, size_t offset)
+ 
+       OFVector<PIXEL> vectmp(2 * components * pixelstride);
+       OFVector<LONG> rgRUNindex(components);
+-      
++
+       for (LONG line = 0; line < Info().height; ++line)
+       {
+-              _previousLine                   = &vectmp[1];   
+-              _currentLine                    = &vectmp[1 + components * 
pixelstride];        
++              _previousLine                   = &vectmp[1];
++              _currentLine                    = &vectmp[1 + components * 
pixelstride];
+               if ((line & 1) == 1)
+               {
+                       PIXEL *tmp = _previousLine;
+@@ -724,17 +734,17 @@ void JlsCodec<TRAITS,STRATEGY>::DoScan(BYTE **ptr, 
size_t *size, size_t offset)
+               for (int component = 0; component < components; ++component)
+               {
+                       _RUNindex = rgRUNindex[component];
+-              
++
+                       // initialize edge pixels used for prediction
+                       _previousLine[_width]   = _previousLine[_width - 1];
+                       _currentLine[-1]                = _previousLine[0];
+                       DoLine((PIXEL*) NULL); // dummy arg for overload 
resolution
+-      
++
+                       rgRUNindex[component] = _RUNindex;
+                       _previousLine += pixelstride;
+                       _currentLine += pixelstride;
+               }
+-              
++
+               if (_rect.Y <= line && line < _rect.Y + _rect.Height)
+               {
+                       STRATEGY::OnLineEnd(_rect.Width, _currentLine + _rect.X 
- (components * pixelstride), pixelstride);
+@@ -754,7 +764,7 @@ ProcessLine* 
JlsCodec<TRAITS,STRATEGY>::CreateProcess(void* pvoidOut)
+               return new PostProcesSingleComponent(pvoidOut, Info(), 
sizeof(typename TRAITS::PIXEL));
+ 
+       if (Info().colorTransform == 0)
+-              return new ProcessTransformed<TransformNone<OFTypename 
TRAITS::SAMPLE> >(pvoidOut, Info(), TransformNone<SAMPLE>()); 
++              return new ProcessTransformed<TransformNone<OFTypename 
TRAITS::SAMPLE> >(pvoidOut, Info(), TransformNone<SAMPLE>());
+ 
+       if (Info().bitspersample == sizeof(SAMPLE)*8)
+       {
+@@ -765,7 +775,7 @@ ProcessLine* 
JlsCodec<TRAITS,STRATEGY>::CreateProcess(void* pvoidOut)
+                       case COLORXFORM_HP3 : return new 
ProcessTransformed<TransformHp3<SAMPLE> >(pvoidOut, Info(), 
TransformHp3<SAMPLE>()); break;
+                       default: throw JlsException(UnsupportedColorTransform);
+               }
+-      } 
++      }
+       else if (Info().bitspersample > 8)
+       {
+               int shift = 16 - Info().bitspersample;
+@@ -796,7 +806,7 @@ size_t JlsCodec<TRAITS,STRATEGY>::EncodeScan(const void* 
rawData, BYTE **ptr, si
+       }
+ 
+       DoScan(ptr, size, offset);
+-      
++
+       return  STRATEGY::GetLength();
+ 
+ }
+@@ -827,7 +837,7 @@ size_t JlsCodec<TRAITS,STRATEGY>::DecodeScan(void* 
rawData, const JlsRect& rect,
+       _rect = rect;
+ 
+       DoScan(ptr, size, offset + readBytes);
+-      
++
+       return STRATEGY::GetCurBytePos() - (*ptr + offset);
+ }
+ 
diff -Nru dcmtk-3.6.7/debian/patches/0014-CVE-2025-9732.patch 
dcmtk-3.6.7/debian/patches/0014-CVE-2025-9732.patch
--- dcmtk-3.6.7/debian/patches/0014-CVE-2025-9732.patch 1970-01-01 
01:00:00.000000000 +0100
+++ dcmtk-3.6.7/debian/patches/0014-CVE-2025-9732.patch 2026-06-24 
21:12:59.000000000 +0200
@@ -0,0 +1,398 @@
+commit 7ad81d69b19714936e18ea5fc74edaeb9f021ce7
+Author: Joerg Riesmeier <[email protected]>
+Date:   Fri Aug 15 13:35:40 2025 +0200
+
+    Fixed issue with invalid "YBR_FULL" DICOM images.
+    
+    Fixed an issue when processing an invalid DICOM image with a Photometric
+    Interpretation of "YBR_FULL" and a Planar Configuration of "1" where
+    the number of pixels stored does not match the expected number of pixels
+    (much too less). Now, the pixel data of such an image is not processed
+    at all, but an empty image (black pixels) is created instead. The user
+    is warned about this by an appropriate log message.
+    
+    Thanks to Ding zhengzheng <[email protected]> for the report
+    and the sample file (PoC).
+
+--- dcmtk.orig/dcmimage/include/dcmtk/dcmimage/dicopxt.h
++++ dcmtk/dcmimage/include/dcmtk/dcmimage/dicopxt.h
+@@ -574,7 +574,11 @@
+                 {
+                     /* erase empty part of the buffer (=blacken the 
background) */
+                     if (InputCount < Count)
+-                        OFBitmanipTemplate<T>::zeroMem(Data[j] + InputCount, 
Count - InputCount);
++                    {
++                        const size_t count = (Count - InputCount);
++                        DCMIMAGE_TRACE("filing empty part of the intermediate 
pixel data (" << count << " pixels) of plane " << j << " with value = 0");
++                        OFBitmanipTemplate<T>::zeroMem(Data[j] + InputCount, 
count);
++                    }
+                 } else {
+                     DCMIMAGE_DEBUG("cannot allocate memory buffer for 'Data[" 
<< j << "]' in DiColorPixelTemplate::Init()");
+                     result = 0;     // at least one buffer could not be 
allocated!
+--- dcmtk.orig/dcmimage/include/dcmtk/dcmimage/diybrpxt.h
++++ dcmtk/dcmimage/include/dcmtk/dcmimage/diybrpxt.h
+@@ -1,6 +1,6 @@
+ /*
+  *
+- *  Copyright (C) 1998-2016, OFFIS e.V.
++ *  Copyright (C) 1998-2025, OFFIS e.V.
+  *  All rights reserved.  See COPYRIGHT file for details.
+  *
+  *  This software and supporting documentation were developed by
+@@ -24,6 +24,7 @@
+ #define DIYBRPXT_H
+ 
+ #include "dcmtk/config/osconfig.h"
++#include "dcmtk/ofstd/ofbmanip.h"
+ 
+ #include "dcmtk/dcmimage/dicopxt.h"
+ #include "dcmtk/dcmimgle/diinpx.h"  /* gcc 3.4 needs this */
+@@ -90,179 +91,189 @@
+             // use the number of input pixels derived from the length of the 
'PixelData'
+             // attribute), but not more than the size of the intermediate 
buffer
+             const unsigned long count = (this->InputCount < this->Count) ? 
this->InputCount : this->Count;
+-            if (rgb)    /* convert to RGB model */
++            // make sure that there is sufficient input data (for planar 
pixel data)
++            if (!this->PlanarConfiguration || (count >= planeSize * 3 /* 
number of planes */))
+             {
+-                T2 *r = this->Data[0];
+-                T2 *g = this->Data[1];
+-                T2 *b = this->Data[2];
+-                const T2 maxvalue = OFstatic_cast(T2, 
DicomImageClass::maxval(bits));
+-                DiPixelRepresentationTemplate<T1> rep;
+-                if (bits == 8 && !rep.isSigned())          // only for 
unsigned 8 bit
++                if (rgb)    /* convert to RGB model */
+                 {
+-                    Sint16 rcr_tab[256];
+-                    Sint16 gcb_tab[256];
+-                    Sint16 gcr_tab[256];
+-                    Sint16 bcb_tab[256];
+-                    const double r_const = 0.7010 * OFstatic_cast(double, 
maxvalue);
+-                    const double g_const = 0.5291 * OFstatic_cast(double, 
maxvalue);
+-                    const double b_const = 0.8859 * OFstatic_cast(double, 
maxvalue);
+-                    unsigned long l;
+-                    for (l = 0; l < 256; ++l)
++                    T2 *r = this->Data[0];
++                    T2 *g = this->Data[1];
++                    T2 *b = this->Data[2];
++                    const T2 maxvalue = OFstatic_cast(T2, 
DicomImageClass::maxval(bits));
++                    DiPixelRepresentationTemplate<T1> rep;
++                    if (bits == 8 && !rep.isSigned())          // only for 
unsigned 8 bit
+                     {
+-                        rcr_tab[l] = OFstatic_cast(Sint16, 1.4020 * 
OFstatic_cast(double, l) - r_const);
+-                        gcb_tab[l] = OFstatic_cast(Sint16, 0.3441 * 
OFstatic_cast(double, l));
+-                        gcr_tab[l] = OFstatic_cast(Sint16, 0.7141 * 
OFstatic_cast(double, l) - g_const);
+-                        bcb_tab[l] = OFstatic_cast(Sint16, 1.7720 * 
OFstatic_cast(double, l) - b_const);
+-                    }
+-                    Sint32 sr;
+-                    Sint32 sg;
+-                    Sint32 sb;
+-                    if (this->PlanarConfiguration)
+-                    {
+-/*
+-                        const T1 *y = pixel;
+-                        const T1 *cb = y + this->InputCount;
+-                        const T1 *cr = cb + this->InputCount;
+-                        for (i = count; i != 0; --i, ++y, ++cb, ++cr)
++                        Sint16 rcr_tab[256];
++                        Sint16 gcb_tab[256];
++                        Sint16 gcr_tab[256];
++                        Sint16 bcb_tab[256];
++                        const double r_const = 0.7010 * OFstatic_cast(double, 
maxvalue);
++                        const double g_const = 0.5291 * OFstatic_cast(double, 
maxvalue);
++                        const double b_const = 0.8859 * OFstatic_cast(double, 
maxvalue);
++                        unsigned long l;
++                        for (l = 0; l < 256; ++l)
+                         {
+-                            sr = OFstatic_cast(Sint32, *y) + 
OFstatic_cast(Sint32, rcr_tab[*cr]);
+-                            sg = OFstatic_cast(Sint32, *y) - 
OFstatic_cast(Sint32, gcb_tab[*cb]) - OFstatic_cast(Sint32, gcr_tab[*cr]);
+-                            sb = OFstatic_cast(Sint32, *y) + 
OFstatic_cast(Sint32, bcb_tab[*cb]);
+-                            *(r++) = (sr < 0) ? 0 : (sr > 
OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr);
+-                            *(g++) = (sg < 0) ? 0 : (sg > 
OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg);
+-                            *(b++) = (sb < 0) ? 0 : (sb > 
OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb);
++                            rcr_tab[l] = OFstatic_cast(Sint16, 1.4020 * 
OFstatic_cast(double, l) - r_const);
++                            gcb_tab[l] = OFstatic_cast(Sint16, 0.3441 * 
OFstatic_cast(double, l));
++                            gcr_tab[l] = OFstatic_cast(Sint16, 0.7141 * 
OFstatic_cast(double, l) - g_const);
++                            bcb_tab[l] = OFstatic_cast(Sint16, 1.7720 * 
OFstatic_cast(double, l) - b_const);
+                         }
++                        Sint32 sr;
++                        Sint32 sg;
++                        Sint32 sb;
++                        if (this->PlanarConfiguration)
++                        {
++/*
++                            const T1 *y = pixel;
++                            const T1 *cb = y + this->InputCount;
++                            const T1 *cr = cb + this->InputCount;
++                            for (i = count; i != 0; --i, ++y, ++cb, ++cr)
++                            {
++                                sr = OFstatic_cast(Sint32, *y) + 
OFstatic_cast(Sint32, rcr_tab[*cr]);
++                                sg = OFstatic_cast(Sint32, *y) - 
OFstatic_cast(Sint32, gcb_tab[*cb]) - OFstatic_cast(Sint32, gcr_tab[*cr]);
++                                sb = OFstatic_cast(Sint32, *y) + 
OFstatic_cast(Sint32, bcb_tab[*cb]);
++                                *(r++) = (sr < 0) ? 0 : (sr > 
OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr);
++                                *(g++) = (sg < 0) ? 0 : (sg > 
OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg);
++                                *(b++) = (sb < 0) ? 0 : (sb > 
OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb);
++                            }
+ */
+-                        const T1 *y = pixel;
+-                        const T1 *cb = y + planeSize;
+-                        const T1 *cr = cb + planeSize;
+-                        unsigned long i = count;
+-                        while (i != 0)
++                            const T1 *y = pixel;
++                            const T1 *cb = y + planeSize;
++                            const T1 *cr = cb + planeSize;
++                            unsigned long i = count;
++                            while (i != 0)
++                            {
++                                /* convert a single frame */
++                                for (l = planeSize; (l != 0) && (i != 0); 
--l, --i, ++y, ++cb, ++cr)
++                                {
++                                    sr = OFstatic_cast(Sint32, *y) + 
OFstatic_cast(Sint32, rcr_tab[*cr]);
++                                    sg = OFstatic_cast(Sint32, *y) - 
OFstatic_cast(Sint32, gcb_tab[*cb]) - OFstatic_cast(Sint32, gcr_tab[*cr]);
++                                    sb = OFstatic_cast(Sint32, *y) + 
OFstatic_cast(Sint32, bcb_tab[*cb]);
++                                    *(r++) = (sr < 0) ? 0 : (sr > 
OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr);
++                                    *(g++) = (sg < 0) ? 0 : (sg > 
OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg);
++                                    *(b++) = (sb < 0) ? 0 : (sb > 
OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb);
++                                }
++                                /* jump to next frame start (skip 2 planes) */
++                                y += 2 * planeSize;
++                                cb += 2 * planeSize;
++                                cr += 2 * planeSize;
++                            }
++                        }
++                        else
+                         {
+-                            /* convert a single frame */
+-                            for (l = planeSize; (l != 0) && (i != 0); --l, 
--i, ++y, ++cb, ++cr)
++                            const T1 *p = pixel;
++                            T1 y;
++                            T1 cb;
++                            T1 cr;
++                            unsigned long i;
++                            for (i = count; i != 0; --i)
+                             {
+-                                sr = OFstatic_cast(Sint32, *y) + 
OFstatic_cast(Sint32, rcr_tab[OFstatic_cast(Uint32, *cr)]);
+-                                sg = OFstatic_cast(Sint32, *y) - 
OFstatic_cast(Sint32, gcb_tab[OFstatic_cast(Uint32, *cb)]) - 
OFstatic_cast(Sint32, gcr_tab[OFstatic_cast(Uint32, *cr)]);
+-                                sb = OFstatic_cast(Sint32, *y) + 
OFstatic_cast(Sint32, bcb_tab[OFstatic_cast(Uint32, *cb)]);
++                                y  = *(p++);
++                                cb = *(p++);
++                                cr = *(p++);
++                                sr = OFstatic_cast(Sint32, y) + 
OFstatic_cast(Sint32, rcr_tab[cr]);
++                                sg = OFstatic_cast(Sint32, y) - 
OFstatic_cast(Sint32, gcb_tab[cb]) - OFstatic_cast(Sint32, gcr_tab[cr]);
++                                sb = OFstatic_cast(Sint32, y) + 
OFstatic_cast(Sint32, bcb_tab[cb]);
+                                 *(r++) = (sr < 0) ? 0 : (sr > 
OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr);
+                                 *(g++) = (sg < 0) ? 0 : (sg > 
OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg);
+                                 *(b++) = (sb < 0) ? 0 : (sb > 
OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb);
+                             }
+-                            /* jump to next frame start (skip 2 planes) */
+-                            y += 2 * planeSize;
+-                            cb += 2 * planeSize;
+-                            cr += 2 * planeSize;
+                         }
+                     }
+                     else
+                     {
+-                        const T1 *p = pixel;
+-                        T1 y;
+-                        T1 cb;
+-                        T1 cr;
+-                        unsigned long i;
+-                        for (i = count; i != 0; --i)
++                        if (this->PlanarConfiguration)
++                        {
++/*
++                            const T1 *y = pixel;
++                            const T1 *cb = y + this->InputCount;
++                            const T1 *cr = cb + this->InputCount;
++                            for (i = count; i != 0; --i)
++                                convertValue(*(r++), *(g++), *(b++), 
removeSign(*(y++), offset), removeSign(*(cb++), offset),
++                                    removeSign(*(cr++), offset), maxvalue);
++*/
++                            unsigned long l;
++                            unsigned long i = count;
++                            const T1 *y = pixel;
++                            const T1 *cb = y + planeSize;
++                            const T1 *cr = cb + planeSize;
++                            while (i != 0)
++                            {
++                                /* convert a single frame */
++                                for (l = planeSize; (l != 0) && (i != 0); 
--l, --i)
++                                {
++                                    convertValue(*(r++), *(g++), *(b++), 
removeSign(*(y++), offset), removeSign(*(cb++), offset),
++                                        removeSign(*(cr++), offset), 
maxvalue);
++                                }
++                                /* jump to next frame start (skip 2 planes) */
++                                y += 2 * planeSize;
++                                cb += 2 * planeSize;
++                                cr += 2 * planeSize;
++                            }
++                        }
++                        else
+                         {
+-                            y  = *(p++);
+-                            cb = *(p++);
+-                            cr = *(p++);
+-                            sr = OFstatic_cast(Sint32, y) + 
OFstatic_cast(Sint32, rcr_tab[OFstatic_cast(Uint32, cr)]);
+-                            sg = OFstatic_cast(Sint32, y) - 
OFstatic_cast(Sint32, gcb_tab[OFstatic_cast(Uint32, cb)]) - 
OFstatic_cast(Sint32, gcr_tab[OFstatic_cast(Uint32, cr)]);
+-                            sb = OFstatic_cast(Sint32, y) + 
OFstatic_cast(Sint32, bcb_tab[OFstatic_cast(Uint32, cb)]);
+-                            *(r++) = (sr < 0) ? 0 : (sr > 
OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr);
+-                            *(g++) = (sg < 0) ? 0 : (sg > 
OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg);
+-                            *(b++) = (sb < 0) ? 0 : (sb > 
OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb);
++                            const T1 *p = pixel;
++                            T2 y;
++                            T2 cb;
++                            T2 cr;
++                            unsigned long i;
++                            for (i = count; i != 0; --i)
++                            {
++                                y = removeSign(*(p++), offset);
++                                cb = removeSign(*(p++), offset);
++                                cr = removeSign(*(p++), offset);
++                                convertValue(*(r++), *(g++), *(b++), y, cb, 
cr, maxvalue);
++                            }
+                         }
+                     }
+-                }
+-                else
+-                {
++                } else {    /* retain YCbCr model */
++                    const T1 *p = pixel;
+                     if (this->PlanarConfiguration)
+                     {
+-/*
+-                        const T1 *y = pixel;
+-                        const T1 *cb = y + this->InputCount;
+-                        const T1 *cr = cb + this->InputCount;
+-                        for (i = count; i != 0; --i)
+-                            convertValue(*(r++), *(g++), *(b++), 
removeSign(*(y++), offset), removeSign(*(cb++), offset),
+-                                removeSign(*(cr++), offset), maxvalue);
+-*/
++    /*
++                        T2 *q;
++                        // number of pixels to be skipped (only applicable if 
'PixelData' contains more
++                        // pixels than expected)
++                        const unsigned long skip = (this->InputCount > 
this->Count) ? (this->InputCount - this->Count) : 0;
++                        for (int j = 0; j < 3; ++j)
++                        {
++                            q = this->Data[j];
++                            for (i = count; i != 0; --i)
++                                *(q++) = removeSign(*(p++), offset);
++                            // skip to beginning of next plane
++                            p += skip;
++                        }
++    */
+                         unsigned long l;
+-                        unsigned long i = count;
+-                        const T1 *y = pixel;
+-                        const T1 *cb = y + planeSize;
+-                        const T1 *cr = cb + planeSize;
+-                        while (i != 0)
++                        unsigned long i = 0;
++                        while (i < count)
+                         {
+-                            /* convert a single frame */
+-                            for (l = planeSize; (l != 0) && (i != 0); --l, 
--i)
++                            /* store current pixel index */
++                            const unsigned long iStart = i;
++                            for (int j = 0; j < 3; ++j)
+                             {
+-                                convertValue(*(r++), *(g++), *(b++), 
removeSign(*(y++), offset), removeSign(*(cb++), offset),
+-                                    removeSign(*(cr++), offset), maxvalue);
++                                /* convert a single plane */
++                                for (l = planeSize, i = iStart; (l != 0) && 
(i < count); --l, ++i)
++                                    this->Data[j][i] = removeSign(*(p++), 
offset);
+                             }
+-                            /* jump to next frame start (skip 2 planes) */
+-                            y += 2 * planeSize;
+-                            cb += 2 * planeSize;
+-                            cr += 2 * planeSize;
+                         }
+                     }
+                     else
+                     {
+-                        const T1 *p = pixel;
+-                        T2 y;
+-                        T2 cb;
+-                        T2 cr;
++                        int j;
+                         unsigned long i;
+-                        for (i = count; i != 0; --i)
+-                        {
+-                            y = removeSign(*(p++), offset);
+-                            cb = removeSign(*(p++), offset);
+-                            cr = removeSign(*(p++), offset);
+-                            convertValue(*(r++), *(g++), *(b++), y, cb, cr, 
maxvalue);
+-                        }
++                        for (i = 0; i < count; ++i)                           
  /* for all pixel ... */
++                            for (j = 0; j < 3; ++j)
++                                this->Data[j][i] = removeSign(*(p++), 
offset);  /* ... copy planes */
+                     }
+                 }
+-            } else {    /* retain YCbCr model */
+-                const T1 *p = pixel;
+-                if (this->PlanarConfiguration)
+-                {
+-/*
+-                    T2 *q;
+-                    // number of pixels to be skipped (only applicable if 
'PixelData' contains more
+-                    // pixels than expected)
+-                    const unsigned long skip = (this->InputCount > 
this->Count) ? (this->InputCount - this->Count) : 0;
+-                    for (int j = 0; j < 3; ++j)
+-                    {
+-                        q = this->Data[j];
+-                        for (i = count; i != 0; --i)
+-                            *(q++) = removeSign(*(p++), offset);
+-                        // skip to beginning of next plane
+-                        p += skip;
+-                    }
+-*/
+-                    unsigned long l;
+-                    unsigned long i = 0;
+-                    while (i < count)
+-                    {
+-                        /* store current pixel index */
+-                        const unsigned long iStart = i;
+-                        for (int j = 0; j < 3; ++j)
+-                        {
+-                            /* convert a single plane */
+-                            for (l = planeSize, i = iStart; (l != 0) && (i < 
count); --l, ++i)
+-                                this->Data[j][i] = removeSign(*(p++), offset);
+-                        }
+-                    }
+-                }
+-                else
+-                {
+-                    int j;
+-                    unsigned long i;
+-                    for (i = 0; i < count; ++i)                             
/* for all pixel ... */
+-                        for (j = 0; j < 3; ++j)
+-                            this->Data[j][i] = removeSign(*(p++), offset);  
/* ... copy planes */
+-                }
++            } else {
++                // do not process the input data, as it is too short
++                DCMIMAGE_WARN("input data is too short, filling the complete 
image with black pixels");
++                // erase empty part of the buffer (that has not been 
"blackened" yet)
++                for (int j = 0; j < 3; ++j)
++                    OFBitmanipTemplate<T2>::zeroMem(this->Data[j], count);
+             }
+         }
+     }
+--- dcmtk.orig/dcmimgle/libsrc/dcmimage.cc
++++ dcmtk/dcmimgle/libsrc/dcmimage.cc
+@@ -1,6 +1,6 @@
+ /*
+  *
+- *  Copyright (C) 1996-2021, OFFIS e.V.
++ *  Copyright (C) 1996-2025, OFFIS e.V.
+  *  All rights reserved.  See COPYRIGHT file for details.
+  *
+  *  This software and supporting documentation were developed by
+@@ -210,6 +210,7 @@
+                         *(q++) = c;
+                 }
+                 *q = '\0';                                          // end of 
C string
++                DCMIMGLE_DEBUG("filtered version of 
'PhotometricInterpretation' = " << OFSTRING_GUARD(cstr));
+                 while ((pin->Name != NULL) && (strcmp(pin->Name, cstr) != 0))
+                     ++pin;
+                 delete[] cstr;
diff -Nru dcmtk-3.6.7/debian/patches/0015-CVE-2025-9732b.patch 
dcmtk-3.6.7/debian/patches/0015-CVE-2025-9732b.patch
--- dcmtk-3.6.7/debian/patches/0015-CVE-2025-9732b.patch        1970-01-01 
01:00:00.000000000 +0100
+++ dcmtk-3.6.7/debian/patches/0015-CVE-2025-9732b.patch        2026-06-24 
21:12:59.000000000 +0200
@@ -0,0 +1,40 @@
+commit 3de96da6cd66b1af7224561c568bc3de50cd1398
+Author: Joerg Riesmeier <[email protected]>
+Date:   Mon Aug 18 17:58:56 2025 +0200
+
+    Fixed issue with commit 7ad81d69b.
+    
+    Fixed an issue with recently committed changes that fix a problem with
+    invalid YBR_FULL images
+
+diff --git a/dcmimage/include/dcmtk/dcmimage/diybrpxt.h 
b/dcmimage/include/dcmtk/dcmimage/diybrpxt.h
+index c5415c149..fdaaafc2d 100644
+--- a/dcmimage/include/dcmtk/dcmimage/diybrpxt.h
++++ b/dcmimage/include/dcmtk/dcmimage/diybrpxt.h
+@@ -92,7 +92,7 @@ class DiYBRPixelTemplate
+             // attribute), but not more than the size of the intermediate 
buffer
+             const unsigned long count = (this->InputCount < this->Count) ? 
this->InputCount : this->Count;
+             // make sure that there is sufficient input data (for planar 
pixel data)
+-            if (!this->PlanarConfiguration || (count >= planeSize * 3 /* 
number of planes */))
++            if (!this->PlanarConfiguration || (count >= planeSize))
+             {
+                 if (rgb)    /* convert to RGB model */
+                 {
+@@ -231,7 +231,7 @@ class DiYBRPixelTemplate
+                     const T1 *p = pixel;
+                     if (this->PlanarConfiguration)
+                     {
+-    /*
++/*
+                         T2 *q;
+                         // number of pixels to be skipped (only applicable if 
'PixelData' contains more
+                         // pixels than expected)
+@@ -244,7 +244,7 @@ class DiYBRPixelTemplate
+                             // skip to beginning of next plane
+                             p += skip;
+                         }
+-    */
++*/
+                         unsigned long l;
+                         unsigned long i = 0;
+                         while (i < count)
diff -Nru dcmtk-3.6.7/debian/patches/0016-CVE-2025-14607.patch 
dcmtk-3.6.7/debian/patches/0016-CVE-2025-14607.patch
--- dcmtk-3.6.7/debian/patches/0016-CVE-2025-14607.patch        1970-01-01 
01:00:00.000000000 +0100
+++ dcmtk-3.6.7/debian/patches/0016-CVE-2025-14607.patch        2026-06-24 
21:12:59.000000000 +0200
@@ -0,0 +1,31 @@
+commit 4c0e5c10079392c594d6a7abd95dd78ac0aa556a
+Author: Marco Eichelberg <[email protected]>
+Date:   Tue Dec 2 09:06:30 2025 +0100
+
+    Fixed bug in handling of odd-length data elements.
+    
+    When a dataset containing an illegal odd-length attribute with a text VR
+    was read from file or received over a network connection, then accessing
+    the value of that attribute with DcmElement::getString() may return a
+    pointer to a string that was not properly null terminated. Using C string
+    functions such as strlen() or strcpy() on that string then lead to a read
+    beyond the end of a string, causing a segmentation fault.
+    
+    Thanks to Zou Dikai <[email protected]> for the bug report and POC.
+    
+    This closes DCMTK issue #1184.
+
+--- dcmtk.orig/dcmdata/libsrc/dcbytstr.cc
++++ dcmtk/dcmdata/libsrc/dcbytstr.cc
+@@ -658,7 +658,11 @@
+ 
+         /* terminate string after real length */
+         if (value != NULL)
++        {
+             value[lengthField] = 0;
++            value[lengthField+1] = 0;
++        }
++
+         /* enforce old (pre DCMTK 3.5.2) behaviour? */
+         if (!dcmAcceptOddAttributeLength.get())
+         {
diff -Nru dcmtk-3.6.7/debian/patches/0017-CVE-2025-14841.patch 
dcmtk-3.6.7/debian/patches/0017-CVE-2025-14841.patch
--- dcmtk-3.6.7/debian/patches/0017-CVE-2025-14841.patch        1970-01-01 
01:00:00.000000000 +0100
+++ dcmtk-3.6.7/debian/patches/0017-CVE-2025-14841.patch        2026-06-23 
21:27:59.000000000 +0200
@@ -0,0 +1,37 @@
+commit ffb1a4a37d2c876e3feeb31df4930f2aed7fa030
+Author: Marco Eichelberg <[email protected]>
+Date:   Fri Nov 28 12:24:07 2025 +0100
+
+    Fixed two possible segfaults in dcmqrscp.
+    
+    Fixed two places where invalid messages may trigger a segmentation fault
+    due to a NULL pointer being de-referenced.
+    
+    Thanks to 邹 迪凯 <[email protected]> for the bug report and 
proof-of-concept.
+
+--- dcmtk.orig/dcmqrdb/libsrc/dcmqrdbi.cc
++++ dcmtk/dcmqrdb/libsrc/dcmqrdbi.cc
+@@ -1381,8 +1381,10 @@
+                 /* only char string type tags are supported at the moment */
+                 char *s = NULL;
+                 dcelem->getString(s);
++
+                 /* the available space is always elem.ValueLength+1 */
+-                OFStandard::strlcpy(elem.PValueField, s, elem.ValueLength+1);
++                if (s) OFStandard::strlcpy(elem.PValueField, s, 
elem.ValueLength+1);
++                    else elem.PValueField[0]='\0';
+             }
+             /** If element is the Query Level, store it in handle
+              */
+@@ -2066,8 +2068,10 @@
+                 /* only char string type tags are supported at the moment */
+                 char *s = NULL;
+                 dcelem->getString(s);
++
+                 /* the available space is always elem.ValueLength+1 */
+-                OFStandard::strlcpy(elem.PValueField, s, elem.ValueLength+1);
++                if (s) OFStandard::strlcpy(elem.PValueField, s, 
elem.ValueLength+1);
++                    else elem.PValueField[0]='\0';
+             }
+ 
+             /** If element is the Query Level, store it in handle
diff -Nru dcmtk-3.6.7/debian/patches/0018-CVE-2026-5663.patch 
dcmtk-3.6.7/debian/patches/0018-CVE-2026-5663.patch
--- dcmtk-3.6.7/debian/patches/0018-CVE-2026-5663.patch 1970-01-01 
01:00:00.000000000 +0100
+++ dcmtk-3.6.7/debian/patches/0018-CVE-2026-5663.patch 2026-06-24 
21:12:59.000000000 +0200
@@ -0,0 +1,274 @@
+commit edbb085e45788dccaf0e64d71534cfca925784b8
+Author: Marco Eichelberg <[email protected]>
+Date:   Sat Mar 21 18:35:14 2026 +0100
+
+    Sanitize all strings passed to the exec options.
+    
+    Sanitize the text fields from incoming DICOM associations and DICOM objects
+    (such as Study Instance UID, SOP Instance UID, Patient's Name) and the
+    calling SCU's network presentation address by removing special characters
+    that may be interpreted as shell escape characters when one of the
+    execution options (e.g. --exec-on-reception) is in use.
+    
+    Thanks to Machine Spirits UG (haftungsbeschränkt) for the bug report,
+    detailed analysis and proof of concept.
+    
+    This closes DCMTK issue #1194.
+
+--- dcmtk.orig/dcmnet/apps/storescp.cc
++++ dcmtk/dcmnet/apps/storescp.cc
+@@ -1,6 +1,6 @@
+ /*
+  *
+- *  Copyright (C) 1994-2021, 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
+@@ -201,6 +201,41 @@
+ #define SHORTCOL 4
+ #define LONGCOL 21
+ 
++// Allow list used by sanitizeAETitle(). Index is (byte - 32), so the
++// table covers the printable ASCII range 0x20..0x7E. Every entry either
++// repeats the input byte (kept) or is '_' (replaced). Kept characters:
++// space, '-', '.', ':', '@', '_' and ASCII letters/digits. All shell
++// metacharacters and path separators map to '_'.
++static const char sanitized_aetitle_charset[] =
++{
++  ' ', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '-', '.', 
'_',
++  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', '_', '_', '_', '_', 
'_',
++  '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 
'O',
++  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_', '_', '_', '_', 
'_',
++  '_', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 
'o',
++  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '_', '_', '_', '_', 
'_'
++};
++
++
++inline void sanitizeAETitle(OFString& aetitle)
++{
++    // Preserve a surrounding pair of quotation marks (used by callers
++    // that substitute the AE title into an already quoted shell argument).
++    size_t len = aetitle.length();
++    size_t start = 0;
++    if (len >= 2 && aetitle[0] == '"' && aetitle[len - 1] == '"')
++    {
++        start = 1;
++        --len;
++    }
++    for (size_t i = start; i < len; ++i)
++    {
++        unsigned char c = OFstatic_cast(unsigned char, aetitle[i]);
++        if (c < 32 || c >= 127) aetitle[i] = '_';
++        else aetitle[i] = sanitized_aetitle_charset[c - 32];
++    }
++}
++
+ int main(int argc, char *argv[])
+ {
+   T_ASC_Network *net;
+@@ -1474,7 +1509,9 @@
+     calledAETitle.clear();
+   }
+   // store calling presentation address (i.e. remote hostname)
+-  callingPresentationAddress = 
OFSTRING_GUARD(assoc->params->DULparams.callingPresentationAddress);
++  callingPresentationAddress = "\"";
++  callingPresentationAddress += 
OFSTRING_GUARD(assoc->params->DULparams.callingPresentationAddress);
++  callingPresentationAddress += "\"";
+ 
+   /* now do the real work, i.e. receive DIMSE commands over the network 
connection */
+   /* which was established and handle these commands correspondingly. In case 
of */
+@@ -1838,6 +1875,7 @@
+             dateTime.getTime().getHour(), dateTime.getTime().getMinute(), 
dateTime.getTime().getIntSecond(), dateTime.getTime().getMilliSecond());
+ 
+           OFString subdirectoryName;
++          OFString s;
+           switch (opt_sortStudyMode)
+           {
+             case ESM_Timestamp:
+@@ -1852,15 +1890,27 @@
+               subdirectoryName = opt_sortStudyDirPrefix;
+               if (!subdirectoryName.empty())
+                 subdirectoryName += '_';
+-              subdirectoryName += currentStudyInstanceUID;
+-              OFStandard::sanitizeFilename(subdirectoryName);
++              s = currentStudyInstanceUID;
++              OFStandard::sanitizeFilename(s);
++              if (s != currentStudyInstanceUID)
++              {
++                OFLOG_WARN(storescpLogger, "Sanitized unusual characters in 
Study Instance UID, converted from \"" << currentStudyInstanceUID << "\" to \"" 
<< s << "\".");
++              }
++              subdirectoryName += s;
+               break;
+             case ESM_PatientName:
+               // pattern: "[Patient's Name]_[YYYYMMDD]_[HHMMSSMMM]"
+               subdirectoryName = currentPatientName;
++              OFStandard::sanitizeFilename(subdirectoryName);
++              if (subdirectoryName != currentPatientName)
++              {
++                // It is quite normal that we need to sanitize characters in 
PatientName.
++                // Therefore, this is only a debug message and not a warning, 
unlike the other
++                // messages about sanitized fields, which are normally not 
expected.
++                OFLOG_DEBUG(storescpLogger, "Sanitized characters in Patient 
Name, converted from \"" << currentPatientName << "\" to \"" << 
subdirectoryName << "\".");
++              }
+               subdirectoryName += '_';
+               subdirectoryName += timestamp;
+-              OFStandard::sanitizeFilename(subdirectoryName);
+               break;
+             case ESM_None:
+               break;
+@@ -2068,8 +2118,13 @@
+     else
+     {
+       // Use the SOP instance UID as found in the C-STORE request message as 
part of the filename
+-      OFString uid = req->AffectedSOPInstanceUID;
++      OFString s(OFSTRING_GUARD(req->AffectedSOPInstanceUID));
++      OFString uid = s;
+       OFStandard::sanitizeFilename(uid);
++      if (uid != s)
++      {
++        OFLOG_WARN(storescpLogger, "Sanitized unusual characters in SOP 
Instance UID, converted from \"" << s << "\" to \"" << uid << "\".");
++      }
+       sprintf(imageFileName, "%s%c%s.%s%s", opt_outputDirectory.c_str(), 
PATH_SEPARATOR, dcmSOPClassUIDToModality(req->AffectedSOPClassUID, "UNKNOWN"),
+         uid.c_str(), opt_fileNameExtension.c_str());
+     }
+@@ -2202,28 +2257,40 @@
+      */
+ {
+   OFString cmd = opt_execOnReception;
++  OFString s;
+ 
+   // in case a file was actually written
+   if( !opt_ignore )
+   {
+     // perform substitution for placeholder #p (depending on presence of any 
--sort-xxx option)
++    // Note: We do not enclose this in quotes because it may be used as part 
of a path expression.
+     OFString dir = (opt_sortStudyMode == ESM_None) ? opt_outputDirectory : 
subdirectoryPathAndName;
+     cmd = replaceChars( cmd, OFString(PATH_PLACEHOLDER), dir );
+ 
+     // perform substitution for placeholder #f; note that 
outputFileNameArray.back()
+     // always contains the name of the file (without path) which was written 
last.
++    // Note: We do not enclose this in quotes because it may be used as part 
of a path expression.
+     OFString outputFileName = outputFileNameArray.back();
+     cmd = replaceChars( cmd, OFString(FILENAME_PLACEHOLDER), outputFileName );
+   }
+ 
+-  // perform substitution for placeholder #a
++  // perform substitution for placeholder #a.
++  // Note that this string is already enclosed in double quotes at this point
+   cmd = replaceChars( cmd, OFString(CALLING_AETITLE_PLACEHOLDER), 
callingAETitle );
+ 
+-  // perform substitution for placeholder #c
++  // perform substitution for placeholder #c.
++  // Note that this string is already enclosed in double quotes at this point
+   cmd = replaceChars( cmd, OFString(CALLED_AETITLE_PLACEHOLDER), 
calledAETitle );
+ 
+-  // perform substitution for placeholder #r
+-  cmd = replaceChars( cmd, 
OFString(CALLING_PRESENTATION_ADDRESS_PLACEHOLDER), callingPresentationAddress 
);
++  // perform substitution for placeholder #r.
++  // Note that this string is already enclosed in double quotes at this point
++  s = callingPresentationAddress;
++  sanitizeAETitle(s);
++  if (s != callingPresentationAddress)
++  {
++    OFLOG_WARN(storescpLogger, "Sanitized unusual characters in calling 
presentation address, converted from " << callingPresentationAddress << " to " 
<< s << ".");
++  }
++  cmd = replaceChars( cmd, 
OFString(CALLING_PRESENTATION_ADDRESS_PLACEHOLDER), s );
+ 
+   // Execute command in a new process
+   executeCommand( cmd );
+@@ -2325,18 +2392,41 @@
+      */
+ {
+   OFString cmd = opt_execOnEndOfStudy;
++  OFString s;
+ 
+   // perform substitution for placeholder #p; #p will be substituted by 
lastStudySubdirectoryPathAndName
++  // Note: We do not enclose this in quotes because it may be used as part of 
a path expression.
+   cmd = replaceChars( cmd, OFString(PATH_PLACEHOLDER), 
lastStudySubdirectoryPathAndName );
+ 
+-  // perform substitution for placeholder #a
+-  cmd = replaceChars( cmd, OFString(CALLING_AETITLE_PLACEHOLDER), 
callingAETitle );
++  // perform substitution for placeholder #a.
++  // Note that this string is already enclosed in double quotes at this point
++  s = callingAETitle;
++  sanitizeAETitle(s);
++  if (s != callingAETitle)
++  {
++    OFLOG_WARN(storescpLogger, "Sanitized unusual characters in calling 
aetitle, converted from " << callingAETitle << " to " << s << ".");
++  }
++  cmd = replaceChars( cmd, OFString(CALLING_AETITLE_PLACEHOLDER), s );
+ 
+-  // perform substitution for placeholder #c
+-  cmd = replaceChars( cmd, OFString(CALLED_AETITLE_PLACEHOLDER), 
calledAETitle );
++  // perform substitution for placeholder #c.
++  // Note that this string is already enclosed in double quotes at this point
++  s = calledAETitle;
++  sanitizeAETitle(s);
++  if (s != calledAETitle)
++  {
++    OFLOG_WARN(storescpLogger, "Sanitized unusual characters in called 
aetitle, converted from " << calledAETitle << " to " << s << ".");
++  }
++  cmd = replaceChars( cmd, OFString(CALLED_AETITLE_PLACEHOLDER), s );
+ 
+-  // perform substitution for placeholder #r
+-  cmd = replaceChars( cmd, 
OFString(CALLING_PRESENTATION_ADDRESS_PLACEHOLDER), callingPresentationAddress 
);
++  // perform substitution for placeholder #r.
++  // Note that this string is already enclosed in double quotes at this point
++  s = callingPresentationAddress;
++  sanitizeAETitle(s);
++  if (s != callingPresentationAddress)
++  {
++    OFLOG_WARN(storescpLogger, "Sanitized unusual characters in calling 
presentation address, converted from " << callingPresentationAddress << " to " 
<< s << ".");
++  }
++  cmd = replaceChars( cmd, 
OFString(CALLING_PRESENTATION_ADDRESS_PLACEHOLDER), s );
+ 
+   // Execute command in a new process
+   executeCommand( cmd );
+--- dcmtk.orig/ofstd/libsrc/ofstd.cc
++++ dcmtk/ofstd/libsrc/ofstd.cc
+@@ -3246,16 +3246,26 @@
+ }
+ 
+ 
++static const char sanitized_filename_charset[] =
++{
++  ' ', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '-', '.', 
'_',
++  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', '_', '_', '_', '_', 
'_',
++  '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 
'O',
++  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_', '_', '_', '_', 
'_',
++  '_', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 
'o',
++  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '_', '_', '_', '_', 
'_'
++};
++
++
+ void OFStandard::sanitizeFilename(OFString& fname)
+ {
+   size_t len = fname.length();
++  char c;
+   for (size_t i=0; i<len; ++i)
+   {
+-#ifdef _WIN32
+-        if ((fname[i] == PATH_SEPARATOR)||(fname[i] == '/')) fname[i] = '_';
+-#else
+-        if (fname[i] == PATH_SEPARATOR) fname[i] = '_';
+-#endif
++        c = fname[i];
++        if (c != 0 && (c < 32 || c >= 127)) c = '_'; else c = 
sanitized_filename_charset[c-32];
++        fname[i] = c;
+   }
+ }
+ 
+@@ -3267,11 +3277,7 @@
+     char *c = fname;
+     while (*c)
+     {
+-#ifdef _WIN32
+-      if ((*c == PATH_SEPARATOR)||(*c == '/')) *c = '_';
+-#else
+-      if (*c == PATH_SEPARATOR) *c = '_';
+-#endif
++      if (*c < 32 || *c >= 127) *c = '_'; else *c = 
sanitized_filename_charset[*c-32];
+       ++c;
+     }
+   }
diff -Nru dcmtk-3.6.7/debian/patches/0019-CVE-2026-10194.patch 
dcmtk-3.6.7/debian/patches/0019-CVE-2026-10194.patch
--- dcmtk-3.6.7/debian/patches/0019-CVE-2026-10194.patch        1970-01-01 
01:00:00.000000000 +0100
+++ dcmtk-3.6.7/debian/patches/0019-CVE-2026-10194.patch        2026-06-24 
21:12:59.000000000 +0200
@@ -0,0 +1,66 @@
+commit 0f78a4ef6f645ea5530166e445e5436a5de58e75
+Author: Marco Eichelberg <[email protected]>
+Date:   Mon May 4 17:48:30 2026 +0200
+
+    Fixed remote heap buffer overflow in dcmqrscp.
+    
+    Thanks to 'elp3pinill0' for the bug report, detailed
+    analysis, proof of concept and proposed fix.
+    
+    This closes DCMTK issue #1206.
+
+--- dcmtk.orig/dcmqrdb/libsrc/dcmqrdbi.cc
++++ dcmtk/dcmqrdb/libsrc/dcmqrdbi.cc
+@@ -1,6 +1,6 @@
+ /*
+  *
+- *  Copyright (C) 1993-2022, OFFIS e.V.
++ *  Copyright (C) 1993-2026, OFFIS e.V.
+  *  All rights reserved.  See COPYRIGHT file for details.
+  *
+  *  This software and supporting documentation were developed by
+@@ -2475,12 +2475,16 @@
+ 
+     DB_IdxInitLoop (&(handle_ -> idxCounter)) ;
+     while ( DB_IdxGetNext(&(handle_ -> idxCounter), &idxRec) == EC_Normal ) {
+-    if ( ! ( strncmp(idxRec. StudyInstanceUID, StudyUID, n) ) ) {
+-
+-        StudyArray[nbimages]. idxCounter = handle_ -> idxCounter ;
+-        StudyArray[nbimages]. RecordedDate = idxRec. RecordedDate ;
+-        StudyArray[nbimages++]. ImageSize = idxRec. ImageSize ;
+-    }
++        if ( ! ( strncmp(idxRec. StudyInstanceUID, StudyUID, n) ) ) {
++            StudyArray[nbimages]. idxCounter = handle_ -> idxCounter ;
++            StudyArray[nbimages]. RecordedDate = idxRec. RecordedDate ;
++            StudyArray[nbimages++]. ImageSize = idxRec. ImageSize ;
++            if (nbimages == MAX_NUMBER_OF_IMAGES) {
++                // too many images in this study, bail out
++                DCMQRDB_ERROR("maximum number of images per study (" << 
MAX_NUMBER_OF_IMAGES << ") exceeded");
++                return QR_EC_IndexDatabaseError;
++            }
++        }
+     }
+ 
+     /** Sort the StudyArray in order to have the oldest images first
+@@ -2567,6 +2571,8 @@
+     s = matchStudyUIDInStudyDesc (pStudyDesc, StudyUID,
+                      (int)(handle_ -> maxStudiesAllowed)) ;
+ 
++    OFCondition cond;
++
+     /** If Study already exists
+      */
+ 
+@@ -2587,10 +2593,10 @@
+ 
+         RequiredSize = imageSize -
+             ( handle_ -> maxBytesPerStudy - pStudyDesc[s]. StudySize ) ;
+-        deleteOldestImages(pStudyDesc, s, StudyUID, RequiredSize) ;
++        cond = deleteOldestImages(pStudyDesc, s, StudyUID, RequiredSize) ;
++        if (cond.bad()) return cond;
+     }
+ 
+-
+     }
+     else {
+ #ifdef DEBUG
diff -Nru dcmtk-3.6.7/debian/patches/0020-CVE-2026-12805.patch 
dcmtk-3.6.7/debian/patches/0020-CVE-2026-12805.patch
--- dcmtk-3.6.7/debian/patches/0020-CVE-2026-12805.patch        1970-01-01 
01:00:00.000000000 +0100
+++ dcmtk-3.6.7/debian/patches/0020-CVE-2026-12805.patch        2026-06-24 
21:14:39.000000000 +0200
@@ -0,0 +1,34 @@
+commit 1d4b3815c0987840a983160bfc671fef63a3105b
+Author: Marco Eichelberg <[email protected]>
+Date:   Sat May 23 17:07:58 2026 +0200
+
+    Fixed buffer overflow in XMLNode::parseFile().
+    
+    Fixed a heap buffer overflow that could occur in the XML parser
+    when reading from a named pipe.
+    
+    Thanks to Cristhian Daniel Rivas Zúñiga and Sebastian Andres Muñoz Morera
+    (Insituto Tecnológico de Costa Rica) for the bug report and fix.
+    
+    This closes DCMTK issue #1208.
+
+--- dcmtk.orig/ofstd/libsrc/ofxml.cc
++++ dcmtk/ofstd/libsrc/ofxml.cc
+@@ -1,6 +1,6 @@
+ /*
+  *
+- *  Copyright (C) 2011-2021, OFFIS e.V.
++ *  Copyright (C) 2011-2026, OFFIS e.V.
+  *  All rights reserved.  See COPYRIGHT file for details.
+  *
+  *  This software and supporting documentation were slightly modified by
+@@ -1962,7 +1962,8 @@
+     if (f==NULL) { if (pResults) pResults->error=eXMLErrorFileNotFound; 
return emptyXMLNode; }
+     fseek(f,0,SEEK_END);
+     int l=OFstatic_cast(int, ftell(f)),headerSz=0;
+-    if (!l) { if (pResults) pResults->error=eXMLErrorEmpty; fclose(f); return 
emptyXMLNode; }
++    // DCMTK: handle situation where ftell() returns -1
++    if (l <= 0) { if (pResults) pResults->error=eXMLErrorEmpty; fclose(f); 
return emptyXMLNode; }
+     fseek(f,0,SEEK_SET);
+     unsigned char *buf=OFreinterpret_cast(unsigned char*, malloc(l+4));
+     l=OFstatic_cast(int, fread(buf,1,l,f));
diff -Nru dcmtk-3.6.7/debian/patches/series dcmtk-3.6.7/debian/patches/series
--- dcmtk-3.6.7/debian/patches/series   2025-02-20 21:57:29.000000000 +0100
+++ dcmtk-3.6.7/debian/patches/series   2026-06-24 21:14:45.000000000 +0200
@@ -21,3 +21,12 @@
 0009-CVE-2025-25475.patch
 0010-CVE-2025-25474.patch
 0011-CVE-2025-25472.patch
+0012-CVE-2022-4981.patch
+0013-CVE-2025-2357.patch
+0014-CVE-2025-9732.patch
+0015-CVE-2025-9732b.patch
+0016-CVE-2025-14607.patch
+0017-CVE-2025-14841.patch
+0018-CVE-2026-5663.patch
+0019-CVE-2026-10194.patch
+0020-CVE-2026-12805.patch

Attachment: signature.asc
Description: PGP signature

Reply via email to