Skip to content

Commit

Permalink
Detect some types of CSA corruption (#633)
Browse files Browse the repository at this point in the history
  • Loading branch information
neurolabusc committed Sep 9, 2022
1 parent 974eb45 commit f7f376a
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 8 deletions.
26 changes: 21 additions & 5 deletions console/nii_dicom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1398,6 +1398,10 @@ int readCSAImageHeader(unsigned char *buff, int lLength, struct TCSAdata *CSA, i
// Storage order is always little-endian, so byte-swap required values if necessary
if (!littleEndianPlatform())
nifti_swap_4bytes(1, &tagCSA.nitems);
if (tagCSA.nitems > 128) {
printError("%d n_tags CSA Image Header corrupted (0029,1010) see issue 633.\n", tagCSA.nitems);
return EXIT_FAILURE;
}
if (isVerbose > 1) //extreme verbosity: show every CSA tag
printMessage(" %d CSA of %s %d\n", lPos, tagCSA.name, tagCSA.nitems);
if (tagCSA.nitems > 0) {
Expand Down Expand Up @@ -5952,12 +5956,25 @@ const uint32_t kEffectiveTE = 0x0018 + (0x9082 << 16);
char iceStr[kDICOMStr];
dcmStr(lLength, &buffer[lPos], iceStr);
dcmStrDigitsOnly(iceStr);
char *end;
int echo = (int)strtol(iceStr, &end, 10);
char *end, *echoStr;
//read the first item ('X' or numeric if uncombined)
char c = iceStr[0];
if( c >= '0' && c <= '9' ){
int coilNumber = (int)strtol(iceStr, &end, 10);
//if ((iceStr != end) && (coilNumber > 0) && (strlen(d.coilName) < 1)) { //nb with uncombined coil will still have a name, e.g. 'HeadNeck_64'
if ((iceStr != end) && (coilNumber > 0)) {
sprintf(d.coilName, "%d", coilNumber);
//printf("issue631 coil name '%s'\n", d.coilName);
d.coilCrc = mz_crc32X((unsigned char *)&d.coilName, strlen(d.coilName));
}
}
//read the second item: the echo number ('4')
echoStr = strchr(iceStr, ' ');
int echo = (int)strtol(echoStr, &end, 10);
//printMessage("%d:%d:'%s'\n", d.echoNum, echo, iceStr);
if (iceStr != end)
d.echoNum = echo;
//printMessage("%d:'%s'\n", echo, iceStr);
//printMessage("%d:'%s'\n", echo, echoStr);
break;
}
case kPhaseEncodingDirectionPositiveSiemens: {
Expand Down Expand Up @@ -6730,15 +6747,14 @@ const uint32_t kEffectiveTE = 0x0018 + (0x9082 << 16);
case kCSAImageHeaderInfo:
if ((lPos + lLength) > fileLen)
break;
readCSAImageHeader(&buffer[lPos], lLength, &d.CSA, isVerbose, d.is3DAcq); //, dti4D);
readCSAImageHeader(&buffer[lPos], lLength, &d.CSA, isVerbose, d.is3DAcq);
if (!d.isHasPhase)
d.isHasPhase = d.CSA.isPhaseMap;
if ((d.CSA.coilNumber > 0) && (strlen(d.coilName) < 1)) {
sprintf(d.coilName, "%d", d.CSA.coilNumber);
//printf("issue631 coil name '%s'\n", d.coilName);
d.coilCrc = mz_crc32X((unsigned char *)&d.coilName, strlen(d.coilName));
}
//okra
break;
case kCSASeriesHeaderInfo:
if ((lPos + lLength) > fileLen)
Expand Down
2 changes: 1 addition & 1 deletion console/nii_dicom.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ extern "C" {
#define kCPUsuf " " //unknown CPU
#endif

#define kDCMdate "v1.0.20220903"
#define kDCMdate "v1.0.20220909"
#define kDCMvers kDCMdate " " kJP2suf kLSsuf kCCsuf kCPUsuf

static const int kMaxEPI3D = 1024; //maximum number of EPI images in Siemens Mosaic
Expand Down
12 changes: 10 additions & 2 deletions console/nii_dicom_batch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,10 @@ int phoenixOffsetCSASeriesHeader(unsigned char *buff, int lLength) {
memcpy(&tagCSA, &buff[lPos], sizeof(tagCSA)); //read tag
if (!littleEndianPlatform())
nifti_swap_4bytes(1, &tagCSA.nitems);
if (tagCSA.nitems > 128) {
printError("%d n_tags CSA Series Header corrupted (0029,1020 ) see issue 633.\n", tagCSA.nitems);
return EXIT_FAILURE;
}
//printf("%d CSA of %s %d\n",lPos, tagCSA.name, tagCSA.nitems);
lPos += sizeof(tagCSA);
if (strcmp(tagCSA.name, "MrPhoenixProtocol") == 0)
Expand Down Expand Up @@ -707,8 +711,14 @@ void siemensCsaAscii(const char *filename, TCsaAscii *csaAscii, int csaOffset, i
size_t result = fread(buffer, 1, csaLength, pFile);
if ((int)result != csaLength)
return;
fclose(pFile);

//next bit complicated: restrict to ASCII portion to avoid buffer overflow errors in BINARY portion
int startAscii = phoenixOffsetCSASeriesHeader((unsigned char *)buffer, csaLength);
if (startAscii == EXIT_FAILURE) {
free(buffer);
return;
}
int csaLengthTrim = csaLength;
char *bufferTrim = buffer;
if ((startAscii > 0) && (startAscii < csaLengthTrim)) { //ignore binary data at start
Expand Down Expand Up @@ -889,7 +899,6 @@ void siemensCsaAscii(const char *filename, TCsaAscii *csaAscii, int csaOffset, i
char keyStrSh7[] = "sGRADSPEC.alShimCurrent[4]";
shimSetting[7] = readKeyFloat(keyStrSh7, keyPos, csaLengthTrim);
}
fclose(pFile);
free(buffer);
return;
} // siemensCsaAscii()
Expand Down Expand Up @@ -1332,7 +1341,6 @@ tse3d: T2*/
if ((strstr(d.imageTypeText, "_ND") != NULL) || (strstr(d.imageType, "_ND") != NULL) ||
(strstr(d.imageTypeText, "_ND") != NULL) || (strstr(d.imageType, "_ND") != NULL))
fprintf(fp, "\t\"NonlinearGradientCorrection\": false,\n");

if (d.isDerived) //DICOM is derived image or non-spatial file (sounds, etc)
fprintf(fp, "\t\"RawImage\": false,\n");
if (d.seriesNum > 0)
Expand Down

0 comments on commit f7f376a

Please sign in to comment.