Skip to content

CodeString.writeBytes() throws on valid multivalued CS tag when individual value exceeds maxLength of 16 #487

@AlasDiablo

Description

@AlasDiablo

CodeString.writeBytes() throws on valid multivalued CS tag when individual value exceeds maxLength of 16

Environment

  • dcmjs version: 0.50.1

Description

When writing a DICOM dictionary to a file, dcmjs throws an error on a multivalued CS (CodeString) tag. The validation in writeBytes checks the length of each value (after splitting by \) against the CS max length of 16, but the private tag contains values that exceed this limit (e.g. GE_TAG_TRIGGER_TIME is 19 characters).

Steps to Reproduce

  1. Load a DICOM file containing the following private tag:
(Group,Element) TAG Description VR VM Length Value
(07A5,1042) Unknown Tag & Data CS 5 98 GE_TAG_TRIGGER_TIME\GE_TAG_MID_SCAN_TIME\GE_TAG_ATTRIBUTE_MODIFICATION_DATETIME\GE_TAG\GE_TAG_ACQ
  1. Attempt to write the DICOM dictionary back to a file (e.g. via DicomDict.write()).

Expected Behaviour

The tag values should be copied as-is from the original file without validation errors, since the data was already present in the source DICOM file.

Actual Behavior

An error is thrown:

Value exceeds max length, vr: CS, value: GE_TAG_TRIGGER_TIME, length: 19

Error: Value exceeds max length, vr: CS, value: GE_TAG_TRIGGER_TIME, length: 19
    at CodeString2.writeBytes (dcmjs.js:6800:22)
    at CodeString2.writeBytes (dcmjs.js:6890:94)
    at Tag2.write (dcmjs.js:8603:26)
    at dcmjs.js:8867:24
    at Array.forEach (<anonymous>)
    at DicomMessage2.write (dcmjs.js:8864:18)
    at DicomDict2.write (dcmjs.js:8115:22)

Analysis

The CS VR has a max length of 16 per value.

this.maxLength = 16;

The writeBytes method validates each value in a multivalued tag against this limit. GE_TAG_TRIGGER_TIME is 19 characters, which triggers the error.

for (var i = 0; i < valarr.length; i++) {
var checkValue = valarr[i],
checklen = lengths[i],
isString = false,
displaylen = checklen;
if (checkValue === null || allowInvalidVRLength) {
valid = true;
} else if (this.checkLength) {
valid = this.checkLength(checkValue);
} else if (this.maxCharLength) {
var check = this.maxCharLength; //, checklen = checkValue.length;
valid = checkValue.length <= check;
displaylen = checkValue.length;
isString = true;
} else if (this.maxLength) {
valid = checklen <= this.maxLength;
}
if (!valid) {
var errmsg =
"Value exceeds max length, vr: " +
this.type +
", value: " +
checkValue +
", length: " +
displaylen;
if (isString) log.info(errmsg);
else throw new Error(errmsg);
}
total += checklen;
}

This is a private/vendor-specific tag (07A5,1042) from GE. While the values technically violate the DICOM standard's CS length constraint, they are present in real-world DICOM files. dcmjs should arguably be more lenient when writing back data that was successfully read, or at least provide an option to skip validation on writing.

Hex Dump of the Original Tag

Hex View  00 01 02 03 04 05 06 07  08 09 0A 0B 0C 0D 0E 0F

000020D0           07 42 10 43 53  62 00 47 45 5F 54 41 47     .B.CSb.GE_TAG
000020E0  5F 54 52 49 47 47 45 52  5F 54 49 4D 45 5C 47 45  _TRIGGER_TIME\GE
000020F0  5F 54 41 47 5F 4D 49 44  5F 53 43 41 4E 5F 54 49  _TAG_MID_SCAN_TI
00002100  4D 45 5C 47 45 5F 54 41  47 5F 41 54 54 52 49 42  ME\GE_TAG_ATTRIB
00002110  55 54 45 5F 4D 4F 44 49  46 49 43 41 54 49 4F 4E  UTE_MODIFICATION
00002120  5F 44 41 54 45 54 49 4D  45 5C 47 45 5F 54 41 47  _DATETIME\GE_TAG
00002130  5C 47 45 5F 54 41 47 5F  41 43 51                 \GE_TAG_ACQ

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions