From d106034dd849c2adafeb6a2073ed8e31393fdbc9 Mon Sep 17 00:00:00 2001 From: Alexander Karaivanov Date: Mon, 15 Feb 2021 08:47:07 +0100 Subject: [PATCH 1/2] Fix crash in DcmFileFormat::readUntilTag() when reading a partial meta info Use case: * DcmFileFormat::readUntilTag() (called from DcmFileFormat::read()) tries to read DcmMetaInfo which is partially available in input stream * DcmMetaInfo::read() returns EC_StreamNotifyClient * DcmFileFormat::readUntilTag() does not check the returned condition and tries to use DcmMetaInfo (by calling lookForXfer()) even though the object is not completely read. By using it, DcmFileFormat changes meta info's current elemetnt to have index -1. * next time DcmFileFormat::readUntilTag() is called, it tries to finish reading last incomplete object. Having its current index set to -1 that leads to a crash Fix: * check returned condition from DcmMetaInfo::read() and exit early if it is bad --- dcmdata/libsrc/dcfilefo.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dcmdata/libsrc/dcfilefo.cc b/dcmdata/libsrc/dcfilefo.cc index 69eacdc29..a5c8a3f5c 100644 --- a/dcmdata/libsrc/dcfilefo.cc +++ b/dcmdata/libsrc/dcfilefo.cc @@ -736,6 +736,8 @@ OFCondition DcmFileFormat::readUntilTag(DcmInputStream &inStream, { // do read meta header not in given transfer syntax (always Little Endian Explicit) errorFlag = metaInfo->read(inStream, EXS_Unknown, glenc, maxReadLength); + if (errorFlag.bad()) + return errorFlag; } // determine xfer from tag (0002,0010) in the meta header From 80a0851a8c2cdd6860b09a61fd81d4c1f69be0ae Mon Sep 17 00:00:00 2001 From: Alexander Karaivanov Date: Mon, 15 Feb 2021 08:59:10 +0100 Subject: [PATCH 2/2] Fix bug in DcmMetaInfo::read() when reading incomplete in stream object Use case: * DcmMetaInfo::read() is called to read object which is partially available in input stream * Transfer syntax is detected from the preamble and is stored in member variable Xfer * On the second call to DcmMetaInfo::read() the stored transfer syntax is overwritten with the value of the input transfer syntax (typically EXS_Unknown). This time preamble is already read and is not used to detect transfer syntax. If input parameter is equal to EXS_Unknown current transfer syntax is maintained in local vairable newxfer will also be EXS_Unknown. Calling readGroupLength() with EXS_Unknown will return condition EC_IllegalCall and that is the be also the returned value of DcmMetaInfo::read() Fix: * do not overwrite store transfer syntax in Xfer if object's transfer has started * use stored transfer syntax on consecutive calls --- dcmdata/libsrc/dcmetinf.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dcmdata/libsrc/dcmetinf.cc b/dcmdata/libsrc/dcmetinf.cc index 8bef02b59..648d003ff 100644 --- a/dcmdata/libsrc/dcmetinf.cc +++ b/dcmdata/libsrc/dcmetinf.cc @@ -407,7 +407,8 @@ OFCondition DcmMetaInfo::read(DcmInputStream &inStream, errorFlag = EC_IllegalCall; else { - Xfer = xfer; + if (getTransferState() == ERW_init) + Xfer = xfer; E_TransferSyntax newxfer = xfer; // figure out if the stream reported an error errorFlag = inStream.status(); @@ -429,7 +430,8 @@ OFCondition DcmMetaInfo::read(DcmInputStream &inStream, fStartPosition = inStream.tell(); setLengthField(0); } - } + } else + newxfer = Xfer; // use stored transfer syntax which was determined from preamble if (getTransferState() == ERW_inWork && getLengthField() == 0) { if (inStream.avail() < OFstatic_cast(offile_off_t, DCM_GroupLengthElementLength))