Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

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

## 1.2.0, 09/04/2025

Expand Down
5 changes: 5 additions & 0 deletions doc/source/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ using a standard C type (e.g,. VR ``"US"`` has type ``uint16_t`` and VR
``"UI"`` has type ``char *``) and additional value constraints may be
checked at runtime (e.g., the maximal capacity of a character string).

When reading DICOM files, a warning will be issued for character strings which
are too long, but they will still be passed unmodified to the caller. Readers
must not crash if strings are longer than the maximum value in the DICOM
specification.

The VR must be appropriate for the tag. Use :c:func:`dcm_vr_from_tag()` to
find the set of allowed VRs for a tag. Use :c:func:`dcm_is_valid_vr_for_tag()`
to check if a VR is allowed for a tag.
Expand Down
10 changes: 4 additions & 6 deletions src/dicom-data.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,14 +340,12 @@ bool dcm_element_get_value_string(DcmError **error,
static bool element_check_capacity(DcmError **error,
DcmElement *element, uint32_t capacity)
{
uint32_t i;

bool was_assigned = element->assigned;

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

for (i = 0; i < element->vm; i++) {
for (uint32_t i = 0; i < element->vm; i++) {
const char *value;
if (!dcm_element_get_value_string(error, element, i, &value)) {
element->assigned = was_assigned;
Expand Down Expand Up @@ -402,9 +400,9 @@ static bool dcm_element_validate(DcmError **error, DcmElement *element)
if (vr_class == DCM_VR_CLASS_STRING_MULTI ||
vr_class == DCM_VR_CLASS_STRING_SINGLE) {
uint32_t capacity = dcm_dict_vr_capacity(element->vr);
if (!element_check_capacity(error, element, capacity)) {
return false;
}

// this only checks and issues a warning, it does not set error
(void) element_check_capacity(error, element, capacity);
}

element->assigned = true;
Expand Down
11 changes: 8 additions & 3 deletions tools/dcm-dump.1.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
dcm-dump \- print metadata content of DICOM PS3.10 file to standard output

.SH SYNOPSIS
.BR "dcm-dump " [ -v "]
.BR "dcm-dump " [ -hViw "]
.IR file

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

.SH OPTIONS

.TP
.B -h
Display help message (usage summary) and exit.
Expand All @@ -20,8 +21,12 @@ Display help message (usage summary) and exit.
Display version and exit.

.TP
.B -v
Increase logging verbosity to INFO.
.B -i
Show info messages.

.TP
.B -w
Show warning messages.

.SH EXIT STATUS
.B dcm-dump
Expand Down
22 changes: 13 additions & 9 deletions tools/dcm-dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,39 @@
#include <dicom/dicom.h>


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


int main(int argc, char *argv[])
{
int i, c;

while ((c = dcm_getopt(argc, argv, "h?Vv")) != -1) {
int c;
while ((c = dcm_getopt(argc, argv, "h?Vviw")) != -1) {
switch (c) {
case 'h':
case '?':
printf("%s\n", usage);
return EXIT_SUCCESS;

case 'v':
case 'V':
printf("%s\n", dcm_get_version());
return EXIT_SUCCESS;

case 'V':
case 'v':
case 'i':
dcm_log_set_level(DCM_LOG_INFO);
break;

case 'w':
dcm_log_set_level(DCM_LOG_WARNING);
break;

case '#':
default:
return EXIT_FAILURE;
}
}

for (i = dcm_optind; i < argc; i++) {
for (int i = dcm_optind; i < argc; i++) {
DcmError *error = NULL;
DcmFilehandle *filehandle = NULL;

Expand All @@ -45,8 +49,8 @@ int main(int argc, char *argv[])
dcm_error_print(error);
dcm_error_clear(&error);
return EXIT_FAILURE;
}
}

if (!dcm_filehandle_print(&error, filehandle)) {
dcm_error_print(error);
dcm_error_clear(&error);
Expand Down
19 changes: 12 additions & 7 deletions tools/dcm-getframe.1.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,14 @@
dcm-getframe \- print a frame from a DICOM PS3.10 file to standard output

.SH SYNOPSIS
.BR "dcm-getframe " [ -v "]
.BR "dcm-getframe " [ -hViw "]
.IR file
.IR frame-number

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

.SH OPTIONS
.TP
.B -o OUTPUT-FILENAME
Write frame to OUTPUT-FILENAME. By default, the frame will be written to
stdout.

.TP
.B -h
Expand All @@ -26,8 +22,17 @@ Display help message (usage summary) and exit.
Display version and exit.

.TP
.B -v
Increase logging verbosity to INFO.
.B -o OUTPUT-FILENAME
Write frame to OUTPUT-FILENAME. By default, the frame will be written to
stdout.

.TP
.B -i
Show info messages.

.TP
.B -w
Show warning messages.

.SH EXIT STATUS
.B dcm-getframe
Expand Down
10 changes: 7 additions & 3 deletions tools/dcm-getframe.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,15 @@


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


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

int c;

while ((c = dcm_getopt(argc, argv, "h?Vvo:")) != -1) {
while ((c = dcm_getopt(argc, argv, "h?vViwo:")) != -1) {
switch (c) {
case 'h':
case '?':
Expand All @@ -32,9 +31,14 @@ int main(int argc, char *argv[])
return EXIT_SUCCESS;

case 'V':
case 'i':
dcm_log_set_level(DCM_LOG_INFO);
break;

case 'w':
dcm_log_set_level(DCM_LOG_WARNING);
break;

case 'o':
output_file = dcm_optarg;
break;
Expand Down