Skip to content

Commit 2c33aa4

Browse files
committed
simplify BOT construction
avoid overflow for length value in dcm_parse_encapsulated_frame
1 parent ac71ff4 commit 2c33aa4

File tree

1 file changed

+29
-52
lines changed

1 file changed

+29
-52
lines changed

src/dicom-parse.c

Lines changed: 29 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -955,65 +955,38 @@ bool dcm_parse_pixeldata_offsets(DcmError **error,
955955
// each frame
956956

957957
dcm_log_info("building Offset Table from Pixel Data");
958+
// by definition the first offset is 0
959+
offsets[0] = 0;
958960

959961
// 0 in the BOT is the offset to the start of frame 1, ie. here
960962
*first_frame_offset = position;
961-
// each frame may consist of several fragments, so we need to scan each fragment to find the next frame
962-
if (!read_tag(&state, &tag, &position)) {
963-
dcm_error_set(error, DCM_ERROR_CODE_PARSE,
964-
"building BasicOffsetTable failed",
965-
"failed to read tag");
966-
return false;
967-
}
968-
// all fragments belong to the only frame
969-
if ( num_frames == 1 ) {
970-
// according to the standard the first frame's offset is 0
971-
offsets[0] = 0;
972-
} else {
973-
// 1 fragment shall contain 1 frame
974-
int fragment_idx = 0;
975-
offsets[fragment_idx] = 0; // by definition the first fragment is at offset 0
976-
fragment_idx++;
977-
while( tag != TAG_SQ_DELIM ) {
978-
if ( tag != TAG_ITEM || !read_uint32(&state, &length, &position)) {
979-
dcm_error_set(error, DCM_ERROR_CODE_PARSE,
980-
"building BasicOffsetTable failed",
981-
"failed to read fragment");
982-
return false;
983-
}
984-
// skip actual content to find next offset
985-
dcm_seekcur(&state, length, &position);
986-
if (!read_tag(&state, &tag, &position)) {
987-
dcm_error_set(error, DCM_ERROR_CODE_PARSE,
988-
"building BasicOffsetTable failed",
989-
"failed to read tag");
990-
return false;
991-
}
992-
if ( fragment_idx < num_frames ) {
993-
offsets[fragment_idx] = offsets[fragment_idx-1] + 8/*tag and length field size*/ + length;
994-
}
995-
fragment_idx++;
996-
}
997-
// fragment_idx shall equal to num_frames+1 at the end
998-
fragment_idx--;
999-
if ( fragment_idx > num_frames ) {
1000-
dcm_error_set(error, DCM_ERROR_CODE_INVALID,
1001-
"building BasicOffsetTable failed",
1002-
"Too many fragments" );
963+
for (int i = 1; i < num_frames; i++) {
964+
if (!read_tag(&state, &tag, &position) ||
965+
!read_uint32(&state, &length, &position)) {
1003966
return false;
1004967
}
1005968

1006-
if ( num_frames < fragment_idx ) {
1007-
dcm_error_set(error, DCM_ERROR_CODE_INVALID,
1008-
"building BasicOffsetTable failed",
1009-
"Too many frames" );
969+
if (tag == TAG_SQ_DELIM) {
970+
dcm_error_set(error, DCM_ERROR_CODE_PARSE,
971+
"reading BasicOffsetTable failed",
972+
"too few frames in PixelData");
1010973
return false;
1011974
}
1012-
1013-
if ( !read_uint32(&state, &length, &position ) || length != 0 ) {
975+
976+
if (tag != TAG_ITEM) {
1014977
dcm_error_set(error, DCM_ERROR_CODE_PARSE,
1015978
"building BasicOffsetTable failed",
1016-
"Sequence Delimiter Tag failure" );
979+
"frame Item #%d has wrong tag '%08x'",
980+
i + 1,
981+
tag);
982+
return false;
983+
}
984+
985+
// step back to the start of the item for this frame
986+
offsets[i] = position - 8;
987+
988+
// and seek forward over the value
989+
if (!dcm_seekcur(&state, length, &position)) {
1017990
return false;
1018991
}
1019992
}
@@ -1070,6 +1043,7 @@ char *dcm_parse_encapsulated_frame(DcmError **error,
10701043
*length = 0;
10711044
uint32_t tag;
10721045
uint32_t fragment_length = 0;
1046+
uint64_t frame_length = 0;
10731047

10741048
// first determine the total length of bytes to be read
10751049
while(position < frame_end_offset) {
@@ -1089,10 +1063,13 @@ char *dcm_parse_encapsulated_frame(DcmError **error,
10891063
return NULL;
10901064
}
10911065
dcm_seekcur(&state, fragment_length, &position);
1092-
*length += fragment_length;
1066+
frame_length += fragment_length;
1067+
}
1068+
if ( frame_length > 0xFFFFFFFF ) {
1069+
return NULL;
10931070
}
10941071

1095-
char *value = DCM_MALLOC(error, *length);
1072+
char *value = DCM_MALLOC(error, frame_length);
10961073
if (value == NULL) {
10971074
return NULL;
10981075
}
@@ -1115,6 +1092,6 @@ char *dcm_parse_encapsulated_frame(DcmError **error,
11151092
}
11161093
fragment += fragment_length;
11171094
}
1118-
1095+
*length = (uint32_t) frame_length;
11191096
return value;
11201097
}

0 commit comments

Comments
 (0)