Bug #970
closedIncorrect handling of malformed JPEG bitstream
0%
Description
Apparently the IJG JPEG code embedded into DCMTK does not correctly handle certain invalid JPEG bitstreams that contain inconsistent start-of-scan (SOS) markers.
The issue is discussed in https://bugs.chromium.org/p/chromium/issues/detail?id=258723 and has been fixed in Chromium and libjpeg-turbo. The fix can be readily
applied to DCMTK as well:
diff --git a/dcmjpeg/libijg12/jdmarker.c b/dcmjpeg/libijg12/jdmarker.c index 355835c7f..4d1e63f84 100644 --- a/dcmjpeg/libijg12/jdmarker.c +++ b/dcmjpeg/libijg12/jdmarker.c @@ -346,6 +346,12 @@ get_sos (j_decompress_ptr cinfo) compptr->dc_tbl_no, compptr->ac_tbl_no); } + /* This CSi (cc) should differ from the previous CSi */ + for (ci = 0; ci < i; ci++) { + if (cinfo->cur_comp_info[ci] == compptr) + ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); + } + /* Collect the additional scan parameters Ss, Se, Ah/Al. */ INPUT_BYTE(cinfo, c, return FALSE); cinfo->Ss = c; diff --git a/dcmjpeg/libijg16/jdmarker.c b/dcmjpeg/libijg16/jdmarker.c index f2b6188e8..381f58226 100644 --- a/dcmjpeg/libijg16/jdmarker.c +++ b/dcmjpeg/libijg16/jdmarker.c @@ -346,6 +346,12 @@ get_sos (j_decompress_ptr cinfo) compptr->dc_tbl_no, compptr->ac_tbl_no); } + /* This CSi (cc) should differ from the previous CSi */ + for (ci = 0; ci < i; ci++) { + if (cinfo->cur_comp_info[ci] == compptr) + ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); + } + /* Collect the additional scan parameters Ss, Se, Ah/Al. */ INPUT_BYTE(cinfo, c, return FALSE); cinfo->Ss = c; diff --git a/dcmjpeg/libijg8/jdmarker.c b/dcmjpeg/libijg8/jdmarker.c index 22f18e567..d7d4a1c37 100644 --- a/dcmjpeg/libijg8/jdmarker.c +++ b/dcmjpeg/libijg8/jdmarker.c @@ -346,6 +346,12 @@ get_sos (j_decompress_ptr cinfo) compptr->dc_tbl_no, compptr->ac_tbl_no); } + /* This CSi (cc) should differ from the previous CSi */ + for (ci = 0; ci < i; ci++) { + if (cinfo->cur_comp_info[ci] == compptr) + ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); + } + /* Collect the additional scan parameters Ss, Se, Ah/Al. */ INPUT_BYTE(cinfo, c, return FALSE); cinfo->Ss = c;
Reported 2021-03-04 by Christian Wetzel <wetzel@phoenix-pacs.de>.
Files
Updated by Marco Eichelberg over 4 years ago
- Category set to Library
- Target version set to 3.6.7
- Module set to dcmjpeg
Updated by Marco Eichelberg over 4 years ago
- File issue_970.dcm issue_970.dcm added
The attached JPEG-compressed DICOM image, based on https://lcamtuf.coredump.cx/jpeg_leak/, demonstrates the issue. The output of a "jpegdump" of the JPEG bitstream contains the following section:
Offset 0x0130 Marker 0xffda SOS Start of Scan length variable 0x0c JPEG_SOS_Parameters: nComponentsPerScan = 3 component 0 ScanComponentSelector = 3 DCEntropyCodingTableSelector = 0 ACEntropyCodingTableSelector = 0 MappingTableSelector(LS) = 0 component 1 ScanComponentSelector = 2 DCEntropyCodingTableSelector = 1 ACEntropyCodingTableSelector = 1 MappingTableSelector(LS) = 17 component 2 ScanComponentSelector = 3 DCEntropyCodingTableSelector = 1 ACEntropyCodingTableSelector = 1 MappingTableSelector(LS) = 17 StartOfSpectralOrPredictorSelection/NearLosslessDifferenceBound(LS) = 0 EndOfSpectralSelection/InterleaveMode(LS) = 63 SuccessiveApproximationBitPositionHigh = 0 SuccessiveApproximationBitPositionLowOrPointTransform = 0
Note that component 0 and 2 both have "ScanComponentSelector = 3", and there is no entry with "ScanComponentSelector = 1".
dcmdjpeg should refuse to decode this image, because doing so would cause uninitialized memory to appear in the output, but currently only prints a warning and produces a decompressed image.
Updated by Marco Eichelberg over 4 years ago
- Status changed from New to Closed
- Assignee set to Marco Eichelberg
- Estimated time set to 2:00 h
Closed by commit #e8161b1e4.