Skip to content

Commit

Permalink
Add error check for bulk data > 2GiB
Browse files Browse the repository at this point in the history
This way a proper error messages will be returned instead of a
NegativeArraySizeExpcetion.
  • Loading branch information
dzelemba committed Sep 24, 2020
1 parent f0d707d commit e83668d
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
target/
.recommenders/
.metadata/
.vscode/
14 changes: 13 additions & 1 deletion dcm4che-core/src/main/java/org/dcm4che3/io/DicomInputStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ public enum IncludeBulkData { NO, YES, URI }
"Implicit VR Big Endian encoded DICOM Stream";
private static final String DEFLATED_WITH_ZLIB_HEADER =
"Deflated DICOM Stream with ZLIB Header";
/* VisibleForTesting */ static final String VALUE_TOO_LARGE =
"tag value too large, must be less than 2Gib";

private static final int ZLIB_HEADER = 0x789c;
private static final int DEF_ALLOCATE_LIMIT = 0x4000000; // 64MiB
Expand Down Expand Up @@ -412,6 +414,11 @@ public void readFully(short[] s, int off, int len) throws IOException {
}
}

private DicomStreamException tagValueTooLargeException() {
return new DicomStreamException(
String.format("0x%s %s", TagUtils.toHexString(tag), VALUE_TOO_LARGE));
}

public void readHeader() throws IOException {
byte[] buf = buffer;
tagPos = pos;
Expand All @@ -427,6 +434,7 @@ public void readHeader() throws IOException {
if (explicitVR) {
vr = VR.valueOf(encodedVR = ByteUtils.bytesToVR(buf, 4));
if (vr.headerLength() == 8) {
// This length can't overflow since length field is only 16 bits in this case.
length = ByteUtils.bytesToUShort(buf, 6, bigEndian);
return;
}
Expand All @@ -436,6 +444,9 @@ public void readHeader() throws IOException {
}
}
length = ByteUtils.bytesToInt(buf, 4, bigEndian);
if (length < -1) {
throw tagValueTooLargeException();
}
}

public boolean readItemHeader() throws IOException {
Expand Down Expand Up @@ -776,7 +787,8 @@ public byte[] readValue() throws IOException {
int valLen = length;
try {
if (valLen < 0)
throw new EOFException(); // assume InputStream length < 2 GiB
throw new IOException(
"internal error: length should have been validated in readHeader");
int allocLen = allocateLimit >= 0
? Math.min(valLen, allocateLimit)
: valLen;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ public void testImplicitVR() throws Exception {
assertEquals(1, attrs.getInt(Tag.SamplesPerPixel, 0));
}

@Test
public void testBulkDataLimit() throws Exception {
try {
readFrom("3gb-bulk-data-truncated", IncludeBulkData.URI);
} catch (DicomStreamException e) {
assertEquals("0x7FE00010 " + DicomInputStream.VALUE_TOO_LARGE, e.getMessage());
}
}

@Test
public void testSpoolDataFragments() throws Exception {
List<File> bulkDataFiles;
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
<remoteResource>US-RGB-8-esopecho</remoteResource>
<remoteResource>YBR_422.dcm</remoteResource>
<remoteResource>YBR_FULL-RLE.dcm</remoteResource>
<remoteResource>3gb-bulk-data-truncated</remoteResource>
</remoteResources>
<sourceEncoding>UTF-8</sourceEncoding>
</remoteResourcesBundle>

0 comments on commit e83668d

Please sign in to comment.