Skip to content

Commit c284690

Browse files
committed
fix validation of long strings
We were failing silently if string length validation failed. With this PR, issue a warning and let long strings though. Also, add a `-w` flag (show warnings) to `dcm-dump` and `dcm-getframe`. Thanks @arngaillard See #105
1 parent 5b4c6c0 commit c284690

7 files changed

Lines changed: 51 additions & 28 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
* fix one-byte overread into struct padding [bgilbert]
44
* support single-frame DICOM images and allow BitsStored > 8 [tokyovigilante]
5+
* fix error handling for string values over max length [arngaillard]
6+
* add `-w` (show warnings) to dcm-dump and dcm-getframe
57

68
## 1.2.0, 09/04/2025
79

doc/source/usage.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ using a standard C type (e.g,. VR ``"US"`` has type ``uint16_t`` and VR
5555
``"UI"`` has type ``char *``) and additional value constraints may be
5656
checked at runtime (e.g., the maximal capacity of a character string).
5757

58+
When reading DICOM files, a warning will be issued for character strings which
59+
are too long, but they will still be passed unmodified to the caller. Readers
60+
must not crash if strings are longer than the maximum value in the DICOM
61+
specification.
62+
5863
The VR must be appropriate for the tag. Use :c:func:`dcm_vr_from_tag()` to
5964
find the set of allowed VRs for a tag. Use :c:func:`dcm_is_valid_vr_for_tag()`
6065
to check if a VR is allowed for a tag.

src/dicom-data.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -340,14 +340,12 @@ bool dcm_element_get_value_string(DcmError **error,
340340
static bool element_check_capacity(DcmError **error,
341341
DcmElement *element, uint32_t capacity)
342342
{
343-
uint32_t i;
344-
345343
bool was_assigned = element->assigned;
346344

347345
// we have to turn on "assigned" for this func so we can read out values
348346
element->assigned = true;
349347

350-
for (i = 0; i < element->vm; i++) {
348+
for (uint32_t i = 0; i < element->vm; i++) {
351349
const char *value;
352350
if (!dcm_element_get_value_string(error, element, i, &value)) {
353351
element->assigned = was_assigned;
@@ -402,9 +400,9 @@ static bool dcm_element_validate(DcmError **error, DcmElement *element)
402400
if (vr_class == DCM_VR_CLASS_STRING_MULTI ||
403401
vr_class == DCM_VR_CLASS_STRING_SINGLE) {
404402
uint32_t capacity = dcm_dict_vr_capacity(element->vr);
405-
if (!element_check_capacity(error, element, capacity)) {
406-
return false;
407-
}
403+
404+
// this only checks and issues a warning, it does not set error
405+
(void) element_check_capacity(error, element, capacity);
408406
}
409407

410408
element->assigned = true;

tools/dcm-dump.1.in

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
dcm-dump \- print metadata content of DICOM PS3.10 file to standard output
55

66
.SH SYNOPSIS
7-
.BR "dcm-dump " [ -v "]
7+
.BR "dcm-dump " [ -hViw "]
88
.IR file
99

1010
.SH DESCRIPTION
1111
Print metadata content of DICOM PS3.10 file to standard output.
1212

1313
.SH OPTIONS
14+
1415
.TP
1516
.B -h
1617
Display help message (usage summary) and exit.
@@ -20,8 +21,12 @@ Display help message (usage summary) and exit.
2021
Display version and exit.
2122

2223
.TP
23-
.B -v
24-
Increase logging verbosity to INFO.
24+
.B -i
25+
Show info messages.
26+
27+
.TP
28+
.B -w
29+
Show warning messages.
2530

2631
.SH EXIT STATUS
2732
.B dcm-dump

tools/dcm-dump.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,39 @@
77
#include <dicom/dicom.h>
88

99

10-
static const char usage[] = "usage: dcm-dump [-v] [-V] [-h] FILE_PATH ...";
10+
static const char usage[] = "usage: dcm-dump [-hViw] FILE_PATH ...";
1111

1212

1313
int main(int argc, char *argv[])
1414
{
15-
int i, c;
16-
17-
while ((c = dcm_getopt(argc, argv, "h?Vv")) != -1) {
15+
int c;
16+
while ((c = dcm_getopt(argc, argv, "h?Vviw")) != -1) {
1817
switch (c) {
1918
case 'h':
2019
case '?':
2120
printf("%s\n", usage);
2221
return EXIT_SUCCESS;
2322

24-
case 'v':
23+
case 'V':
2524
printf("%s\n", dcm_get_version());
2625
return EXIT_SUCCESS;
2726

28-
case 'V':
27+
case 'v':
28+
case 'i':
2929
dcm_log_set_level(DCM_LOG_INFO);
3030
break;
3131

32+
case 'w':
33+
dcm_log_set_level(DCM_LOG_WARNING);
34+
break;
35+
3236
case '#':
3337
default:
3438
return EXIT_FAILURE;
3539
}
3640
}
3741

38-
for (i = dcm_optind; i < argc; i++) {
42+
for (int i = dcm_optind; i < argc; i++) {
3943
DcmError *error = NULL;
4044
DcmFilehandle *filehandle = NULL;
4145

@@ -45,8 +49,8 @@ int main(int argc, char *argv[])
4549
dcm_error_print(error);
4650
dcm_error_clear(&error);
4751
return EXIT_FAILURE;
48-
}
49-
52+
}
53+
5054
if (!dcm_filehandle_print(&error, filehandle)) {
5155
dcm_error_print(error);
5256
dcm_error_clear(&error);

tools/dcm-getframe.1.in

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,14 @@
44
dcm-getframe \- print a frame from a DICOM PS3.10 file to standard output
55

66
.SH SYNOPSIS
7-
.BR "dcm-getframe " [ -v "]
7+
.BR "dcm-getframe " [ -hViw "]
88
.IR file
99
.IR frame-number
1010

1111
.SH DESCRIPTION
1212
Print a frame from a DICOM PS3.10 file to standard output.
1313

1414
.SH OPTIONS
15-
.TP
16-
.B -o OUTPUT-FILENAME
17-
Write frame to OUTPUT-FILENAME. By default, the frame will be written to
18-
stdout.
1915

2016
.TP
2117
.B -h
@@ -26,8 +22,17 @@ Display help message (usage summary) and exit.
2622
Display version and exit.
2723

2824
.TP
29-
.B -v
30-
Increase logging verbosity to INFO.
25+
.B -o OUTPUT-FILENAME
26+
Write frame to OUTPUT-FILENAME. By default, the frame will be written to
27+
stdout.
28+
29+
.TP
30+
.B -i
31+
Show info messages.
32+
33+
.TP
34+
.B -w
35+
Show warning messages.
3136

3237
.SH EXIT STATUS
3338
.B dcm-getframe

tools/dcm-getframe.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,15 @@
1111

1212

1313
static const char usage[] = "usage: "
14-
"dcm-getframe [-v] [-V] [-h] [-o OUTPUT-FILE] FILE_PATH FRAME_NUMBER";
14+
"dcm-getframe [-hviw] [-o OUTPUT-FILE] FILE_PATH FRAME_NUMBER";
1515

1616

1717
int main(int argc, char *argv[])
1818
{
1919
char *output_file = NULL;
2020

2121
int c;
22-
23-
while ((c = dcm_getopt(argc, argv, "h?Vvo:")) != -1) {
22+
while ((c = dcm_getopt(argc, argv, "h?vViwo:")) != -1) {
2423
switch (c) {
2524
case 'h':
2625
case '?':
@@ -32,9 +31,14 @@ int main(int argc, char *argv[])
3231
return EXIT_SUCCESS;
3332

3433
case 'V':
34+
case 'i':
3535
dcm_log_set_level(DCM_LOG_INFO);
3636
break;
3737

38+
case 'w':
39+
dcm_log_set_level(DCM_LOG_WARNING);
40+
break;
41+
3842
case 'o':
3943
output_file = dcm_optarg;
4044
break;

0 commit comments

Comments
 (0)