Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package dcmtk for openSUSE:Factory checked 
in at 2024-04-25 20:48:27
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/dcmtk (Old)
 and      /work/SRC/openSUSE:Factory/.dcmtk.new.1880 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "dcmtk"

Thu Apr 25 20:48:27 2024 rev:30 rq:1169995 version:3.6.8

Changes:
--------
--- /work/SRC/openSUSE:Factory/dcmtk/dcmtk.changes      2024-03-01 
23:39:53.954775153 +0100
+++ /work/SRC/openSUSE:Factory/.dcmtk.new.1880/dcmtk.changes    2024-04-25 
20:48:31.980649598 +0200
@@ -1,0 +2,14 @@
+Wed Apr 24 07:45:23 UTC 2024 - Christophe Marin <christo...@krop.fr>
+
+- Add upstream changes:
+  * 0001-Fixed-buffer-overflow-in-decompression-codecs.patch
+  * 0001-Fixed-possible-overflows-when-allocating-memory.patch
+  * 0001-Fixed-two-segmentation-faults.patch
+  * 0001-Fixed-unchecked-typecasts-of-DcmItem-search-results.patch
+  * 0002-Fixed-unchecked-typecasts-and-fixed-LUT-handling.patch
+    (boo#1223324, CVE-2024-28130)
+  * 0003-Fixed-wrong-error-handling-previous-commit.patch
+  * 0001-Fixed-DcmDecimalString-unit-tests.patch
+- Run unit tests
+
+-------------------------------------------------------------------

New:
----
  0001-Fixed-DcmDecimalString-unit-tests.patch
  0001-Fixed-buffer-overflow-in-decompression-codecs.patch
  0001-Fixed-possible-overflows-when-allocating-memory.patch
  0001-Fixed-two-segmentation-faults.patch
  0001-Fixed-unchecked-typecasts-of-DcmItem-search-results.patch
  0002-Fixed-unchecked-typecasts-and-fixed-LUT-handling.patch
  0003-Fixed-wrong-error-handling-previous-commit.patch

BETA DEBUG BEGIN:
  New:  * 0003-Fixed-wrong-error-handling-previous-commit.patch
  * 0001-Fixed-DcmDecimalString-unit-tests.patch
- Run unit tests
  New:- Add upstream changes:
  * 0001-Fixed-buffer-overflow-in-decompression-codecs.patch
  * 0001-Fixed-possible-overflows-when-allocating-memory.patch
  New:  * 0001-Fixed-buffer-overflow-in-decompression-codecs.patch
  * 0001-Fixed-possible-overflows-when-allocating-memory.patch
  * 0001-Fixed-two-segmentation-faults.patch
  New:  * 0001-Fixed-possible-overflows-when-allocating-memory.patch
  * 0001-Fixed-two-segmentation-faults.patch
  * 0001-Fixed-unchecked-typecasts-of-DcmItem-search-results.patch
  New:  * 0001-Fixed-two-segmentation-faults.patch
  * 0001-Fixed-unchecked-typecasts-of-DcmItem-search-results.patch
  * 0002-Fixed-unchecked-typecasts-and-fixed-LUT-handling.patch
  New:  * 0001-Fixed-unchecked-typecasts-of-DcmItem-search-results.patch
  * 0002-Fixed-unchecked-typecasts-and-fixed-LUT-handling.patch
    (boo#1223324, CVE-2024-28130)
  New:    (boo#1223324, CVE-2024-28130)
  * 0003-Fixed-wrong-error-handling-previous-commit.patch
  * 0001-Fixed-DcmDecimalString-unit-tests.patch
BETA DEBUG END:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ dcmtk.spec ++++++
--- /var/tmp/diff_new_pack.9IFFMF/_old  2024-04-25 20:48:33.100690725 +0200
+++ /var/tmp/diff_new_pack.9IFFMF/_new  2024-04-25 20:48:33.100690725 +0200
@@ -26,6 +26,14 @@
 Source0:        
ftp://dicom.offis.de/pub/dicom/offis/software/dcmtk/release/%{name}-%{version}.tar.gz
 # PATCH-FIX-OPENSUSE dcmtk-fix-DCMTKTargets.cmake.patch -- Do not track 
executables to be able to use dcmtk-devel without dcmtk package
 Patch0:         dcmtk-fix-DCMTKTargets.cmake.patch
+# PATCH-FIX-UPSTREAM
+Patch1:         0001-Fixed-buffer-overflow-in-decompression-codecs.patch
+Patch2:         0001-Fixed-possible-overflows-when-allocating-memory.patch
+Patch3:         0001-Fixed-two-segmentation-faults.patch
+Patch4:         0001-Fixed-unchecked-typecasts-of-DcmItem-search-results.patch
+Patch5:         0002-Fixed-unchecked-typecasts-and-fixed-LUT-handling.patch
+Patch6:         0003-Fixed-wrong-error-handling-previous-commit.patch
+Patch7:         0001-Fixed-DcmDecimalString-unit-tests.patch
 BuildRequires:  cmake
 BuildRequires:  doxygen
 BuildRequires:  fdupes
@@ -95,7 +103,10 @@
 # Install README file to documentation
 install -pm 0644 README %{buildroot}%{_docdir}/dcmtk/
 
-%fdupes -s %{buildroot}
+%fdupes %{buildroot}
+
+%check
+%ctest
 
 %ldconfig_scriptlets -n libdcmtk%{abiversion}
 

++++++ 0001-Fixed-DcmDecimalString-unit-tests.patch ++++++
>From 66c317feae446deda1a389226aa24c95a0eeac4c Mon Sep 17 00:00:00 2001
From: Marco Eichelberg <di...@offis.de>
Date: Wed, 13 Mar 2024 23:03:40 +0100
Subject: [PATCH] Fixed DcmDecimalString unit tests.

---
 dcmdata/tests/tvrds.cc | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/dcmdata/tests/tvrds.cc b/dcmdata/tests/tvrds.cc
index a9132a341..0e929304d 100644
--- a/dcmdata/tests/tvrds.cc
+++ b/dcmdata/tests/tvrds.cc
@@ -1,6 +1,6 @@
 /*
  *
- *  Copyright (C) 2011-2020, OFFIS e.V.
+ *  Copyright (C) 2011-2024, OFFIS e.V.
  *  All rights reserved.  See COPYRIGHT file for details.
  *
  *  This software and supporting documentation were developed by
@@ -30,7 +30,7 @@
 
 OFTEST(dcmdata_decimalString_1)
 {
-    DcmDecimalString decStr(DCM_ContourData, EVR_DS);
+    DcmDecimalString decStr(DCM_ContourData);
     OFVector<Float64> doubleVals;
     OFCHECK(decStr.putString("1\\2.0\\3.5\\-4.99\\+500.005\\6.66E-01").good());
     OFCHECK(decStr.getFloat64Vector(doubleVals).good());
@@ -45,7 +45,7 @@ OFTEST(dcmdata_decimalString_1)
 
 OFTEST(dcmdata_decimalString_2)
 {
-    DcmDecimalString decStr(DCM_ContourData, EVR_DS);
+    DcmDecimalString decStr(DCM_ContourData);
     OFVector<Float64> doubleVals;
     /* insert a NULL byte into the string */
     OFCHECK(decStr.putString("1\\2.0\\3.5\\-4.99\0\\+500.005\\6.66E-01", 
34).good());
@@ -61,7 +61,7 @@ OFTEST(dcmdata_decimalString_2)
 
 OFTEST(dcmdata_decimalString_3)
 {
-    DcmDecimalString decStr(DCM_ContourData, EVR_DS);
+    DcmDecimalString decStr(DCM_ContourData);
     OFVector<Float64> doubleVals;
     /* insert a NULL byte into the string */
     
OFCHECK(decStr.putOFStringArray(OFString("1\\2.0\\3.5\\-4.99\0\\+500.005\\6.66E-01",
 34)).good());
@@ -77,7 +77,7 @@ OFTEST(dcmdata_decimalString_3)
 
 OFTEST(dcmdata_decimalString_4)
 {
-    DcmDecimalString decStr(DCM_ContourData, EVR_DS);
+    DcmDecimalString decStr(DCM_ContourData);
     OFVector<Float64> doubleVals;
     
OFCHECK(decStr.putString("1\\2.0\\3.5\\-4.99\\+500.005\\6.66E-01\\").good());
     OFCHECK_EQUAL(decStr.getVM(), 7);
@@ -96,7 +96,7 @@ OFTEST(dcmdata_decimalString_putFloat64)
 {
     // Test insertion in the beginning
     OFString testStr;
-    DcmDecimalString decStr(DCM_ContourData, EVR_DS);
+    DcmDecimalString decStr(DCM_ContourData);
     OFCHECK(decStr.putFloat64(0, 0).good());
     decStr.getOFStringArray(testStr);
     OFCHECK(testStr == "0");
-- 
2.44.0


++++++ 0001-Fixed-buffer-overflow-in-decompression-codecs.patch ++++++
>From 31ff413f97839c61752875569862a94a6cce06dd Mon Sep 17 00:00:00 2001
From: Marco Eichelberg <di...@offis.de>
Date: Thu, 28 Dec 2023 17:32:42 +0100
Subject: [PATCH] Fixed buffer overflow in decompression codecs.

Fixed the computation of the element size for the decompressed PixelData
element in all decompression codecs. In the case of datasets that cannot
be decoded to an unencapsulated transfer syntax, since the resulting
pixel data would be larger than 4 GByte, an overflow of the size
variable remained undetected and could lead to a segmentation fault due
to a buffer overrun.

This closes DCMTK issue #1099.
---
 dcmdata/libsrc/dcrleccd.cc | 39 ++++++++++++++++++++++++++++++--------
 dcmjpeg/libsrc/djcodecd.cc | 36 ++++++++++++++++++++++++++++++-----
 dcmjpls/libsrc/djcodecd.cc | 17 ++++++++++++++++-
 3 files changed, 78 insertions(+), 14 deletions(-)

diff --git a/dcmdata/libsrc/dcrleccd.cc b/dcmdata/libsrc/dcrleccd.cc
index ffdd14116..5ddc8f6be 100644
--- a/dcmdata/libsrc/dcrleccd.cc
+++ b/dcmdata/libsrc/dcrleccd.cc
@@ -1,6 +1,6 @@
 /*
  *
- *  Copyright (C) 2002-2020, OFFIS e.V.
+ *  Copyright (C) 2002-2024, OFFIS e.V.
  *  All rights reserved.  See COPYRIGHT file for details.
  *
  *  This software and supporting documentation were developed by
@@ -129,9 +129,25 @@ OFCondition DcmRLECodecDecoder::decode(
       if (rledecoder.fail()) result = EC_MemoryExhausted;  // RLE decoder 
failed to initialize
       else
       {
-        const size_t frameSize = OFstatic_cast(size_t, imageBytesAllocated) * 
OFstatic_cast(size_t, imageRows)
-            * OFstatic_cast(size_t, imageColumns) * OFstatic_cast(size_t, 
imageSamplesPerPixel);
-        size_t totalSize = frameSize * imageFrames;
+        // compute size of uncompressed frame, in bytes
+        Uint32 frameSize = imageBytesAllocated * imageRows * imageColumns * 
imageSamplesPerPixel;
+
+        // check for overflow
+        if (imageRows != 0 && frameSize / imageRows != (imageBytesAllocated * 
imageColumns * imageSamplesPerPixel))
+        {
+          DCMDATA_WARN("Cannot decompress image because uncompressed 
representation would exceed maximum possible size of PixelData attribute.");
+          return EC_ElemLengthExceeds32BitField;
+        }
+
+        Uint32 totalSize = frameSize * imageFrames;
+
+        // check for overflow
+        if (totalSize == 0xFFFFFFFF || (frameSize != 0 && totalSize / 
frameSize != OFstatic_cast(Uint32, imageFrames)))
+        {
+          DCMDATA_WARN("Cannot decompress image because uncompressed 
representation would exceed maximum possible size of PixelData attribute.");
+          return EC_ElemLengthExceeds32BitField;
+        }
+
         if (totalSize & 1) totalSize++; // align on 16-bit word boundary
         Uint16 *imageData16 = NULL;
         Sint32 currentFrame = 0;
@@ -139,7 +155,7 @@ OFCondition DcmRLECodecDecoder::decode(
         Uint32 numberOfStripes = 0;
         Uint32 fragmentLength = 0;
 
-        result = uncompressedPixelData.createUint16Array(OFstatic_cast(Uint32, 
totalSize/sizeof(Uint16)), imageData16);
+        result = 
uncompressedPixelData.createUint16Array(totalSize/sizeof(Uint16), imageData16);
         if (result.good())
         {
           Uint8 *imageData8 = OFreinterpret_cast(Uint8 *, imageData16);
@@ -463,7 +479,7 @@ OFCondition DcmRLECodecDecoder::decodeFrame(
     Uint16 imageColumns = 0;
     Sint32 imageFrames = 1;
     Uint16 imageBitsAllocated = 0;
-    Uint16 imageBytesAllocated = 0;
+    Uint32 imageBytesAllocated = 0;
     Uint16 imagePlanarConfiguration = 0;
     Uint32 rleHeader[16];
     OFString photometricInterpretation;
@@ -476,7 +492,7 @@ OFCondition DcmRLECodecDecoder::decodeFrame(
     if (result.good()) result = 
dataset->findAndGetOFString(DCM_PhotometricInterpretation, 
photometricInterpretation);
     if (result.good())
     {
-        imageBytesAllocated = OFstatic_cast(Uint16, imageBitsAllocated / 8);
+        imageBytesAllocated = OFstatic_cast(Uint32, imageBitsAllocated / 8);
         if ((imageBitsAllocated < 8)||(imageBitsAllocated % 8 != 0))
         {
           DCMDATA_ERROR("The RLE decoder only supports images where 
BitsAllocated is a multiple of 8.");
@@ -500,9 +516,16 @@ OFCondition DcmRLECodecDecoder::decodeFrame(
     const size_t bytesPerStripe = OFstatic_cast(size_t, imageColumns) * 
OFstatic_cast(size_t, imageRows);
     Uint32 numberOfStripes = 0;
     Uint32 fragmentLength = 0;
-    Uint32 frameSize = OFstatic_cast(Uint32, imageBytesAllocated) * 
OFstatic_cast(Uint32, imageRows)
+    Uint32 frameSize = imageBytesAllocated * OFstatic_cast(Uint32, imageRows)
                        * OFstatic_cast(Uint32, imageColumns) * 
OFstatic_cast(Uint32, imageSamplesPerPixel);
 
+    // check for overflow
+    if (imageRows != 0 && frameSize / imageRows != (imageBytesAllocated * 
imageColumns * imageSamplesPerPixel))
+    {
+      DCMDATA_WARN("Cannot decompress image because uncompressed 
representation would exceed maximum possible size of PixelData attribute.");
+      return EC_ElemLengthExceeds32BitField;
+    }
+
     if (frameSize > bufSize) return EC_IllegalCall;
 
     DcmRLEDecoder rledecoder(bytesPerStripe);
diff --git a/dcmjpeg/libsrc/djcodecd.cc b/dcmjpeg/libsrc/djcodecd.cc
index 364b75533..a93a8104b 100644
--- a/dcmjpeg/libsrc/djcodecd.cc
+++ b/dcmjpeg/libsrc/djcodecd.cc
@@ -1,6 +1,6 @@
 /*
  *
- *  Copyright (C) 2001-2022, OFFIS e.V.
+ *  Copyright (C) 2001-2024, OFFIS e.V.
  *  All rights reserved.  See COPYRIGHT file for details.
  *
  *  This software and supporting documentation were developed by
@@ -150,8 +150,25 @@ OFCondition DJCodecDecoder::decode(
               if (jpeg == NULL) result = EC_MemoryExhausted;
               else
               {
-                size_t frameSize = ((precision > 8) ? sizeof(Uint16) : 
sizeof(Uint8)) * imageRows * imageColumns * imageSamplesPerPixel;
-                size_t totalSize = frameSize * imageFrames;
+                Uint32 imageBytesAllocated = (precision > 8) ? sizeof(Uint16) 
: sizeof(Uint8);
+                Uint32 frameSize = imageBytesAllocated * imageRows * 
imageColumns * imageSamplesPerPixel;
+
+                // check for overflow
+                if (imageRows != 0 && frameSize / imageRows != 
(imageBytesAllocated * imageColumns * imageSamplesPerPixel))
+                {
+                  DCMJPEG_WARN("Cannot decompress image because uncompressed 
representation would exceed maximum possible size of PixelData attribute.");
+                  return EC_ElemLengthExceeds32BitField;
+                }
+
+                Uint32 totalSize = frameSize * imageFrames;
+
+                // check for overflow
+                if (totalSize == 0xFFFFFFFF || (frameSize != 0 && totalSize / 
frameSize != OFstatic_cast(Uint32, imageFrames)))
+                {
+                  DCMJPEG_WARN("Cannot decompress image because uncompressed 
representation would exceed maximum possible size of PixelData attribute.");
+                  return EC_ElemLengthExceeds32BitField;
+                }
+
                 if (totalSize & 1) totalSize++; // align on 16-bit word 
boundary
                 Uint16 *imageData16 = NULL;
                 Sint32 currentFrame = 0;
@@ -166,7 +183,7 @@ OFCondition DJCodecDecoder::decode(
                   }
                 }
 
-                result = 
uncompressedPixelData.createUint16Array(OFstatic_cast(Uint32, totalSize / 
sizeof(Uint16)), imageData16);
+                result = uncompressedPixelData.createUint16Array(totalSize / 
sizeof(Uint16), imageData16);
                 if (result.good())
                 {
                   Uint8 *imageData8 = OFreinterpret_cast(Uint8*, imageData16);
@@ -492,7 +509,16 @@ OFCondition DJCodecDecoder::decodeFrame(
             if (precision == 0) result = EC_CannotChangeRepresentation; // 
something has gone wrong, bail out
             else
             {
-              size_t frameSize = ((precision > 8) ? sizeof(Uint16) : 
sizeof(Uint8)) * imageRows * imageColumns * imageSamplesPerPixel;
+              Uint32 imageBytesAllocated = (precision > 8) ? sizeof(Uint16) : 
sizeof(Uint8);
+              Uint32 frameSize = imageBytesAllocated * imageRows * 
imageColumns * imageSamplesPerPixel;
+
+              // check for overflow
+              if (imageRows != 0 && frameSize / imageRows != 
(imageBytesAllocated * imageColumns * imageSamplesPerPixel))
+              {
+                DCMJPEG_WARN("Cannot decompress image because uncompressed 
representation would exceed maximum possible size of PixelData attribute.");
+                return EC_ElemLengthExceeds32BitField;
+              }
+
               if (frameSize > bufSize) return EC_IllegalCall;
 
               DJDecoder *jpeg = createDecoderInstance(fromParam, djcp, 
precision, isYBR);
diff --git a/dcmjpls/libsrc/djcodecd.cc b/dcmjpls/libsrc/djcodecd.cc
index e04a21e0d..45e6fec56 100644
--- a/dcmjpls/libsrc/djcodecd.cc
+++ b/dcmjpls/libsrc/djcodecd.cc
@@ -1,6 +1,6 @@
 /*
  *
- *  Copyright (C) 2007-2022, OFFIS e.V.
+ *  Copyright (C) 2007-2024, OFFIS e.V.
  *  All rights reserved.  See COPYRIGHT file for details.
  *
  *  This software and supporting documentation were developed by
@@ -143,8 +143,23 @@ OFCondition DJLSDecoderBase::decode(
   // compute size of uncompressed frame, in bytes
   Uint32 frameSize = bytesPerSample * imageRows * imageColumns * 
imageSamplesPerPixel;
 
+  // check for overflow
+  if (imageRows != 0 && frameSize / imageRows != (bytesPerSample * 
imageColumns * imageSamplesPerPixel))
+  {
+    DCMJPLS_WARN("Cannot decompress image because uncompressed representation 
would exceed maximum possible size of PixelData attribute.");
+    return EC_ElemLengthExceeds32BitField;
+  }
+
   // compute size of pixel data attribute, in bytes
   Uint32 totalSize = frameSize * imageFrames;
+
+  // check for overflow
+  if (totalSize == 0xFFFFFFFF || (frameSize != 0 && totalSize / frameSize != 
OFstatic_cast(Uint32, imageFrames)))
+  {
+    DCMJPLS_WARN("Cannot decompress image because uncompressed representation 
would exceed maximum possible size of PixelData attribute.");
+    return EC_ElemLengthExceeds32BitField;
+  }
+
   if (totalSize & 1) totalSize++; // align on 16-bit word boundary
 
   // assume we can cast the codec parameter to what we need
-- 
2.44.0


++++++ 0001-Fixed-possible-overflows-when-allocating-memory.patch ++++++
++++ 612 lines (skipped)

++++++ 0001-Fixed-two-segmentation-faults.patch ++++++
>From c78e434c0c5f9d932874f0b17a8b4ce305ca01f5 Mon Sep 17 00:00:00 2001
From: Marco Eichelberg <di...@offis.de>
Date: Wed, 13 Mar 2024 17:15:58 +0100
Subject: [PATCH] Fixed two segmentation faults.

Fixed two segmentations faults that could occur while processing an
invalid incoming DIMSE message due to insufficient error handling
causing a de-referenced NULL pointer.

Thanks to Nils Bars <nils.b...@rub.de> for the bug report and sample files.

This closes DCMTK issue #1114.
---
 dcmdata/libsrc/dcelem.cc |  9 ++++++++-
 dcmnet/libsrc/dimcmd.cc  | 33 ++++++++++++++++++---------------
 2 files changed, 26 insertions(+), 16 deletions(-)

diff --git a/dcmdata/libsrc/dcelem.cc b/dcmdata/libsrc/dcelem.cc
index 1524904be..3b9cc2bf7 100644
--- a/dcmdata/libsrc/dcelem.cc
+++ b/dcmdata/libsrc/dcelem.cc
@@ -1,6 +1,6 @@
 /*
  *
- *  Copyright (C) 1994-2023, OFFIS e.V.
+ *  Copyright (C) 1994-2024, OFFIS e.V.
  *  All rights reserved.  See COPYRIGHT file for details.
  *
  *  This software and supporting documentation were developed by
@@ -717,6 +717,13 @@ OFCondition DcmElement::loadValue(DcmInputStream *inStream)
             if (isStreamNew)
                 delete readStream;
         }
+        else
+        {
+            errorFlag = EC_InvalidStream; // incomplete dataset read from 
stream
+            DCMDATA_ERROR("DcmElement: " << getTagName() << " " << getTag()
+                << " larger (" << getLengthField() << ") than remaining bytes 
("
+                << getTransferredBytes() << ") in file, premature end of 
stream");
+        }
     }
     /* return result value */
     return errorFlag;
diff --git a/dcmnet/libsrc/dimcmd.cc b/dcmnet/libsrc/dimcmd.cc
index 6dca39546..ffd225f4b 100644
--- a/dcmnet/libsrc/dimcmd.cc
+++ b/dcmnet/libsrc/dimcmd.cc
@@ -1,6 +1,6 @@
 /*
  *
- *  Copyright (C) 1994-2022, OFFIS e.V.
+ *  Copyright (C) 1994-2024, OFFIS e.V.
  *  All rights reserved.  See COPYRIGHT file for details.
  *
  *  This software and supporting documentation were partly developed by
@@ -205,22 +205,25 @@ getString(DcmDataset *obj, DcmTagKey t, char *s, int 
maxlen, OFBool *spacePadded
             return parseErrorWithMsg("dimcmd:getString: string too small", t);
         } else {
             ec =  elem->getString(aString);
-            strncpy(s, aString, maxlen);
-            if (spacePadded)
+            if (ec.good())
             {
-                /* before we remove leading and tailing spaces we want to know
-                 * whether the string is actually space padded. Required to 
communicate
-                 * with dumb peers which send space padded UIDs and fail if 
they
-                 * receive correct UIDs back.
-                 *
-                 * This test can only detect space padded strings if
-                 * dcmEnableAutomaticInputDataCorrection is false; otherwise 
the padding
-                 * has already been removed by dcmdata at this stage.
-                 */
-                size_t s_len = strlen(s);
-                if ((s_len > 0)&&(s[s_len-1] == ' ')) *spacePadded = OFTrue; 
else *spacePadded = OFFalse;
+                strncpy(s, aString, maxlen);
+                if (spacePadded)
+                {
+                    /* before we remove leading and tailing spaces we want to 
know
+                     * whether the string is actually space padded. Required 
to communicate
+                     * with dumb peers which send space padded UIDs and fail 
if they
+                     * receive correct UIDs back.
+                     *
+                     * This test can only detect space padded strings if
+                     * dcmEnableAutomaticInputDataCorrection is false; 
otherwise the padding
+                     * has already been removed by dcmdata at this stage.
+                     */
+                    size_t s_len = strlen(s);
+                    if ((s_len > 0)&&(s[s_len-1] == ' ')) *spacePadded = 
OFTrue; else *spacePadded = OFFalse;
+                }
+                DU_stripLeadingAndTrailingSpaces(s);
             }
-            DU_stripLeadingAndTrailingSpaces(s);
         }
     }
     return (ec.good())? ec : DIMSE_PARSEFAILED;
-- 
2.44.0


++++++ 0001-Fixed-unchecked-typecasts-of-DcmItem-search-results.patch ++++++
++++ 1666 lines (skipped)

++++++ 0002-Fixed-unchecked-typecasts-and-fixed-LUT-handling.patch ++++++
>From 601b227eecaab33a3a3a11dc256d84b1a62f63af Mon Sep 17 00:00:00 2001
From: Marco Eichelberg <di...@offis.de>
Date: Mon, 15 Apr 2024 12:19:33 +0200
Subject: [PATCH 2/3] Fixed unchecked typecasts and fixed LUT handling.

This commit adds further fixes for unchecked typecasts of DcmItem::search()
results (see description of previous commit). Furthermore, this commit
specifically addresses the handling of look-up tables (LUTs) in module
dcmpstat, where attribute (0028,3006) LUTData may use either US or OW
value representation, and (0028,3002) LUTDescriptor may be either US or SS.
The code should now properly handle all permitted value representations.
LUTData is now always written as OW in order to avoid the 64k size limit
for US in explicit VR encoding.

Thanks to Martin Zeiser from the Cisco Talos team
<vulndiscov...@external.cisco.com> for the bug report (TALOS-2024-1957).

Together with the previous commit, this closes DCMTK issue #1120.
---
 dcmpstat/libsrc/dcmpstat.cc | 40 ++++++++++++++++-------
 dcmpstat/libsrc/dvpspl.cc   | 34 +++++++++++++------
 dcmpstat/libsrc/dvpssv.cc   | 34 +++++++++++++------
 dcmpstat/libsrc/dvpssvl.cc  | 25 +++++++++-----
 dcmpstat/libsrc/dvpstat.cc  | 65 +++++++++++++++++--------------------
 dcmpstat/libsrc/dvpsvl.cc   | 19 +++++++++--
 6 files changed, 139 insertions(+), 78 deletions(-)

diff --git a/dcmpstat/libsrc/dcmpstat.cc b/dcmpstat/libsrc/dcmpstat.cc
index 4a8e5af6c..a7d11abac 100644
--- a/dcmpstat/libsrc/dcmpstat.cc
+++ b/dcmpstat/libsrc/dcmpstat.cc
@@ -384,12 +384,16 @@ OFCondition DcmPresentationState::read(DcmItem &dset)
       {
          item = seq->getItem(0);
          stack.clear();
-         // LUTDescriptor can be US or SS. For now we only handle US.
+
+         // LUTDescriptor can be US or SS
          if ((EC_Normal == item->search((DcmTagKey 
&)modalityLUTDescriptor.getTag(),
-           stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US))
+           stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US 
|| stack.top()->ident() == EVR_SS))
          {
-           modalityLUTDescriptor = *((DcmUnsignedShort *)(stack.top()));
+           // We explicitly use DcmElement::operator=(), which works for US 
and SS
+           DcmElement *mLUTDescriptor = &modalityLUTDescriptor;
+           mLUTDescriptor->operator=(* OFstatic_cast(DcmElement *, 
stack.top()));
          }
+
          stack.clear();
          if ((EC_Normal == item->search((DcmTagKey 
&)modalityLUTExplanation.getTag(),
            stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_LO))
@@ -400,9 +404,11 @@ OFCondition DcmPresentationState::read(DcmItem &dset)
 
          // LUTData can be OW, US or SS. For now we only handle US.
          if ((EC_Normal == item->search((DcmTagKey &)modalityLUTData.getTag(),
-           stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US))
+           stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US 
|| stack.top()->ident() == EVR_OW))
          {
-           modalityLUTData = *((DcmUnsignedShort *)(stack.top()));
+           // we deliberately call DcmElement::operator=() here, which will 
work for both DcmUnsignedShort and DcmOtherByteOtherWord parameters
+           DcmElement *mdata = &modalityLUTData;
+           mdata->operator=(*(DcmElement *)(stack.top()));
          }
          stack.clear();
          if ((EC_Normal == item->search((DcmTagKey &)modalityLUTType.getTag(),
@@ -879,11 +885,13 @@ OFCondition DcmPresentationState::createFromImage(
       {
          item = seq->getItem(0);
          stack.clear();
-         // LUTDescriptor can be US or SS. For now we only handle US.
+         // LUTDescriptor can be US or SS
          if ((EC_Normal == item->search((DcmTagKey 
&)modalityLUTDescriptor.getTag(),
-           stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US))
+           stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US 
|| stack.top()->ident() == EVR_SS))
          {
-           modalityLUTDescriptor = *((DcmUnsignedShort *)(stack.top()));
+           // We explicitly use DcmElement::operator=(), which works for US 
and SS
+           DcmElement *mLUTDescriptor = &modalityLUTDescriptor;
+           mLUTDescriptor->operator=(* OFstatic_cast(DcmElement *, 
stack.top()));
          }
          stack.clear();
          if ((EC_Normal == item->search((DcmTagKey 
&)modalityLUTExplanation.getTag(),
@@ -895,9 +903,11 @@ OFCondition DcmPresentationState::createFromImage(
 
          // LUTData can be OW, US or SS. For now we only handle US.
          if ((EC_Normal == item->search((DcmTagKey &)modalityLUTData.getTag(),
-           stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US))
+           stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US 
|| stack.top()->ident() == EVR_OW))
          {
-           modalityLUTData = *((DcmUnsignedShort *)(stack.top()));
+           // we deliberately call DcmElement::operator=() here, which will 
work for both DcmUnsignedShort and DcmOtherByteOtherWord parameters
+           DcmElement *mdata = &modalityLUTData;
+           mdata->operator=(*(DcmElement *)(stack.top()));
          }
          stack.clear();
          if ((EC_Normal == item->search((DcmTagKey &)modalityLUTType.getTag(),
@@ -1247,10 +1257,16 @@ OFCondition DcmPresentationState::write(DcmItem &dset, 
OFBool replaceSOPInstance
         dseq = new DcmSequenceOfItems(DCM_ModalityLUTSequence);
         if (dseq)
         {
-          delem = new DcmUnsignedShort(modalityLUTDescriptor);
+          // we clone modalityLUTDescriptor in order to retain the VR (US or 
SS)
+          delem = OFstatic_cast(DcmElement *, modalityLUTDescriptor.clone());
           if (delem) ditem->insert(delem, OFTrue /*replaceOld*/); else 
result=EC_MemoryExhausted;
-          delem = new DcmUnsignedShort(modalityLUTData);
+
+          // we write LUTData as OW in order to avoid the 64 kByte limit for US
+          delem = new DcmOtherByteOtherWord(DCM_LUTData);
+          delem->operator=(modalityLUTData);
+          OFstatic_cast(DcmOtherByteOtherWord *, delem)->setVR(EVR_OW);
           if (delem) ditem->insert(delem, OFTrue /*replaceOld*/); else 
result=EC_MemoryExhausted;
+
           delem = new DcmLongString(modalityLUTType);
           if (delem) ditem->insert(delem, OFTrue /*replaceOld*/); else 
result=EC_MemoryExhausted;
           if (modalityLUTExplanation.getLength() >0)
diff --git a/dcmpstat/libsrc/dvpspl.cc b/dcmpstat/libsrc/dvpspl.cc
index ec4cccf97..f5574ab33 100644
--- a/dcmpstat/libsrc/dvpspl.cc
+++ b/dcmpstat/libsrc/dvpspl.cc
@@ -1,6 +1,6 @@
 /*
  *
- *  Copyright (C) 1999-2018, OFFIS e.V.
+ *  Copyright (C) 1999-2024, OFFIS e.V.
  *  All rights reserved.  See COPYRIGHT file for details.
  *
  *  This software and supporting documentation were developed by
@@ -24,6 +24,7 @@
 #include "dcmtk/dcmdata/dcdeftag.h"
 #include "dcmtk/dcmdata/dcsequen.h"
 #include "dcmtk/dcmdata/dcvrcs.h"
+#include "dcmtk/dcmdata/dcvrobow.h"
 #include "dcmtk/dcmpstat/dvpspl.h"
 #include "dcmtk/dcmpstat/dvpsdef.h"     /* for constants and macros */
 #include "dcmtk/dcmnet/dimse.h"
@@ -79,29 +80,36 @@ OFCondition DVPSPresentationLUT::read(DcmItem &dset, OFBool 
withSOPInstance)
   if (result==EC_Normal)
   {
     stack.clear();
-    if (EC_Normal == dset.search(DCM_PresentationLUTSequence, stack, 
ESM_fromHere, OFFalse))
+    if (EC_Normal == dset.search(DCM_PresentationLUTSequence, stack, 
ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_SQ))
     {
       seq=(DcmSequenceOfItems *)stack.top();
       if (seq->card() ==1)
       {
          item = seq->getItem(0);
          stack.clear();
-         if (EC_Normal == item->search((DcmTagKey 
&)presentationLUTDescriptor.getTag(), 
-           stack, ESM_fromHere, OFFalse))
+
+         // LUTDescriptor can be US or SS
+         if ((EC_Normal == item->search((DcmTagKey 
&)presentationLUTDescriptor.getTag(),
+           stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US 
|| stack.top()->ident() == EVR_SS))
          {
-           presentationLUTDescriptor = *((DcmUnsignedShort *)(stack.top()));
+           // We explicitly use DcmElement::operator=(), which works for US 
and SS
+           DcmElement *pLUTDescriptor = &presentationLUTDescriptor;
+           pLUTDescriptor->operator=(* OFstatic_cast(DcmElement *, 
stack.top()));
          }
+
          stack.clear();
          if (EC_Normal == item->search((DcmTagKey 
&)presentationLUTExplanation.getTag(), 
-           stack, ESM_fromHere, OFFalse))
+           stack, ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_LO))
          {
            presentationLUTExplanation = *((DcmLongString *)(stack.top()));
          }
          stack.clear();
          if (EC_Normal == item->search((DcmTagKey 
&)presentationLUTData.getTag(), 
-           stack, ESM_fromHere, OFFalse))
+           stack, ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_US || 
stack.top()->ident() == EVR_OW))
          {
-           presentationLUTData = *((DcmUnsignedShort *)(stack.top()));
+           // we deliberately call DcmElement::operator=() here, which will 
work for both DcmUnsignedShort and DcmOtherByteOtherWord parameters
+           DcmElement *pldata = &presentationLUTData;
+           pldata->operator=(*(DcmElement *)(stack.top()));
          }
       } else {
         result=EC_TagNotFound;
@@ -187,10 +195,16 @@ OFCondition DVPSPresentationLUT::write(DcmItem &dset, 
OFBool withSOPInstance)
         dseq = new DcmSequenceOfItems(DCM_PresentationLUTSequence);
         if (dseq)
         {
-          delem = new DcmUnsignedShort(presentationLUTDescriptor);
+          // we clone presentationLUTDescriptor in order to retain the VR (US 
or SS)
+          delem = OFstatic_cast(DcmElement *, 
presentationLUTDescriptor.clone());
           if (delem) ditem->insert(delem, OFTrue /*replaceOld*/); else 
result=EC_MemoryExhausted;
-          delem = new DcmUnsignedShort(presentationLUTData);
+
+          // we write LUTData as OW in order to avoid the 64 kByte limit for US
+          delem = new DcmOtherByteOtherWord(DCM_LUTData);
+          delem->operator=(presentationLUTData);
+          OFstatic_cast(DcmOtherByteOtherWord *, delem)->setVR(EVR_OW);
           if (delem) ditem->insert(delem, OFTrue /*replaceOld*/); else 
result=EC_MemoryExhausted;
+
           if (presentationLUTExplanation.getLength() >0)
           {
             delem = new DcmLongString(presentationLUTExplanation);
diff --git a/dcmpstat/libsrc/dvpssv.cc b/dcmpstat/libsrc/dvpssv.cc
index 8e3d49bd4..4a7fd0e30 100644
--- a/dcmpstat/libsrc/dvpssv.cc
+++ b/dcmpstat/libsrc/dvpssv.cc
@@ -1,6 +1,6 @@
 /*
  *
- *  Copyright (C) 1998-2018, OFFIS e.V.
+ *  Copyright (C) 1998-2024, OFFIS e.V.
  *  All rights reserved.  See COPYRIGHT file for details.
  *
  *  This software and supporting documentation were developed by
@@ -23,6 +23,7 @@
 #include "dcmtk/config/osconfig.h"    /* make sure OS specific configuration 
is included first */
 #include "dcmtk/dcmdata/dcdeftag.h"
 #include "dcmtk/dcmdata/dcsequen.h"
+#include "dcmtk/dcmdata/dcvrobow.h"
 #include "dcmtk/dcmpstat/dvpssv.h"
 #include "dcmtk/dcmpstat/dvpsri.h"      /* for DVPSReferencedImage */
 #include "dcmtk/dcmpstat/dvpsrsl.h"     /* DVPSReferencedSeries_PList */
@@ -75,29 +76,36 @@ OFCondition DVPSSoftcopyVOI::read(DcmItem &dset)
   if (result==EC_Normal)
   {
     stack.clear();
-    if (EC_Normal == dset.search(DCM_VOILUTSequence, stack, ESM_fromHere, 
OFFalse))
+    if (EC_Normal == dset.search(DCM_VOILUTSequence, stack, ESM_fromHere, 
OFFalse) && (stack.top()->ident() == EVR_SQ))
     {
       seq=(DcmSequenceOfItems *)stack.top();
       if (seq->card() ==1)
       {
          item = seq->getItem(0);
          stack.clear();
-         if (EC_Normal == item->search((DcmTagKey &)voiLUTDescriptor.getTag(), 
-           stack, ESM_fromHere, OFFalse))
+
+         // LUTDescriptor can be US or SS
+         if ((EC_Normal == item->search((DcmTagKey &)voiLUTDescriptor.getTag(),
+           stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US 
|| stack.top()->ident() == EVR_SS))
          {
-           voiLUTDescriptor = *((DcmUnsignedShort *)(stack.top()));
+           // We explicitly use DcmElement::operator=(), which works for US 
and SS
+           DcmElement *vLUTDescriptor = &voiLUTDescriptor;
+           vLUTDescriptor->operator=(* OFstatic_cast(DcmElement *, 
stack.top()));
          }
+
          stack.clear();
          if (EC_Normal == item->search((DcmTagKey 
&)voiLUTExplanation.getTag(), 
-           stack, ESM_fromHere, OFFalse))
+           stack, ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_LO))
          {
            voiLUTExplanation = *((DcmLongString *)(stack.top()));
          }
          stack.clear();
          if (EC_Normal == item->search((DcmTagKey &)voiLUTData.getTag(), 
-           stack, ESM_fromHere, OFFalse))
+           stack, ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_US || 
stack.top()->ident() == EVR_OW))
          {
-           voiLUTData = *((DcmUnsignedShort *)(stack.top()));
+           // we deliberately call DcmElement::operator=() here, which will 
work for both DcmUnsignedShort and DcmOtherByteOtherWord parameters
+           DcmElement *vldata = &voiLUTData;
+           vldata->operator=(*(DcmElement *)(stack.top()));
          }
       } else {
         result=EC_TagNotFound;
@@ -177,10 +185,16 @@ OFCondition DVPSSoftcopyVOI::write(DcmItem &dset)
       dseq = new DcmSequenceOfItems(DCM_VOILUTSequence);
       if (dseq)
       {
-        delem = new DcmUnsignedShort(voiLUTDescriptor);
+        // we clone voiLUTDescriptor in order to retain the VR (US or SS)
+        delem = OFstatic_cast(DcmElement *, voiLUTDescriptor.clone());
         if (delem) ditem->insert(delem, OFTrue /*replaceOld*/); else 
result=EC_MemoryExhausted;
-        delem = new DcmUnsignedShort(voiLUTData);
+
+        // we write LUTData as OW in order to avoid the 64 kByte limit for US
+        delem = new DcmOtherByteOtherWord(DCM_LUTData);
+        delem->operator=(voiLUTData);
+        OFstatic_cast(DcmOtherByteOtherWord *, delem)->setVR(EVR_OW);
         if (delem) ditem->insert(delem, OFTrue /*replaceOld*/); else 
result=EC_MemoryExhausted;
+
         if (voiLUTExplanation.getLength() >0)
         {
           delem = new DcmLongString(voiLUTExplanation);
diff --git a/dcmpstat/libsrc/dvpssvl.cc b/dcmpstat/libsrc/dvpssvl.cc
index d1532db5c..efcb6a26b 100644
--- a/dcmpstat/libsrc/dvpssvl.cc
+++ b/dcmpstat/libsrc/dvpssvl.cc
@@ -1,6 +1,6 @@
 /*
  *
- *  Copyright (C) 1999-2023, OFFIS e.V.
+ *  Copyright (C) 1999-2024, OFFIS e.V.
  *  All rights reserved.  See COPYRIGHT file for details.
  *
  *  This software and supporting documentation were developed by
@@ -72,7 +72,7 @@ OFCondition DVPSSoftcopyVOI_PList::read(DcmItem &dset)
   DcmSequenceOfItems *dseq=NULL;
   DcmItem *ditem=NULL;
 
-  if (EC_Normal == dset.search(DCM_SoftcopyVOILUTSequence, stack, 
ESM_fromHere, OFFalse))
+  if (EC_Normal == dset.search(DCM_SoftcopyVOILUTSequence, stack, 
ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_SQ))
   {
     dseq=(DcmSequenceOfItems *)stack.top();
     if (dseq)
@@ -249,29 +249,36 @@ OFCondition DVPSSoftcopyVOI_PList::createFromImage(
   if (result==EC_Normal)
   {
     stack.clear();
-    if (EC_Normal == dset.search(DCM_VOILUTSequence, stack, ESM_fromHere, 
OFFalse))
+    if (EC_Normal == dset.search(DCM_VOILUTSequence, stack, ESM_fromHere, 
OFFalse) && (stack.top()->ident() == EVR_SQ))
     {
       seq=(DcmSequenceOfItems *)stack.top();
       if (seq->card() > 0)
       {
          item = seq->getItem(0);
          stack.clear();
-         if (EC_Normal == item->search((DcmTagKey &)voiLUTDescriptor.getTag(),
-           stack, ESM_fromHere, OFFalse))
+
+         // LUTDescriptor can be US or SS
+         if ((EC_Normal == item->search((DcmTagKey &)voiLUTDescriptor.getTag(),
+           stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US 
|| stack.top()->ident() == EVR_SS))
          {
-           voiLUTDescriptor = *((DcmUnsignedShort *)(stack.top()));
+           // We explicitly use DcmElement::operator=(), which works for US 
and SS
+           DcmElement *vLUTDescriptor = &voiLUTDescriptor;
+           vLUTDescriptor->operator=(* OFstatic_cast(DcmElement *, 
stack.top()));
          }
+
          stack.clear();
          if (EC_Normal == item->search((DcmTagKey &)voiLUTExplanation.getTag(),
-           stack, ESM_fromHere, OFFalse))
+           stack, ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_LO))
          {
            voiLUTExplanation = *((DcmLongString *)(stack.top()));
          }
          stack.clear();
          if (EC_Normal == item->search((DcmTagKey &)voiLUTData.getTag(),
-           stack, ESM_fromHere, OFFalse))
+           stack, ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_US || 
stack.top()->ident() == EVR_OW))
          {
-           voiLUTData = *((DcmUnsignedShort *)(stack.top()));
+           // we deliberately call DcmElement::operator=() here, which will 
work for both DcmUnsignedShort and DcmOtherByteOtherWord parameters
+           DcmElement *vldata = &voiLUTData;
+           vldata->operator=(*(DcmElement *)(stack.top()));
          }
       } else result=EC_TagNotFound;
     }
diff --git a/dcmpstat/libsrc/dvpstat.cc b/dcmpstat/libsrc/dvpstat.cc
index ce2f5ad5f..4bfe8f9cb 100644
--- a/dcmpstat/libsrc/dvpstat.cc
+++ b/dcmpstat/libsrc/dvpstat.cc
@@ -1,6 +1,6 @@
 /*
  *
- *  Copyright (C) 1998-2021, OFFIS e.V.
+ *  Copyright (C) 1998-2024, OFFIS e.V.
  *  All rights reserved.  See COPYRIGHT file for details.
  *
  *  This software and supporting documentation were developed by
@@ -578,14 +578,14 @@ OFCondition DVPresentationState::attachImage(DcmDataset 
*dataset, OFBool transfe
       currentImageSelectedFrame = 1; // default: first frame
 
       // get Modality
-      if (EC_Normal == dataset->search(DCM_Modality, stack, ESM_fromHere, 
OFFalse))
+      if (EC_Normal == dataset->search(DCM_Modality, stack, ESM_fromHere, 
OFFalse) && (stack.top()->ident() == EVR_CS))
       {
         currentImageModality = *((DcmCodeString *)(stack.top()));
       }
       stack.clear();
 
       // determine default Presentation LUT Shape
-      if (EC_Normal == dataset->search(DCM_PhotometricInterpretation, stack, 
ESM_fromHere, OFFalse))
+      if (EC_Normal == dataset->search(DCM_PhotometricInterpretation, stack, 
ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_CS))
       {
          DcmCodeString *photometricInterpretation = (DcmCodeString 
*)(stack.top());
          if (photometricInterpretation->getVM() == 1)
@@ -598,12 +598,12 @@ OFCondition DVPresentationState::attachImage(DcmDataset 
*dataset, OFBool transfe
       stack.clear();
 
       // get SOP class UID and SOP instance UID.
-      if ((EC_Normal == result)&&(EC_Normal == 
dataset->search(DCM_SOPClassUID, stack, ESM_fromHere, OFFalse)))
+      if ((EC_Normal == result)&&(EC_Normal == 
dataset->search(DCM_SOPClassUID, stack, ESM_fromHere, OFFalse)) && 
(stack.top()->ident() == EVR_UI))
       {
         result = ((DcmUniqueIdentifier 
*)(stack.top()))->getString(currentImageSOPClassUID);
       }
       stack.clear();
-      if ((EC_Normal == result)&&(EC_Normal == 
dataset->search(DCM_SOPInstanceUID, stack, ESM_fromHere, OFFalse)))
+      if ((EC_Normal == result)&&(EC_Normal == 
dataset->search(DCM_SOPInstanceUID, stack, ESM_fromHere, OFFalse)) && 
(stack.top()->ident() == EVR_UI))
       {
         result = ((DcmUniqueIdentifier 
*)(stack.top()))->getString(currentImageSOPInstanceUID);
       }
@@ -1124,40 +1124,36 @@ OFCondition DVPresentationState::setGammaVOILUT(double 
gammaValue, DVPSObjectApp
         numEntries16 = (Uint16)numberOfEntries;
 
       /* LUT Descriptor */
-      DcmElement *lutDescriptor = NULL;
-      if (firstMapped < 0)
+      DcmUnsignedShort *lutDescriptor = new 
DcmUnsignedShort(DcmTag(DCM_LUTDescriptor, EVR_US));
+      if (lutDescriptor == NULL) status = EC_MemoryExhausted;
+      else
       {
-        // LUT Descriptor is SS
-        lutDescriptor = new DcmSignedShort(DcmTag(DCM_LUTDescriptor, EVR_SS));
-        if (lutDescriptor != NULL)
+        if (firstMapped < 0)
         {
-            status = lutDescriptor->putSint16((Sint16)numEntries16, 0);
-            if (EC_Normal == status)
-              status = lutDescriptor->putSint16((Sint16)firstMapped, 1);
-            if (EC_Normal == status)
-              status = lutDescriptor->putSint16((Sint16)numberOfBits, 2);
-        } else
-          status = EC_MemoryExhausted;
-      } else {
-        // LUT Descriptor is US
-        lutDescriptor = new DcmUnsignedShort(DcmTag(DCM_LUTDescriptor, 
EVR_US));
-        if (lutDescriptor != NULL)
-        {
-            status = lutDescriptor->putUint16(numEntries16, 0);
-            if (EC_Normal == status)
-              status = lutDescriptor->putUint16((Uint16)firstMapped, 1);
-            if (EC_Normal == status)
-              status = lutDescriptor->putUint16((Uint16)numberOfBits, 2);
-        } else
-            status = EC_MemoryExhausted;
+          // LUT Descriptor is SS
+          DcmSignedShort ldesc(DcmTag(DCM_LUTDescriptor, EVR_SS));
+          status = ldesc.putSint16((Sint16)numEntries16, 0);
+          if (EC_Normal == status) status = 
ldesc.putSint16((Sint16)firstMapped, 1);
+          if (EC_Normal == status) status = 
ldesc.putSint16((Sint16)numberOfBits, 2);
+          if (EC_Normal == status)
+          {
+            // copy content of SS element into DcmUnsignedShort using 
DcmElement::operator=
+            DcmElement *ld = lutDescriptor;
+            ld->operator=(ldesc);
+          }
+        } else {
+          // LUT Descriptor is US
+          status = lutDescriptor->putUint16(numEntries16, 0);
+          if (EC_Normal == status) status = 
lutDescriptor->putUint16((Uint16)firstMapped, 1);
+          if (EC_Normal == status) status = 
lutDescriptor->putUint16((Uint16)numberOfBits, 2);
+        }
       }
 
       /* LUT Data */
-      DcmElement *lutData = NULL;
+      DcmUnsignedShort *lutData = NULL;
       if (status == EC_Normal)
       {
-        // LUT Data as OW, because of max size = 64K
-        lutData = new DcmOtherByteOtherWord(DcmTag(DCM_LUTData, EVR_OW));
+        lutData = new DcmUnsignedShort(DcmTag(DCM_LUTData, EVR_US));
         if (lutData != NULL)
           status = lutData->putUint16Array(data, numberOfEntries);
         else
@@ -1186,15 +1182,14 @@ OFCondition DVPresentationState::setGammaVOILUT(double 
gammaValue, DVPSObjectApp
       if (status == EC_Normal)
       {
         if ((lutDescriptor != NULL) && (lutData != NULL) && (lutExplanation != 
 NULL))
-          status = setVOILUT(*(DcmUnsignedShort *)lutDescriptor, 
*(DcmUnsignedShort *)lutData, *lutExplanation, applicability);
+          status = setVOILUT(*lutDescriptor, *lutData, *lutExplanation, 
applicability);
       }
 
       /* delete temporary dcmtk structures */
       delete lutDescriptor;
       delete lutData;
       delete lutExplanation;
-    } else
-      status = EC_MemoryExhausted;
+    } else status = EC_MemoryExhausted;
     delete[] data;
   }
   return status;
diff --git a/dcmpstat/libsrc/dvpsvl.cc b/dcmpstat/libsrc/dvpsvl.cc
index b10b83f20..fdba0a0e0 100644
--- a/dcmpstat/libsrc/dvpsvl.cc
+++ b/dcmpstat/libsrc/dvpsvl.cc
@@ -59,9 +59,24 @@ OFCondition DVPSVOILUT::read(DcmItem &dset)
   OFCondition result = EC_Normal;
   DcmStack stack;
 
-  READ_FROM_DATASET(DcmUnsignedShort, EVR_US, voiLUTDescriptor)
+  // LUTDescriptor can be US or SS
+  if ((EC_Normal == dset.search((DcmTagKey &)voiLUTDescriptor.getTag(),
+    stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US || 
stack.top()->ident() == EVR_SS))
+  {
+    // We explicitly use DcmElement::operator=(), which works for US and SS
+    DcmElement *vLUTDescriptor = &voiLUTDescriptor;
+    vLUTDescriptor->operator=(* OFstatic_cast(DcmElement *, stack.top()));
+  }
+
   READ_FROM_DATASET(DcmLongString, EVR_LO, voiLUTExplanation)
-  READ_FROM_DATASET(DcmUnsignedShort, EVR_US, voiLUTData)
+
+  stack.clear();
+  if ((EC_Normal == dset.search((DcmTagKey &)voiLUTData.getTag(), stack, 
ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US || 
stack.top()->ident() == EVR_OW))
+  {
+    // we deliberately call DcmElement::operator=() here, which will work for 
both DcmUnsignedShort and DcmOtherByteOtherWord parameters
+    DcmElement *vldata = &voiLUTData;
+    vldata->operator=(*(DcmElement *)(stack.top()));
+  }
 
   if (EC_Normal == result)
   {
-- 
2.44.0


++++++ 0003-Fixed-wrong-error-handling-previous-commit.patch ++++++
>From 7d54f8efec995e5601d089fa17b0625c2b41af23 Mon Sep 17 00:00:00 2001
From: Joerg Riesmeier <di...@jriesmeier.com>
Date: Mon, 22 Apr 2024 12:11:11 +0200
Subject: [PATCH 3/3] Fixed wrong error handling (previous commit).

Fixed wrong error handling introduced with the previous commit.
---
 dcmrt/libsrc/drttypes.cc |  6 +++---
 dcmsr/libsrc/dsrtypes.cc | 32 ++++++++++++++++++++------------
 2 files changed, 23 insertions(+), 15 deletions(-)

diff --git a/dcmrt/libsrc/drttypes.cc b/dcmrt/libsrc/drttypes.cc
index 77ff1674c..097ab9727 100644
--- a/dcmrt/libsrc/drttypes.cc
+++ b/dcmrt/libsrc/drttypes.cc
@@ -210,11 +210,11 @@ OFCondition 
DRTTypes::getAndCheckStringValueFromDataset(DcmItem &dataset,
 {
     DcmStack stack;
     OFCondition result = dataset.search(tagKey, stack, ESM_fromHere, OFFalse 
/*searchIntoSub*/);
-    if (result.good() && stack.top()->isElement())
+    if (result.good())
     {
-        DcmElement *element = OFstatic_cast(DcmElement *, stack.top());
-        if (element != NULL)
+        if (stack.top()->isElement())
         {
+            DcmElement *element = OFstatic_cast(DcmElement *, stack.top());
             if (checkElementValue(*element, vm, type, result, moduleName))
                 result = element->getOFString(stringValue, 0);
             else
diff --git a/dcmsr/libsrc/dsrtypes.cc b/dcmsr/libsrc/dsrtypes.cc
index a9d621859..166bfabff 100644
--- a/dcmsr/libsrc/dsrtypes.cc
+++ b/dcmsr/libsrc/dsrtypes.cc
@@ -1178,13 +1178,17 @@ OFCondition 
DSRTypes::getAndCheckElementFromDataset(DcmItem &dataset,
     DcmStack stack;
     const DcmTagKey tagKey = delem.getTag();
     OFCondition result = dataset.search(tagKey, stack, ESM_fromHere, OFFalse 
/*searchIntoSub*/);
-    if (result.good() && stack.top()->isElement())
+    if (result.good())
     {
-        /* copy object from search stack */
-        result = delem.copyFrom(*stack.top());
-        /* we need a reference to the original element in order to determine 
the SpecificCharacterSet */
-        if (!checkElementValue(OFstatic_cast(DcmElement *, stack.top()), 
tagKey, vm, type, result, moduleName, acceptViolation))
-            result = SR_EC_InvalidValue;
+        if (stack.top()->isElement())
+        {
+            /* copy object from search stack */
+            result = delem.copyFrom(*stack.top());
+            /* we need a reference to the original element in order to 
determine the SpecificCharacterSet */
+            if (!checkElementValue(OFstatic_cast(DcmElement *, stack.top()), 
tagKey, vm, type, result, moduleName, acceptViolation))
+                result = SR_EC_InvalidValue;
+        } else
+            result = EC_CorruptedData;
     }
     /* the element could not be found in the dataset */
     else if (!checkElementValue(delem, vm, type, result, moduleName, 
acceptViolation))
@@ -1203,13 +1207,17 @@ OFCondition 
DSRTypes::getAndCheckStringValueFromDataset(DcmItem &dataset,
 {
     DcmStack stack;
     OFCondition result = dataset.search(tagKey, stack, ESM_fromHere, OFFalse 
/*searchIntoSub*/);
-    if (result.good() && stack.top()->isElement())
+    if (result.good())
     {
-        DcmElement *delem = OFstatic_cast(DcmElement *, stack.top());
-        /* we need a reference to the original element in order to determine 
the SpecificCharacterSet */
-        if (!checkElementValue(delem, tagKey, vm, type, result, moduleName, 
acceptViolation))
-            result = SR_EC_InvalidValue;
-        delem->getOFString(stringValue, 0);
+        if (stack.top()->isElement())
+        {
+            DcmElement *delem = OFstatic_cast(DcmElement *, stack.top());
+            /* we need a reference to the original element in order to 
determine the SpecificCharacterSet */
+            if (!checkElementValue(delem, tagKey, vm, type, result, 
moduleName, acceptViolation))
+                result = SR_EC_InvalidValue;
+            delem->getOFString(stringValue, 0);
+        } else
+            result = EC_CorruptedData;
     } else {
         if ((type == "1") || (type == "2"))
         {
-- 
2.44.0

Reply via email to